diff --git a/opencv/cv.go b/opencv/cv.go index ea9eb7d..4d20598 100644 --- a/opencv/cv.go +++ b/opencv/cv.go @@ -18,8 +18,9 @@ func init() { } const ( - CV_BGR2GRAY = C.CV_BGR2GRAY - CV_BGR2BGRA = C.CV_BGR2BGRA + CV_BGR2GRAY = C.CV_BGR2GRAY + CV_BGR2BGRA = C.CV_BGR2BGRA + CV_RGBA2BGRA = C.CV_RGBA2BGRA CV_BLUR = C.CV_BLUR diff --git a/opencv/cxcore.go b/opencv/cxcore.go index 0e5c622..b2b335a 100644 --- a/opencv/cxcore.go +++ b/opencv/cxcore.go @@ -57,6 +57,11 @@ func CreateImage(w, h, depth, channels int) *IplImage { return (*IplImage)(img) } +/* SetData assigns user data to the image header */ +func (img *IplImage) SetData(data unsafe.Pointer, step int) { + C.cvSetData(unsafe.Pointer(img), data, C.int(step)) +} + /* Releases (i.e. deallocates) IPL image header */ func (img *IplImage) ReleaseHeader() { img_c := (*C.IplImage)(img) diff --git a/opencv/goimage.go b/opencv/goimage.go index 15804db..34c74e2 100644 --- a/opencv/goimage.go +++ b/opencv/goimage.go @@ -14,7 +14,7 @@ func DecodeImageMem(data []byte) *IplImage { return DecodeImage(unsafe.Pointer(buf), CV_LOAD_IMAGE_UNCHANGED) } -/* From Image converts a go image.Image to an opencv.IplImage. */ +/* FromImage converts a go image.Image to an opencv.IplImage. */ func FromImage(img image.Image) *IplImage { b := img.Bounds() model := color.RGBAModel @@ -36,6 +36,26 @@ func FromImage(img image.Image) *IplImage { return dst } +/* FromImageUnsafe create an opencv.IplImage that shares the buffer with the +go image.RGBA image. All changes made from opencv might affect go! */ +func FromImageUnsafe(img *image.RGBA) *IplImage { + b := img.Bounds() + buf := CreateImageHeader( + b.Max.X-b.Min.X, + b.Max.Y-b.Min.Y, + IPL_DEPTH_8U, 4) + dst := CreateImage( + b.Max.X-b.Min.X, + b.Max.Y-b.Min.Y, + IPL_DEPTH_8U, 4) + + buf.SetData(unsafe.Pointer(&img.Pix[0]), CV_AUTOSTEP) + CvtColor(buf, dst, CV_RGBA2BGRA) + buf.Release() + + return dst +} + /* ToImage converts a opencv.IplImage to an go image.Image */ func (img *IplImage) ToImage() image.Image { out := image.NewNRGBA(image.Rect(0, 0, img.Width(), img.Height())) diff --git a/opencv/goimage_test.go b/opencv/goimage_test.go new file mode 100644 index 0000000..e0bc3b5 --- /dev/null +++ b/opencv/goimage_test.go @@ -0,0 +1,96 @@ +package opencv + +import ( + "image" + _ "image/jpeg" + _ "image/png" + "os" + "reflect" + "testing" +) + +func TestFromImage(t *testing.T) { + fh, err := os.Open("../images/pic5.png") + if err != nil { + t.Fatal(err) + } + + img, _, err := image.Decode(fh) + if err != nil { + t.Fatal(err) + } + + ocv := FromImage(img) + if ocv == nil { + t.Fatal("failed to convert image") + } + + width := img.Bounds().Max.X - img.Bounds().Min.X + height := img.Bounds().Max.Y - img.Bounds().Min.Y + if ocv.Width() != width || ocv.Height() != height { + t.Fatalf("loaded image has wrong dimensions: got %dx%d, expected %dx%d", ocv.Width(), ocv.Height(), width, height) + } + + ex := [4]float64{98, 139, 26, 255} + px := ocv.Get2D(50, 90).Val() + if !reflect.DeepEqual(px, ex) { + t.Fatalf("wrong color @50,90: got %v, expected %v", px, ex) + } +} + +func TestFromImageUnsafe(t *testing.T) { + fh, err := os.Open("../images/pic5.png") + if err != nil { + t.Fatal(err) + } + + img, _, err := image.Decode(fh) + if err != nil { + t.Fatal(err) + } + + rgba, ok := img.(*image.RGBA) + if !ok { + t.Fatal("image is no RGBA image") + } + + ocv := FromImageUnsafe(rgba) + if ocv == nil { + t.Fatal("failed to convert image") + } + + width := img.Bounds().Max.X - img.Bounds().Min.X + height := img.Bounds().Max.Y - img.Bounds().Min.Y + if ocv.Width() != width || ocv.Height() != height { + t.Fatalf("loaded image has wrong dimensions: got %dx%d, expected %dx%d", ocv.Width(), ocv.Height(), width, height) + } + + ex := [4]float64{98, 139, 26, 255} + px := ocv.Get2D(50, 90).Val() + if !reflect.DeepEqual(px, ex) { + t.Fatalf("wrong color @50,90: got %v, expected %v", px, ex) + } +} + +func BenchmarkFromImage(b *testing.B) { + fh, _ := os.Open("../images/pic5.png") + img, _, _ := image.Decode(fh) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + ocv := FromImage(img) + ocv.Release() + } +} + +func BenchmarkFromImageUnsafe(b *testing.B) { + fh, _ := os.Open("../images/pic5.png") + img, _, _ := image.Decode(fh) + b.ResetTimer() + + for i := 0; i < b.N; i++ { + rgba := img.(*image.RGBA) + ocv := FromImageUnsafe(rgba) + ocv.Release() + } +}