Java – How to pass an ArrayListMat from Java to native (NDK) in opencv for android

How to pass an ArrayList from Java to native (NDK) in opencv for android… here is a solution to the problem.

How to pass an ArrayList from Java to native (NDK) in opencv for android

On the Java side I have

List<Mat> arystrdimages = new ArrayList<Mat>();

The images read from folders in the external catalog are then added to the list

for(File f : strdimgs)
{       
    Mat tempimg = Highgui.imread(f.getAbsolutePath(), CvType.CV_8UC1);
    arystrdimages.add(tempimg);
}

On the native jni side, I want to access arystrdimages by reference.

For a single Mat object, we can complete the method by calling getNativeObjAddr, i.e. in the opencv4android example of the Mat object, the access on the native side is done as follows

Java

private Mat mRgba;

Call native

CallNative(mRgba.getNativeObjAddr());

On the native side

JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_CallNative(JNIEnv *env, jobject thiz, jlong addrRgba1)
{
     Mat& mRgb = *(Mat*)addrRgba1;
}

How do I perform this action object for List<Mat>?

EDIT: Implementation of your suggested solution

Java side

int elems = arystrdimages.size();
Log.v("Matobjdata", "number of Matobject read = " + elems);
Log.v("Matobjdata", "from native = " + ans);
long[] tempobjadr = new long[elems]; 
for (int i=0; i<elems; i++)
{
    Mat tempaddr = arystrdimages.elementAt(i);
    tempobjadr[i] = tempaddr.getNativeObjAddr();
}

Log.v("Matobjdata", "addresselementsinlong arrray = " + tempobjadr.length);
int ans = TrainDescriptors(tempobjadr);  Call to native function
Log.v("Matobjdata", "from native = " + ans);

Native side

JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_TrainDescriptors(JNIEnv *env, jobject trainobject, jlongArray traindataaddr)
{
    vector<Mat> trainimgs;
    jsize a_len = env->GetArrayLength(traindataaddr);
    jlong *traindata = env->GetLongArrayElements(traindataaddr, 0);

for(int k=0; k<a_len; k++)
    {
        Mat & newimage=*(Mat*)traindata[k];
        trainimgs.push_back(newimage);
    }
     Do the required manipulation on the images; 
    env->ReleaseLongArrayElements(traindataaddr, traindata, 0);

return a_len;
}

Solution

You can build an array of long values (getNativeObjAddr() results for all Mats) in Java and call the native function that passes the array.

In JNI, you can access all long values using GetArrayLength and GetLongArrayElements, which return jlong to the first element.

Use ReleaseLongArrayElements when you’re done.

Related Problems and Solutions