- Notifications
You must be signed in to change notification settings - Fork5
fast, high peformance image processing library for golang
License
octu0/blurry
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
fast, high peformance image processing libary.
blurry
provides image processing algorithms withhalide-lang backend.
implements optimized processor for amd64 CPUs on Linux/macos
This is the result of using halide'sbenchamrk.
darwin/amd64 Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
src 320x240BenchmarkJIT/cloneimg : 0.00788msBenchmarkJIT/convert_from_argb : 0.02375msBenchmarkJIT/convert_from_abgr : 0.03884msBenchmarkJIT/convert_from_bgra : 0.02470msBenchmarkJIT/convert_from_rabg : 0.03655msBenchmarkJIT/convert_from_yuv_420 : 0.03168msBenchmarkJIT/convert_from_yuv_444 : 0.02686msBenchmarkJIT/convert_to_yuv_420 : 0.06742msBenchmarkJIT/convert_to_yuv_444 : 0.07209msBenchmarkJIT/rotate0 : 0.00774msBenchmarkJIT/rotate90 : 0.02599msBenchmarkJIT/rotate180 : 0.00802msBenchmarkJIT/rotate270 : 0.02582msBenchmarkJIT/crop : 0.06126msBenchmarkJIT/scale : 0.13889msBenchmarkJIT/scale_box : 0.20598msBenchmarkJIT/scale_linear : 0.20440msBenchmarkJIT/scale_gaussian : 0.31444msBenchmarkJIT/blend_normal : 0.08443msBenchmarkJIT/blend_sub : 0.08398msBenchmarkJIT/blend_add : 0.08364msBenchmarkJIT/blend_diff : 0.08453msBenchmarkJIT/grayscale : 0.03687msBenchmarkJIT/invert : 0.03730msBenchmarkJIT/brightness : 0.04703msBenchmarkJIT/gammacorrection : 0.08013msBenchmarkJIT/contrast : 0.01549msBenchmarkJIT/boxblur : 0.11211msBenchmarkJIT/gaussianblur : 0.33058msBenchmarkJIT/blockmozaic : 0.27455msBenchmarkJIT/erosion : 0.11934msBenchmarkJIT/dilation : 0.12013msBenchmarkJIT/morphology_open : 0.10370msBenchmarkJIT/morphology_close : 0.10435msBenchmarkJIT/morphology_gradient : 0.07684msBenchmarkJIT/emboss : 0.04402msBenchmarkJIT/laplacian : 0.03192msBenchmarkJIT/highpass : 0.03847msBenchmarkJIT/gradient : 0.03322msBenchmarkJIT/edgedetect : 0.02705msBenchmarkJIT/sobel : 0.06276msBenchmarkJIT/canny : 0.29922msBenchmarkJIT/canny_dilate : 0.35114msBenchmarkJIT/canny_morphology_open : 0.44488msBenchmarkJIT/canny_morphology_close : 0.40522msBenchmarkJIT/match_template_sad : 5.75482msBenchmarkJIT/match_template_ssd : 4.48363msBenchmarkJIT/match_template_ncc : 8.32420msBenchmarkJIT/prepared_match_template_ncc : 6.22423msBenchmarkJIT/match_template_zncc : 12.73780msBenchmarkJIT/prepared_match_template_zncc : 11.38906msBenchmarkJIT/pcm16_decibel : 0.00257ms
Calling a library compiled by AOT(ahead-of-time) via cgo.
Incgo, 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
isDisablePool, i.e. the benchmark when BufferPool is off.
goos: darwingoarch: amd64pkg: github.com/octu0/blurry/benchmarkcpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHzBenchmarkBlurBenchmarkBlur/bild/blur/BoxBenchmarkBlur/bild/blur/Box-8 154 7812824 ns/op 640402 B/op 11 allocs/opBenchmarkBlur/bild/blur/GaussianBenchmarkBlur/bild/blur/Gaussian-8 333 3486751 ns/op 1262485 B/op 21 allocs/opBenchmarkBlur/imaging/BlurBenchmarkBlur/imaging/Blur-8 786 1520193 ns/op 793698 B/op 45 allocs/opBenchmarkBlur/stackblur-goBenchmarkBlur/stackblur-go-8 231 5147219 ns/op 925937 B/op 153609 allocs/opBenchmarkBlur/libyuv/ARGBBlurBenchmarkBlur/libyuv/ARGBBlur-8 1861 642486 ns/op10182722 B/op 3 allocs/opBenchmarkBlur/blurry/BoxblurBenchmarkBlur/blurry/Boxblur-8 7257 178086 ns/op 88 B/op 2 allocs/opBenchmarkBlur/blurry/GaussianblurBenchmarkBlur/blurry/Gaussianblur-8 5367 222615 ns/op 146 B/op 2 allocs/opBenchmarkBlur/blurry/Boxblur/DBenchmarkBlur/blurry/Boxblur/D-8 6093 201573 ns/op 311361 B/op 2 allocs/opBenchmarkBlur/blurry/Gaussianblur/DBenchmarkBlur/blurry/Gaussianblur/D-8 4629 257483 ns/op 311361 B/op 2 allocs/op
goos: darwingoarch: amd64pkg: github.com/octu0/blurry/benchmarkcpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHzBenchmarkEdgeBenchmarkEdge/bild/EdgeDetectionBenchmarkEdge/bild/EdgeDetection-8 643 1858350 ns/op 631257 B/op 10 allocs/opBenchmarkEdge/blurry/EdgeBenchmarkEdge/blurry/Edge-8 10000 100695 ns/op 311513 B/op 3 allocs/op
goos: darwingoarch: amd64pkg: github.com/octu0/blurry/benchmarkcpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHzBenchmarkRotateBenchmarkRotate/bild/Rotate/90BenchmarkRotate/bild/Rotate/90-8 612 2080543 ns/op 1237046 B/op 115685 allocs/opBenchmarkRotate/bild/Rotate/180BenchmarkRotate/bild/Rotate/180-8 480 2355424 ns/op 1540311 B/op 153605 allocs/opBenchmarkRotate/bild/Rotate/270BenchmarkRotate/bild/Rotate/270-8 520 2061518 ns/op 1236932 B/op 115685 allocs/opBenchmarkRotate/imaging/90BenchmarkRotate/imaging/90-8 7918 130736 ns/op 314181 B/op 6 allocs/opBenchmarkRotate/imaging/180BenchmarkRotate/imaging/180-8 9654 138252 ns/op 313542 B/op 6 allocs/opBenchmarkRotate/imaging/270BenchmarkRotate/imaging/270-8 6972 163349 ns/op 314165 B/op 6 allocs/opBenchmarkRotate/libyuv/ARGBRotate/90BenchmarkRotate/libyuv/ARGBRotate/90-8 13423 81131 ns/op 311360 B/op 2 allocs/opBenchmarkRotate/libyuv/ARGBRotate/180BenchmarkRotate/libyuv/ARGBRotate/180-8 34771 34425 ns/op 311361 B/op 2 allocs/opBenchmarkRotate/libyuv/ARGBRotate/270BenchmarkRotate/libyuv/ARGBRotate/270-8 15904 78290 ns/op 311361 B/op 2 allocs/opBenchmarkRotate/blurry/Rotate/90BenchmarkRotate/blurry/Rotate/90-8 10000 109336 ns/op 311514 B/op 3 allocs/opBenchmarkRotate/blurry/Rotate/180BenchmarkRotate/blurry/Rotate/180-8 13102 89067 ns/op 311514 B/op 3 allocs/opBenchmarkRotate/blurry/Rotate/270BenchmarkRotate/blurry/Rotate/270-8 10000 124949 ns/op 311514 B/op 3 allocs/op
goos: darwingoarch: amd64pkg: github.com/octu0/blurry/benchmarkcpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHzBenchmarkSobelBenchmarkSobel/bild/SobelBenchmarkSobel/bild/Sobel-8 208 5707148 ns/op 2196784 B/op 32 allocs/opBenchmarkSobel/libyuv/ARGBSobelBenchmarkSobel/libyuv/ARGBSobel-8 16557 72320 ns/op 311361 B/op 2 allocs/opBenchmarkSobel/blurry/SobelBenchmarkSobel/blurry/Sobel-8 9255 140586 ns/op 311515 B/op 3 allocs/op
See_benchmark for benchmarks of other methods and performance comparison withlibyuv.
$ 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 | ![]() |
flipV(vertically) flipH(horizontally)
img,err:=blurry.Flip(input,blurry.FlipVertical)
blurry.FlipMode | Result |
---|---|
blurry.FlipVertical | ![]() |
blurry.FlipHorizon | ![]() |
crop x,y with crop_width,crop_height
img,err:=blurry.Crop(input,image.Pt(175,40),crop_width,crop_height)
original | x=175,y=40,cw=80,ch=50 |
---|---|
![]() | ![]() |
a.k.a. Resize resampling
img,err:=blurry.Scale(input,scale_width,scale_height,blurry.ScaleFilterNone)
blurry.ScaleFilter | Result |
---|---|
blurry.ScaleFilterNone | ![]() |
blurry.ScaleFilterBox | ![]() |
blurry.ScaleFilterLinear | ![]() |
blurry.ScaleFilterGaussian | ![]() |
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:=5N:=2img,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.CannyMorphologyClosemorph_size:=5dilate_size:=3img,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), NCC(Normalized Cross Correlation) AND ZNCC(Zero means 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)iferr!=nil {panic(err)}deferblurry.FreePreparedNCCTemplate(p)for_,img:=rangeimages {scores,err:=blurry.PreparedMatchTemplateNCC(img,p,0.1)iferr!=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)iferr!=nil {panic(err)}deferblurry.FreePreparedZNCCTemplate(p)for_,img:=rangeimages {scores,err:=blurry.PreparedMatchTemplateZNCC(img,p,0.1)iferr!=nil {panic(err) }}
Extract contours based on the sobel filter for binarization.
In actual use, it is better to denoise the image before passing it through the sobel filter.
points,err:=blurry.Contour(input,100,4)
threshold | size | Result |
---|---|---|
100 | 4 | ![]() |
150 | 4 | ![]() |
200 | 4 | ![]() |
250 | 4 | ![]() |
100 | 2 | ![]() |
200 | 2 | ![]() |
Blend input1 on input0.
img,err:=blurry.Blend(input0,input1,image.Pt(76,36),blurry.BlendNormal)
blurry.BlendMode | Result |
---|---|
blurry.BlendNormal | ![]() |
blurry.BlendSub | ![]() |
blurry.BlendAdd | ![]() |
blurry.BlendDiff | ![]() |
blurry supports reading ARGB, ABGR, BGRA, YUV420 and YUV444.
It also supports YUV444 output.
img,err:=blurry.ConvertFromARGB(input)
ColorModel | Method |
---|---|
ARGB | blurry.ConvertFromARGB(*image.RGBA) |
ABGR | blurry.ConvertFromABGR(*image.RGBA) |
BGRA | blurry.ConvertFromBGRA(*image.RGBA) |
RABG | blurry.ConvertFromRABG(*image.RGBA) |
img,err:=blurry.ConvertFromYUV420(ycbcr)
Subsampling | Method |
---|---|
420 | blurry.ConvertFromYUV420(*image.YCbCr) |
444 | blurry.ConvertFromYUV444(*image.YCbCr) |
or byte slice can also be specified
vary,u,v []bytevarstrideY,strideU,strideVintvarwidth,heightintimg,err:=blurry.ConvertFromYUV420Plane(y,u,v,strideY,strideU,strideV,width,height)
Subsampling | Method |
---|---|
420 | blurry.ConvertFromYUV420Plane(y,u,v []byte, int,int,int, w,h int) |
444 | blurry.ConvertFromYUV444Plane(y,u,v []byte, int,int,int, w,h int) |
ycbcr,err:=blurry.ConvertToYUV444(rgba)
Subsampling | Method |
---|---|
420 | blurry.ConvertToYUV420(*image.RGBA) |
444 | blurry.ConvertToYUV444(*image.RGBA) |
Gets the decibel of given PCM16.
vardata []bytedecibel,err:=blurry.PCM16Decibel(data,length)orvarinput []int16decibel,err:=blurry.PCM16DecibelFromInt16(input)
Run it via docker.
Usedocker 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: blurryUSAGE: blurry [global options] command [command options] [arguments...]VERSION: 1.20.1COMMANDS: blend blockmozaic boxblur brightness canny clone contour contrast convert convert_from_yuv convert_to_yuv crop dilation edge emboss erosion flip gamma gaussianblur gradient grayscale highpass invert laplacian morphology match_template pcm16 rotate scale sobel help, h Shows a list of commands or help for one commandGLOBAL OPTIONS: --debug, -d debug mode --verbose, -V verbose. more message --help, -h show help --version, -v print the version
When building, create a docker container with Halide(clang, llvm, etc).installed as the build environment.
$ make build-generator
Compilelibruntime.a
and all kindslib*_osx.a
orlib*_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.
About
fast, high peformance image processing library for golang