2

I would like to pass an array of arrays calculated from a native method in a Java class. To do this I thought to call the method setTarghet from native code to set each vector field. I think it's a good idea. this is a java class:

public class struttura {


 private int _facetCount;


    public Mat [] VectorTarget;

    public struttura(int facetCount)
    {
        _facetCount = facetCount;


        VectorTarget = new Mat[facetCount];

    }

    public int getFacetCount()
    {
        return _facetCount;
    }

    public void setTarget (int index,Mat value)
    {
        VectorTarget[index]=value;    

    }
}

this is native code

 JNIEXPORT void JNICALL Java_com_example_nonfreejnidemo_NonfreeJNILib_extractorSuTarget(JNIEnv * env, jobject obj, jint nT )
{
   .....

    Mat object[50];

  // read 50 image and put them in object[i]
        for (unsigned int i = 0;i < 50 ;i++) {
            object[i] = imread( files[i], CV_LOAD_IMAGE_GRAYSCALE );
        }

        //Detect the keypoints using SURF Detector
        int minHessian = 500;

        SurfFeatureDetector detector( minHessian );
        std::vector<KeyPoint> kp_object[nT];


        for (unsigned int i = 0;i < nT; i++)
        {
            detector.detect( object[i], kp_object[i] );
        }


        //Calculate descriptors (feature vectors)
        SurfDescriptorExtractor extractor;

        Mat des_object[nT];

        for (unsigned int i = 0;i < nT; i++)
        {
             extractor.compute( object[i], kp_object[i], des_object[i] );

        }
        //-----------------------------------------------------------------------------------------------
        // now begin my problem
    // i want to call method setTarget from java code to map des_object on VectorTarget 
    // and use it on java code.
    // i try something like this but i have some  errors.
    // i now that it is not correct, i do not know how write it.

    for (int index=0; index <50; index++)
    {

               jlong        y  =    (jlong)des_object[index] ;
               jclass cls = env->GetObjectClass(obj);
               jmethodID methodId = env->GetMethodID( cls, "setTarget", "(IJ)V");
               env->CallVoidMethod(obj, methodId,index,y );

     }
        //-----------------------------------------------------------------------------------------------

i want to call method setTarget from java code to map des_object on VectorTarget and use it on java code. i try something like this but i have some errors. i know that it is not correct, i do not know how write it please help me.

1 Answer 1

1

Your concept has a flow - you cannot pass a C++ instance of class Mat as Java object of class Mat.

On the other hand, you don't need to call Java method just to set an element of a Java Object array.

So, your loop can simply look like

jclass matClass = static_cast<jclass>(env->FindClass("com/example/Mat");
jmethodID matConstructor = env->GetMethodID(matClass, "<init>", "([I)V");
for (int index=0; index<50; index++)
{
    jobject jMatObject = env->NewObject(matClass, matConstructor, des_object[index]);
    env->SetObjectArrayElement( arr, i, jMatObject);
    env->DeleteLocalRef(jMatObject);
}

If your descriptor is not an array of integers, you must prepare the relevant constructor for your Mat Java class.

Note that you can cache both matClass and matConstructor for all calls of your extractorSuTarget() native method.


If you don't need to access the individual elements of des_object, your life is much easier:

public class struttura {

    private int _facetCount;

    public long nativeVectorTarget;

    public struttura(int facetCount)
    {
        _facetCount = facetCount;
    }

    public int getFacetCount()
    {
        return _facetCount;
    }

    private void setTarget(long nativePointer)
    {
        nativeVectorTarget = nativePointer;

    }
}

and in C++,

extern "C" JNIEXPORT void JNICALL Java_com_example_nonfreejnidemo_NonfreeJNILib_extractorSuTarget(JNIEnv * env, jobject obj, jint nT )
{
   .....

    Mat object[50];

  // read 50 image and put them in object[i]
        for (unsigned int i = 0;i < 50 ;i++) {
            object[i] = imread( files[i], CV_LOAD_IMAGE_GRAYSCALE );
        }

        //Detect the keypoints using SURF Detector
        int minHessian = 500;

        SurfFeatureDetector detector( minHessian );
        std::vector<KeyPoint> kp_object[nT];


        for (unsigned int i = 0;i < nT; i++)
        {
            detector.detect( object[i], kp_object[i] );
        }

        //Calculate descriptors (feature vectors)
        SurfDescriptorExtractor extractor;

        Mat* des_object = new Mat[nT]();

        for (unsigned int i = 0;i < nT; i++)
        {
             extractor.compute( object[i], kp_object[i], des_object[i] );

        }
        jclass cls = env->GetObjectClass(obj);
        jmethodID methodId = env->GetMethodID( cls, "setTarget", "(J)V");
        env->CallVoidMethod(obj, methodId, (jlong)des_object);

}
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you for having responded to me. I'm not practical jni, sorry for my basic questions. I did not understand a few things: 1) when you write : env->FindClass("com/example/Mat") you mean the path of my class (struttura) in my package? therefore: com/example/nonfreejnidemo/struttura 2) how to modify my costructor for my java class? please can yo help me? 3) how i rewrite env->GetMethodID(matClass, "<init>", "([I)V"); for an array of mat? thanks very much.
FindClass is for the class Mat (the class of elements of VectorTarget). Same for the constructor: it takes one object from des_object vector and creates one object to be placed in VectorTarget. Or maybe I don't understand correctly the purpose of storing these native objects (are they from OpenCV?) in the Java object. What will you do with all these descriptors later, after you store them in VectorTarget?
I'm probably a lot of things wrong. I write a program written in C ++ and opencv that via webcam reads images stored on the HD 50 and compares them with each frame captured by the webcam. I used the algorithms of SURF for matching of images. The purpose of this is that each time webcam I see a road sign is recognized among the 50 images targhet I preloaded. Everything works fine. the problems I have in making the porting of this application on Android.
methods to calculate descriptors SURF must remain in C ++ for this I used the JNI. so the first part of the program, where I have problems, it works well. native code read the 50 images taghet, calculating their descriptor and pass it in a Java class (what I call the structura). then to Java code, I open the webcam and for each frame captured the step to native code, calculating the descriptor of each frame and the comparison with all the descriptors contained in the class struttura. when I find the matching between a frame and a picture then I do other actions ...
Whereas in native code I can not have global variables have to be stored in java structure. you have no idea how to accomplish this in a more efficient porting?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.