Android OpenCV : how to pass Mat objects between java & c++

Let's Get The Job Done!

Android OpenCV : how to pass Mat objects between java & c++

Hello friends , in this article i’m gonna discuss a trick that could save a lot of time and energy and also give OpenCV fans so much flexibility working on the android platform.

As you may encounter some of OpenCV parts are not ported into java for example the one that i had encountered is Stiching  module.

And in other hands some android capabilities are not fully supported in OpenCV C++  and the one i encountered is just camera API , integrating with camera is not so solid and reliable in OpenCV through NDK but it could be done through java API.

So imagine  that you want use camea from java and Stiching from C++ , now you come up into a Dilemma to how pass camera images captured from java part into class that you have written using NDK .

One Solution is to save the Bitmap object into disk ,  pass file path to NDK  and later use the image from file system , that could be a good solution when you want perform processing just on a single image file , but what if you want to process a stream of Bitmaps coming from camera that is not reasonable to use file system .

first let me discuss how to capture bitmap for opencv in java :

by using JavaCamera2View you can capture Mat objects from android camera :

//    **********************
//  *** This is a sudo code ***
//    **********************
private JavaCamera2View mCareaView;
    mCareaView = (JavaCamera2View) view.findViewById(R.id.fragment_java_camera) ;
           mCareaView.setCvCameraViewListener(new CameraBridgeViewBase.CvCameraViewListener() {
            @Override
            public void onCameraViewStarted(int width, int height) {
                Log.d(TAG, "onCameraViewStarted: cameara started");
                mRgba = new Mat(height , width , CvType.CV_8UC4) ;
            }

            @Override
            public void onCameraViewStopped() {
                Log.d(TAG, "onCameraViewStopped: camera stopped");
                mRgba.release();
            }

            @Override
            public Mat onCameraFrame(Mat inputFrame) {
                // capture Mat frames here 
                mRgba = inputFrame ;
                mCounter++ ;
                return processReturnedMat(onFramePrepared(inputFrame));
            }
        });

Now we have Mat frame , so what to do  , how to send it to ndk : we can get the pointer to mat object into memory using OpenCV built-in methods and pass the address to ndk :

// another java method to pass Mat to NDK  
public static void appyColorMap(Context context , Mat input){
        applyColorMap(input.getNativeObjAddr());
    }
    
// native funtion connecting java and NDK
private static native void applyColorMap(long inputMat);
// C++ code that does image processing on mat
extern "C"
JNIEXPORT void JNICALL
Java_softeng_class1_lclass2_opencvpanorama_utils_ImageUtils_applyColorMap(JNIEnv *env, jclass type,
                 //Hee you see the Pointer to Mat object as jlong argument
                     jlong inputMat) {

    // just define a Mat object using the pointer
    Mat& input = *(Mat*) inputMat ;
    cvtColor(input , input ,CV_RGBA2GRAY ) ;
    applyColorMap(input , input , COLORMAP_OCEAN) ;
}

Now after finishing the c++ method you can use the Mat object in java your class without any extra operation right after :

public static void appyColorMap(Context context , Mat input){
      applyColorMap(input.getNativeObjAddr());
      // converting Mat to Bitmap using OpenCV Built-in method.
      Utils.matToBitmap(mat , mBitmap);
      // and finally using the processed Bitmap
      mImageView.setImageBitmap(mBitmap) ; 
  }

  private static native void applyColorMap(long inputMat);

that’s it , hope you enjoyed.

 

Comments are closed.