Skip to content Skip to sidebar Skip to footer

How To Call Jni Object In Android Activity?

I am making an Document Scanner. I'm using opencv for image processing. In camera view i'm bounding rectangle on largest contour. Processing part written in Native-lib.cpp. It is d

Solution 1:

You can receive org.opencv.core.Rect from native-lib. The easiest way is to change your native method signature, doWithMat() like this:

private org.opencv.core.Rect mBoundingRect;

@OverridepublicMatonCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
    // input frame has RGBA format
    mRgba = inputFrame.rgba();
    mGray = inputFrame.gray();
    mBoundingRect = doWithMat(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
    return mRgba;
}

extern"C"JNIEXPORT jobject JNICALL
Java_prisca_ctest_OpenCvCamera_doWithMat(JNIEnv *env, jobject instance,
        jlong matAddrGr, jlong matAddrRgba){

    Mat &image = *(Mat *) matAddrRgba;
    Rect bounding_rect;

    Mat thr(image.rows, image.cols, CV_8UC1);
    cvtColor(image, thr, CV_BGR2GRAY); // Convert to graythreshold(thr, thr, 150, 255, THRESH_BINARY + THRESH_OTSU); //Threshold the gray

    vector<vector<Point> > contours; // Vector for storing contour
    vector<Vec4i> hierarchy;
    findContours(thr, contours, hierarchy, CV_RETR_CCOMP,
        CV_CHAIN_APPROX_SIMPLE); // Find the contours in the imagesort(contours.begin(), contours.end(),
        compareContourAreas);    // Store the index of largest contour
    bounding_rect = boundingRect((const _InputArray &) contours[0]);

    rectangle(image, bounding_rect, Scalar(250, 250, 250) , 5);

    jclass rectClass = env->FindClass("org/opencv/core/Rect");
    jmethodID rectCtorID = env->GetMethodID(rectClass, "<init>", "(IIII)V");
    return env->NewObject(rectClass, rectCtorID, bounding_rect.x, bounding_rect.y, bounding_rect.width, bounding_rect.height);
}

As you can see, I removed try ... catch from the native code; I don't think it can really help, especially when you try to catch an int, instead of exception.

Note that extraction of rectClass and rectCtorID are expensive operations, therefore it's smart to cache these values:

static jclass rectClass = nulltr;
ststic jmethodID rectCtorID = 0;
if (rectCtorID == 0) {
    rectClass = env->NewGlobalRef(env->FindClass("org/opencv/core/Rect"));
    rectCtorID = env->GetMethodID(rectClass, "<init>", "(IIII)V");
}

Note that we need a global reference to Java class, but the method ID is just an int.


Another optimization that I can suggest is to use matAddrGr. If I understand correctly, OpenCV will prepare both matrices for onCameraFrame(), so you there is probably no need to convert RGB to gray.

Solution 2:

here, you have two options first one you need to process byte of the camera frame using JNI and then after you need to fetch processed pixels and set into the camera preview. Then after using canvas crop bitmap. The second one you need to follow this code for the image cropping.

Matimage= ...; // your image
Mat crop(image, bounding_rect); 
// NOTE: this is only give refrence to you.Matoutput= crop.clone();

Solution 3:

You need to do a couple of things to be able to call Java_prisca_ctest_OpenCvCamera_doWithMat in Java code.

Do you have CMakeList.txt or something similar where you decide, what files will be part of your compilation?

If so, you can present your 'native-lib.cpp' in Java code like this:

static { System.loadLibrary("native-lib"); }

Then you have to present your native functions to Java code. It is done like this:

publicnativevoiddoWithMat(long matAddrGr, long matAddrRgba);

Finally you can call your native function anywhere in the same file you have presented that function. Just call e.g.:

doWithMat(1, 2);

But like you might have noticed, doWithMath() is void type function, so it does not return anything. You just simply cant "access object" from C++ in Java code. Instead you have to have getter to transfer object to Java side or return Rect from function doWithMath().

Unfortunately you can't return Rect straight from C++ code, since you cannot specify the function to return C++ types. Instead what you should do IMHO is to get data from Rect (coordinates or whatever it has) and return them in array, and then handle that data in Java side.

I recommend to go through this hello-jni tutorial so you get the idea of how to do stuff in JNI: https://developer.android.com/ndk/samples/sample_hellojni.html

Post a Comment for "How To Call Jni Object In Android Activity?"