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:
apply plugin: ''

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 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) {
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                    Log.i(TAG, "OpenCV loaded successfully");
                } break;
                } 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 file to set
APP_ABI := all

Edit 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: