gocv icon indicating copy to clipboard operation
gocv copied to clipboard

image.YCbCr to Mat

Open cedricve opened this issue 4 years ago • 2 comments

What is the best way to convert a image.YCbCr to gocv.Mat?

cedricve avatar Apr 24 '20 20:04 cedricve

Hello @cedricve you would need to add another wrapper function to GoCV such as ImageToMatYCbCr() that is similar to the existing ImageToMatRGBA() function:

https://github.com/hybridgroup/gocv/blob/master/core.go#L801

deadprogram avatar Apr 25 '20 06:04 deadprogram

Hello! I am using this code in my project.

func ImageToMatRGB(img image.Image) (gocv.Mat, error) {
	bounds := img.Bounds()
	x := bounds.Dx()
	y := bounds.Dy()
	var data []uint8
	switch img.ColorModel() {
	case color.RGBAModel:
		m, res := img.(*image.RGBA)
		if true != res {
			return gocv.NewMat(), errors.New("Image color format error")
		}
		data = m.Pix

	case color.NRGBAModel:
		m, res := img.(*image.NRGBA)
		if !res {
			return gocv.NewMat(), errors.New("Image color format error")
		}
		data = m.Pix

	case color.YCbCrModel:

		im := img.(*image.YCbCr)

		data := make([]byte, 0, x*y*3)
		for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
			for i := bounds.Min.X; i < bounds.Max.X; i++ {
				r, g, b, _ := im.YCbCrAt(i, j).RGBA()
				data = append(data, byte(b>>8), byte(g>>8), byte(r>>8))

			}
		}
		return gocv.NewMatFromBytes(y, x, gocv.MatTypeCV8UC3, data)

	default:
		data := make([]byte, 0, x*y*3)
		for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
			for i := bounds.Min.X; i < bounds.Max.X; i++ {
				r, g, b, _ := img.At(i, j).RGBA()
				data = append(data, byte(b>>8), byte(g>>8), byte(r>>8))
			}
		}
		return gocv.NewMatFromBytes(y, x, gocv.MatTypeCV8UC3, data)
	}

	// speed up the conversion process of RGBA format
	src, err := gocv.NewMatFromBytes(y, x, gocv.MatTypeCV8UC4, data)
	if err != nil {
		return gocv.NewMat(), err
	}
	defer src.Close()

	dst := gocv.NewMat()
	gocv.CvtColor(src, &dst, gocv.ColorRGBAToBGR)
	return dst, nil
}

Method At in case img.At(i, j).RGBA() is very slow and creates too many allocs, so i replaced it with im.YCbCrAt(i, j).RGBA() and this is my benchmark:

Benchmark_ImageToMatRGB/standart-8                  1035           1155578 ns/op          415998 B/op      65963 allocs/op
Benchmark_ImageToMatRGB/my_func-8                   2788            432530 ns/op          204927 B/op          3 allocs/op

apoldev avatar Jan 12 '24 09:01 apoldev