OpenCV Mat 转换为 JavaCV Mat

5
我正在编写一个使用JavaCV进行面部识别的Android应用程序。 我遇到了一个小问题,需要将onCameraFrame(CvCameraViewFrame inputFrame)函数返回的org.opencv.core.Mat转换为org.bytedeco.javacpp.opencv_core.Mat,以便满足org.bytedeco.javacpp.opencv_contrib.FaceRecognizer的要求。
我发现类似的问题herehere,但都没有得到可行的解决方案。

是的,这是一个令人沮丧的话题——有两个独立的Java OpenCV包装器,但它们基本上不兼容。 - berak
一定有办法。可以编写一个手动函数来完成它或者其他什么方法。 - Eduan Bekker
我正在编写一个使用JavaCV的Android应用程序。但是,我强烈建议您在新代码中使用官方的OpenCV Java API。但如果您真的必须这样做,您可能需要编写一些本地代码来进行转换,并通过JNI调用它,除非有某种方法可以将OpenCV的Mat.dataAddr()的长结果转换为bytedeco指针,以便您可以将其传递给bytedeco Mat构造函数。 - Bull
2个回答

4

https://github.com/bytedeco/javacpp/issues/38#issuecomment-140728812上有一种更简单、更高效的方法,简而言之:

对于JavaCPP / JavaCV:

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

访问OpenCV的官方Java API:

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

编辑OpenCVFrameConverter 现在提供了一种更简单、更安全的方法来实现这一点,例如:

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));

这个在更新库到javacpp-presets:ffmpeg 4.1-1.4.4之后就可以工作了。 - SalutonMondo
找不到"OpenCVFrameConverter.ToOrgOpenCvCoreMat",表示无法解析该符号。 - Bala Ganesh
它仍然存在,没有任何改变:http://bytedeco.org/javacv/apidocs/org/bytedeco/javacv/OpenCVFrameConverter.ToOrgOpenCvCoreMat.html - Samuel Audet

1
你可以使用java.awt.image.BufferedImage作为接口。
只需将你的org.opencv.core.Mat对象转换为java.awt.image.BufferedImage,然后将结果对象转换为org.bytedeco.javacpp.opencv_core.Mat。
现在,这些是你需要的功能:
1)将org.opencv.core.Mat转换为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)将java.awt.image.BufferedImage转换为org.bytedeco.javacpp.opencv_core.Mat:

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

请确保拥有所有必要的JAR文件和导入项。

你可以深入研究JNI相关内容,但对于测试用例来说,这应该已经足够了。


javacv中没有像opencv_core.Mat..get(0, 0, data);这样的方法!! - user924
@user924 是的,有一种叫做“索引器”的东西:http://bytedeco.org/news/2014/12/23/third-release/。 - Samuel Audet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接