Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning Mat object from native code to java in OpenCV

I have an OpenCV Android app. Most of its code is in Java but I have one function that is in C. The function gets a Mat object and returns a new one.

My question is how do I return a Mat from the native code to Java? Couldn't find any example of that.

Thanks.

like image 209
Saqib Razaq Avatar asked Mar 30 '12 00:03

Saqib Razaq


2 Answers

Today I had to return a Mat from native code. I started with "Tutorial 2 Advanced - 2. Mix Java+Native OpenCV" it already passes two Mat (Images captured from camera) objects to the native code. But I wanted to return extracted feature, thus I added jlong addrDescriptor to the signature:

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

In the java part I added the Mat

private Mat descriptor;
descriptor = new Mat();

The method getNativeObjAddr() does the trick. The Mat is allocated in java and its address is passed to the native code, thus there isn't any explicit returning.

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

The Mat was filled with the required data and is directly accessible in the java code after the JNI invokation returns.

Somwhere else in the code the Mat is released:

if ( descriptor != null) 
  descriptor.release();
descriptor = null;
like image 153
stacker Avatar answered Nov 11 '22 14:11

stacker


in C++

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

in java:

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

Attention: You must new Mat() in C,if you code is : Mat mat();mat object memory will be collect when funC() end.

like image 25
K Lam Avatar answered Nov 11 '22 16:11

K Lam