Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV Mat to JavaCV Mat conversion

I am in the process of writing an Android application that uses JavaCV for some facial recognition. I have come across a slight problem where I need to convert from an org.opencv.core.Mat that the onCameraFrame(CvCameraViewFrame inputFrame) function returns to a org.bytedeco.javacpp.opencv_core.Mat that the org.bytedeco.javacpp.opencv_contrib.FaceRecognizer requires.

I have found similar questions here and here but neither got a working solution.

like image 826
Eduan Bekker Avatar asked Oct 01 '22 00:10

Eduan Bekker


2 Answers

There's an easier, more efficient way documented at https://github.com/bytedeco/javacpp/issues/38#issuecomment-140728812, in short:

To JavaCPP/JavaCV:

Mat mat2 = new Mat((Pointer)null) { { address = mat.getNativeObjAddr(); } };

To official Java API of OpenCV:

Mat mat = new Mat(mat2.address());

EDIT: OpenCVFrameConverter now provides an easier and safer way to do this, for example:

OpenCVFrameConverter.ToMat converter1 = new OpenCVFrameConverter.ToMat();
OpenCVFrameConverter.ToOrgOpenCvCoreMat converter2 = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
Mat mat = ...;
org.opencv.core.Mat cvmat = converter2.convert(converter1.convert(mat));
Mat mat2 = converter2.convert(converter1.convert(cvmat));
like image 125
Samuel Audet Avatar answered Oct 03 '22 03:10

Samuel Audet


You can use java.awt.image.BufferedImage as interface.

Just convert your org.opencv.core.Mat object to java.awt.image.BufferedImage and then take the result object to convert it to org.bytedeco.javacpp.opencv_core.Mat.

Now, these are the functions that you will need:

1) Convert org.opencv.core.Mat to java.awt.image.BufferedImage:

public BufferedImage matToBufferedImage(Mat frame) {       
        int type = 0;
        if (frame.channels() == 1) {
            type = BufferedImage.TYPE_BYTE_GRAY;
        } else if (frame.channels() == 3) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        BufferedImage image = new BufferedImage(frame.width() ,frame.height(), type);
        WritableRaster raster = image.getRaster();
        DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
        byte[] data = dataBuffer.getData();
        frame.get(0, 0, data);
        return image;
    }

2) Convert java.awt.image.BufferedImage to org.bytedeco.javacpp.opencv_core.Mat:

public Mat bufferedImageToMat(BufferedImage bi) {
        OpenCVFrameConverter.ToMat cv = new OpenCVFrameConverter.ToMat();
        return cv.convertToMat(new Java2DFrameConverter().convert(bi)); 
    }

Make sure to have all the necessary jars and imports.

You could go deeper into JNI stuff, but for test use cases, this should be enough.

like image 29
Luis Mendoza Avatar answered Oct 03 '22 01:10

Luis Mendoza