Search code examples
javacopencvjava-native-interface

Passing OpenCv Mat Object From Java to C Native


I'm trying to read an image by opencv then pass it from java language to my native library written by C Language not C++. I'm using JNI function and I've seen many samples of c++ code in which Mat Object is used. but my problem is that there isn't any Mat object in "C Language" and the only object I have is CvMat.So when I get my image in my native codes it is a wrong image. I should mention that I can not use c++ for many reasons and the C is my only option to write native code.

My Java Code:

Mat img = Imgcodecs.imread("./mypic.jpg", Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
myClass.getImg(img.getNativeObjAddr())

My Native Code:

JNIEXPORT jfloat JNICALL Java_PredictJNI_getImg
(JNIEnv *env, jobject thisObj, jlong imgPtr)
{
    CvMat* img = (CvMat*)imgPtr;
    printf("Image Width:%d:" , img->cols);
}

Solution

  • So don't pass whole Mat structure. Pass just pointer to raw data instead.

    //uchar* ptr2imgData = dynamic_cast<uchar *>( imgPtr );
    //cv::Mat img( cv::Size{ WIDTH, HEIGHT }, CV_8UC3, ptr2imgData ); // C++
    
    uchar* ptr2imgData = (uchar *)imgPtr;  // uchar is unsigned char
    CvMat* img = cvCreateMat( WIDTH, HEIGHT, CV_8UC3 );
    img->ptr = imgPtr;
    

    If type of matrix and/or matrix size may differ, pass additional info in another argument(s). If type of matrix is always the same, leave it hardcoded and pass just pointer to data.

    Then construct new Mat from these data.

    I have never written line of Java and I'm proud of it - anyway I know there are no pointers. I found you may use get() method

    myClass.getImg(img.get(0, 0)); // Beginning of the array
    

    or your mentioned getNativeObjAddr() method

    myClass.getImg(img.getNativeObjAddr());
    

    Your solution can't work and invokes undefined behavior, because cvMat and Mat are totally different types.