Saturday, October 15, 2016

How to Integrate OpenCV for Android Tutorial 2 and Tutorial 3 Modules

OpenCV Android Tutorial 2 shows how to setup JNI to import C++ native code, while Tutorial 3 shows how to control Android camera to take a picture. In this tutorial, I will go over step by step how to integrate Tutorial 2 and Tutorial 3 modules; that is, we will be building an app that will both let us import native C++ OpenCV code and control Android camera to take picture.

To me, it seems easier to integrate JNI into Tutorial 3 module, so the following will simply add JNI capability to Tutorial 3 module.

First, import Tutorial 3 module from OpenCV Android.

Next, edit openCVTutorial3CameraControl/build.gradle file to use NDK, similar to below:
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "24.0.3"

    defaultConfig {
        applicationId "org.opencv.samples.tutorial3"
        minSdkVersion 8
        targetSdkVersion 22

        ndk {
            moduleName "camera_control" // this is the native module name
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

    sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
        jni.srcDirs = []
    }

    task ndkBuild(type: Exec) {
        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
            commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
        } else {
            commandLine '/home/linuxnme/Android/Sdk/ndk-bundle/build/ndk-build', '-C', file('src/main').absolutePath // replace with your path
        }
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }
}

dependencies {
    compile project(':openCVLibrary310')
}

Make sure to note NDK module name; in my case it is set to camera_control. Also, make sure to compile openCVLibrary with the same SdkVersion by editing the library's build.gradle file.

Next, edit Tutorial3Activity.java file to look like following:
...
public class Tutorial3Activity extends Activity implements CvCameraViewListener2, OnTouchListener {
    private static final String TAG = "OCVSample::Activity";
...
    public native void FindFeatures(long matAddrGr, long matAddrRgba);
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    System.loadLibrary("camera_control");
                    mOpenCvCameraView.enableView();
                    mOpenCvCameraView.setOnTouchListener(Tutorial3Activity.this);
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
...

   public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        Mat mRgba =  inputFrame.rgba();
        Mat mGray = inputFrame.gray();
        FindFeatures(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
        return mRgba;
    }
...

Make sure to use the same native module name.

Next, copy jni folder from Tutorial 2. Edit Application.mk file to set
APP_ABI := all

Edit Android.mk file to change JNI module name:
LOCAL_MODULE    := camera_control

Also, edit line 12 of this file to correctly point to your jni folder of OpenCV Android SDK.

Edit jni_part.cpp to correct the function names as below:
...
extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial3_Tutorial3Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial3_Tutorial3Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
    Mat& mGr  = *(Mat*)addrGray;
    Mat& mRgb = *(Mat*)addrRgba;
    vector<KeyPoint> v;
...

Enjoy Android development!

1 comment: