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 |
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.13.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.01862ms
BenchmarkJIT/rotate0 : 0.01951ms
BenchmarkJIT/rotate90 : 0.08718ms
BenchmarkJIT/rotate180 : 0.02239ms
BenchmarkJIT/rotate270 : 0.08980ms
BenchmarkJIT/grayscale : 0.08124ms
BenchmarkJIT/invert : 0.06432ms
BenchmarkJIT/brightness : 0.06673ms
BenchmarkJIT/gammacorrection : 0.10340ms
BenchmarkJIT/contrast : 0.06726ms
BenchmarkJIT/boxblur : 0.18134ms
BenchmarkJIT/gaussianblur : 0.16342ms
BenchmarkJIT/blockmozaic : 0.31450ms
BenchmarkJIT/erosion : 0.09010ms
BenchmarkJIT/dilation : 0.09402ms
BenchmarkJIT/morphology_open : 0.08982ms
BenchmarkJIT/morphology_close : 0.09786ms
BenchmarkJIT/morphology_gradient : 0.09497ms
BenchmarkJIT/emboss$1 : 0.16786ms
BenchmarkJIT/laplacian : 0.13665ms
BenchmarkJIT/highpass : 0.14077ms
BenchmarkJIT/gradient : 0.14108ms
BenchmarkJIT/edge : 0.10536ms
BenchmarkJIT/sobel : 0.10951ms
BenchmarkJIT/canny : 0.60258ms
BenchmarkJIT/canny_dilate : 0.63061ms
BenchmarkJIT/canny_morphology_open : 0.69504ms
BenchmarkJIT/canny_morphology_close : 0.69271ms
BenchmarkJIT/match_template_sad : 5.34206ms
BenchmarkJIT/match_template_ssd : 4.17693ms
BenchmarkJIT/match_template_ncc : 7.84047ms
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.