fast, high peformance image processing libary.
blurry
provides image processing algorithms with halide-lang backend.
implements optimized processor for amd64 CPUs on Linux/macos
$ go get github.com/octu0/blurry
original image
rotation 0/90/180/270 clockwise
img, err := blurry.Rotate(input, blurry.Rotate90)
blurry.RotationMode |
Result |
---|---|
blurry.Rotate90 |
|
blurry.Rotate180 |
|
blurry.Rotate270 |
img, err := blurry.Grayscale(input)
img, err := blurry.Invert(input)
img, err := blurry.Brightness(input, 1.5)
img, err := blurry.Gamma(input, 2.5)
img, err := blurry.Contrast(input, 0.525)
img, err := blurry.Boxblur(input, 11)
img, err := blurry.Gaussianblur(input, 5.0)
img, err := blurry.Blockmozaic(input, 10)
img, err := blurry.Erosion(input, 5)
img, err := blurry.Dilation(input, 8)
Morphology repeats Erode and Dilate N times.
size := 5
N := 2
img, err := blurry.Morphology(input, MorphOpen, size, N)
blurry.MorphologyMode |
Result |
---|---|
blurry.MorphologyOpen |
|
blurry.MorphologyClose |
|
blurry.MorphologyGradient |
img, err := blurry.Emboss(input)
img, err := blurry.Highpass(input)
img, err := blurry.Laplacian(input)
img, err := blurry.Gradient(input)
a.k.a. Edge Detection
img, err := blurry.Edge(input)
img, err := blurry.Sobel(input)
a.k.a. Canny Edge Detection
img, err := blurry.Canny(input, 250, 100)
max:250 min:100 |
max:400 min:10 |
---|---|
img, err := blurry.CannyWithDilate(input, 250, 100, 3)
max:250 min:100 dilate:3 |
max:250 min:150 dilate:4 |
---|---|
Pre-process morphology before applying Canny process.
mode := blurry.CannyMorphologyClose
morph_size := 5
dilate_size := 3
img, err := blurry.MorphologyCannyWithDilate(input, 250, 100, mode, morph_size, dilate_size);
blurry.CannyMorphologyMode |
Result |
---|---|
blurry.CannyMorphologyOpen |
|
blurry.CannyMorphologyClose |
SAD(Sum of Absolute Difference), SSD(Sum of Squared Difference) AND NCC(Normalized Cross Correlation) methods are available for template matching.
scores, err := blurry.MatchTemplateSAD(input, template, 1000)
filter | input | template | Result |
---|---|---|---|
none |
|||
grayscale |
|||
sobel |
|||
canny dilate:3 morph:open |
scores, err := blurry.MatchTemplateSSD(input, template, 1000)
filter | input | template | Result |
---|---|---|---|
none |
|||
grayscale |
|||
sobel |
|||
canny dilate:3 morph:open |
scores, err := blurry.MatchTemplateNCC(input, template, 0.1)
filter | input | template | Result |
---|---|---|---|
none |
|||
grayscale |
|||
sobel |
|||
canny dilate:3 morph:open |
Improve processing speed by pre-calculating part of NCC process.
p, err := blurry.PrepareNCCTemplate(template)
if err != nil {
panic(err)
}
defer blurry.FreePreparedNCCTemplate(p)
for _, img := range images {
scores, err := blurry.PreparedMatchTemplateNCC(img, p, 0.1)
if err != nil {
panic(err)
}
}
scores, err := blurry.MatchTemplateZNCC(input, template, 0.1)
filter | input | template | Result |
---|---|---|---|
none |
|||
grayscale |
|||
sobel |
|||
canny dilate:3 morph:open |
Improve processing speed by pre-calculating part of ZNCC process.
p, err := blurry.PrepareZNCCTemplate(template)
if err != nil {
panic(err)
}
defer blurry.FreePreparedZNCCTemplate(p)
for _, img := range images {
scores, err := blurry.PreparedMatchTemplateZNCC(img, p, 0.1)
if err != nil {
panic(err)
}
}
Run it via docker.
Use docker run -v
to specify where to load the images and where to output them (/tmp
will be used as a temporary file).
$ mkdir myimagedir
$ mkdir myimageout
$ cp /from/img/path.png myimagedir/src.png
# grayscale
$ docker run --rm -it \
-v $PWD/myimagedir:/img \
-v $PWD/myimageout:/tmp \
blurry:1.0.0 grayscale -i /img/src.png
NAME:
blurry
USAGE:
blurry [global options] command [command options] [arguments...]
VERSION:
1.15.0
COMMANDS:
blockmozaic
boxblur
brightness
canny
clone
contrast
dilation
edge
emboss
erosion
gamma
gaussianblur
gradient
grayscale
highpass
invert
laplacian
morphology
match_template
rotate
sobel
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--debug, -d debug mode
--verbose, -V verbose. more message
--help, -h show help
--version, -v print the version
This is the result of using halide's benchamrk.
darwin/amd64 Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
src 320x240
BenchmarkJIT/cloneimg : 0.01952ms
BenchmarkJIT/rotate0 : 0.01952ms
BenchmarkJIT/rotate90 : 0.08169ms
BenchmarkJIT/rotate180 : 0.02266ms
BenchmarkJIT/rotate270 : 0.09420ms
BenchmarkJIT/grayscale : 0.08012ms
BenchmarkJIT/invert : 0.06201ms
BenchmarkJIT/brightness : 0.06828ms
BenchmarkJIT/gammacorrection : 0.11261ms
BenchmarkJIT/contrast : 0.06815ms
BenchmarkJIT/boxblur : 0.18756ms
BenchmarkJIT/gaussianblur : 0.16728ms
BenchmarkJIT/blockmozaic : 0.31110ms
BenchmarkJIT/erosion : 0.10399ms
BenchmarkJIT/dilation : 0.09312ms
BenchmarkJIT/morphology_open : 0.13103ms
BenchmarkJIT/morphology_close : 0.12874ms
BenchmarkJIT/morphology_gradient : 0.07516ms
BenchmarkJIT/emboss$1 : 0.15934ms
BenchmarkJIT/laplacian : 0.13013ms
BenchmarkJIT/highpass : 0.13032ms
BenchmarkJIT/gradient : 0.12489ms
BenchmarkJIT/edge : 0.10574ms
BenchmarkJIT/sobel : 0.11102ms
BenchmarkJIT/canny : 0.59503ms
BenchmarkJIT/canny_dilate : 0.62175ms
BenchmarkJIT/canny_morphology_open : 0.72361ms
BenchmarkJIT/canny_morphology_close : 0.70342ms
BenchmarkJIT/match_template_sad : 5.26705ms
BenchmarkJIT/match_template_ssd : 4.14713ms
BenchmarkJIT/match_template_ncc : 8.03261ms
BenchmarkJIT/prepared_match_template_ncc : 5.83674ms
BenchmarkJIT/match_template_zncc : 11.69895ms
BenchmarkJIT/prepared_match_template_zncc : 10.88168ms
Calling a library compiled by AOT(ahead-of-time) via cgo.
In cgo, due to the overhead of ffi calls(e.g.),
more complex operations will be optimized for CPU and become faster.
Also, the execution speed may be reduced by the overhead of multiple calls.
/D is DisablePool, i.e. the benchmark when BufferPool is off.
goos: darwin
goarch: amd64
pkg: github.com/octu0/blurry
cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
BenchmarkBlur
BenchmarkBlur/bild/blur/Box
BenchmarkBlur/bild/blur/Box-8 150 7792666 ns/op 640322 B/op 11 allocs/op
BenchmarkBlur/bild/blur/Gaussian
BenchmarkBlur/bild/blur/Gaussian-8 338 3317723 ns/op 1262513 B/op 21 allocs/op
BenchmarkBlur/imaging/Blur
BenchmarkBlur/imaging/Blur-8 801 1482781 ns/op 793696 B/op 45 allocs/op
BenchmarkBlur/stackblur-go
BenchmarkBlur/stackblur-go-8 242 4989647 ns/op 925932 B/op 153609 allocs/op
BenchmarkBlur/libyuv/ARGBBlur
BenchmarkBlur/libyuv/ARGBBlur-8 1843 638517 ns/op 10182723 B/op 3 allocs/op
BenchmarkBlur/blurry/Boxblur
BenchmarkBlur/blurry/Boxblur-8 3666 355664 ns/op 173 B/op 2 allocs/op
BenchmarkBlur/blurry/Gaussianblur
BenchmarkBlur/blurry/Gaussianblur-8 5731 216902 ns/op 142 B/op 2 allocs/op
BenchmarkBlur/blurry/Boxblur/D
BenchmarkBlur/blurry/Boxblur/D-8 3114 367782 ns/op 311361 B/op 2 allocs/op
BenchmarkBlur/blurry/Gaussianblur/D
BenchmarkBlur/blurry/Gaussianblur/D-8 5107 235022 ns/op 311361 B/op 2 allocs/op
goos: darwin
goarch: amd64
pkg: github.com/octu0/blurry
cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
BenchmarkEdge
BenchmarkEdge/bild/EdgeDetection
BenchmarkEdge/bild/EdgeDetection-8 679 1794476 ns/op 631299 B/op 10 allocs/op
BenchmarkEdge/blurry/Edge
BenchmarkEdge/blurry/Edge-8 9400 129556 ns/op 311479 B/op 3 allocs/op
BenchmarkSobel
BenchmarkSobel/bild/Sobel
BenchmarkSobel/bild/Sobel-8 202 5693435 ns/op 2196801 B/op 32 allocs/op
BenchmarkSobel/blurry/Sobel
BenchmarkSobel/blurry/Sobel-8 5522 220248 ns/op 311479 B/op 3 allocs/op
See benchmark for benchmarks of other methods and performance comparison with libyuv.
When building, create a docker container with Halide(clang, llvm, etc). installed as the build environment.
$ make build-generator
Compile libruntime.a
and all kinds lib*_osx.a
or lib*_linu.a
to make static link.
$ make generate
Finally, generate a docker image if necessary.
$ make build
Set up configuration for macos to be able to run image filtering directly through Halide.
$ make setup-halide-runtime
genrun
package allows you to export images to temporary file and run image filtering directly.
$ go run cmd/genrun/main.go benchmark
MIT, see LICENSE file for details.