【问题标题】:Returning Mat object from native code to java in OpenCV在 OpenCV 中将 Mat 对象从本机代码返回到 java
【发布时间】:2012-03-30 00:46:05
【问题描述】:

我有一个 OpenCV Android 应用程序。它的大部分代码都是用 Java 编写的,但我有 C 中的一个函数。 该函数获取一个 Mat 对象并返回一个新对象。

我的问题是如何将 Mat 从本机代码返回给 Java? 找不到任何例子。

谢谢。

【问题讨论】:

    标签: android opencv javacv


    【解决方案1】:

    今天我不得不从本机代码返回一个 Mat。我从“Tutorial 2 Advanced - 2. Mix Java+Native OpenCV”开始,它已经将两个 Mat(从相机捕获的图像)对象传递给本机代码。 但我想返回提取的特征,因此我在签名中添加了jlong addrDescriptor:

    extern "C" {
    JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_Sample4View_FindFeatures(JNIEnv* env, jobject thiz, jlong addrGray, jlong addrRgba, jlong addrDescriptor)
    {
        Mat* pMatGr=(Mat*)addrGray;
        Mat* pMatRgb=(Mat*)addrRgba;
        Mat* pMatDesc=(Mat*)addrDescriptor;
        vector<KeyPoint> v;
    
        //OrbFeatureDetector detector(50);
        OrbFeatureDetector detector;
        OrbDescriptorExtractor  extractor;
        detector.detect(*pMatGr, v);
        extractor.compute( *pMatGr, v, *pMatDesc );
        circle(*pMatRgb, Point(100,100), 10, Scalar(5,128,255,255));
        for( size_t i = 0; i < v.size(); i++ ) {
            circle(*pMatRgb, Point(v[i].pt.x, v[i].pt.y), 10, Scalar(255,128,0,255));
        }
        }
    }
    

    在 java 部分我添加了 Mat

    private Mat descriptor;
    descriptor = new Mat();
    

    getNativeObjAddr() 方法可以解决问题。 Mat 是在 java 中分配的,它的地址被传递给本地代码,因此没有任何显式返回。

    FindFeatures(mGraySubmat.getNativeObjAddr(), mRgba.getNativeObjAddr(), descriptor.getNativeObjAddr());
    Log.i("desc:"  , descriptor.dump());
    

    Mat 填充了所需的数据,在 JNI 调用返回后可在 java 代码中直接访问。

    Mat 被释放的代码中的其他地方:

    if ( descriptor != null) 
      descriptor.release();
    descriptor = null;
    

    【讨论】:

    • 您好 stacker,将我的本机代码更改为:Mat* image=(Mat*)addrDescriptor;垫处理(image.size(), CV_8UC3); cv::medianBlur(*image, processing, 5);现在我收到以下错误消息:jni/objDetector.cpp:23: error: request for member 'size' in 'image', which is non-class type 'cv::Mat
    • @SaqibRazaq 签名是 void medianBlur(const Mat&amp; src, Mat&amp; dst, int ksize) 您需要通过引用处理来调用它。试试&amp;processing。或者定义为Mat&amp; processing(image.size(), CV_8UC3);
    • @SaqibRazaq 如果你想返回Mat &amp;dst,那么你应该在你的java代码中声明它,并将它添加到JNI方法的调用中,就像你添加image一样。
    • @stacker Somwhere else in the code the Mat is released:是什么意思
    • @RomanticElectron 应该在工作完成后调用代码(帖子的最后 3 行)以释放内存。
    【解决方案2】:

    在 C++ 中

    jlong funC(){
    Mat *mat = new Mat();
    //...
    return (jlong)mat;
    }
    

    在java中:

    long = addr;// addr is return from c method funC()
    Mat mat = new Mat(addr);
    

    注意:你必须在 C 中 new Mat(),如果你的代码是: Mat mat();当 funC() 结束时,mat 对象内存将被收集。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-14
      • 2019-05-23
      • 2018-09-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多