Android openCV and NDK integration in android studio 2.1.2

143 views Asked by At

I'm just getting started with Android NDK and openCV in android studio.

I have followed all the steps (which includes importing openCV-sdk) mentioned here https://www.learn2crack.com/2016/03/setup-opencv-sdk-android-studio.html and followed basic tutorials from Github samples for openCV https://github.com/opencv/opencv/tree/master/samples/android. Where in Tutorial2 It uses jni folder for C/C++ code when I compile and run the app I am getting following below error

07-27 17:55:43.407 13197-13197/com.sample.opencvtest E/AndroidRuntime: FATAL EXCEPTION: main
                                                                   Process: com.sample.opencvtest, PID: 13197
                                                                   java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.sample.opencvtest-1/base.apk"],nativeLibraryDirectories=[/data/app/com.sample.opencvtest-1/lib/arm, /data/app/com.sample.opencvtest-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]] couldn't find "libopenCVLibrary310.so"
                                                                       at java.lang.Runtime.loadLibrary(Runtime.java:367)
                                                                       at java.lang.System.loadLibrary(System.java:1076)
                                                                       at com.sample.opencvtest.Tutorial2$1.onManagerConnected(Tutorial2.java:54)
                                                                       at com.sample.opencvtest.Tutorial2.onResume(Tutorial2.java:121)
                                                                       at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258)
                                                                       at android.app.Activity.performResume(Activity.java:6327)
                                                                       at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
                                                                       at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
                                                                       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
                                                                       at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                                       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                                       at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                       at android.os.Looper.loop(Looper.java:148)
                                                                       at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

The error occur at statement

// Load native library after(!) OpenCV initialization
System.loadLibrary("openCVLibrary310"); // Confusing part here what should be pointed here in place of "openCVLibrary"

Below is MainActivity code

public class Tutorial2 extends Activity implements CameraBridgeViewBase.CvCameraViewListener2
{
    private static final String TAG = "OCVSample::Activity";

    private static final int VIEW_MODE_RGBA = 0;
    private static final int VIEW_MODE_GRAY = 1;
    private static final int VIEW_MODE_CANNY = 2;
    private static final int VIEW_MODE_FEATURES = 5;

    private int mViewMode;
    private Mat mRgba;
    private Mat mIntermediateMat;
    private Mat mGray;

    private MenuItem mItemPreviewRGBA;
    private MenuItem mItemPreviewGray;
    private MenuItem mItemPreviewCanny;
    private MenuItem mItemPreviewFeatures;

    private CameraBridgeViewBase mOpenCvCameraView;

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this)
    {
        @Override
        public void onManagerConnected(int status)
        {
            switch (status)
            {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");

                    // Load native library after(!) OpenCV initialization
                    System.loadLibrary("openCVLibrary310");

                    mOpenCvCameraView.enableView();
                }
                break;
                default:
                {
                    super.onManagerConnected(status);
                }
                break;
            }
        }
    };

    public Tutorial2()
    {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.tutorial2_surface_view);

        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial2_activity_surface_view);
        mOpenCvCameraView.setVisibility(CameraBridgeViewBase.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        Log.i(TAG, "called onCreateOptionsMenu");
        mItemPreviewRGBA = menu.add("Preview RGBA");
        mItemPreviewGray = menu.add("Preview GRAY");
        mItemPreviewCanny = menu.add("Canny");
        mItemPreviewFeatures = menu.add("Find features");
        return true;
    }

    @Override
    public void onPause()
    {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug())
        {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        }
        else
        {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    public void onDestroy()
    {
        super.onDestroy();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    public void onCameraViewStarted(int width, int height)
    {
        mRgba = new Mat(height, width, CvType.CV_8UC4);
        mIntermediateMat = new Mat(height, width, CvType.CV_8UC4);
        mGray = new Mat(height, width, CvType.CV_8UC1);
    }

    public void onCameraViewStopped()
    {
        mRgba.release();
        mGray.release();
        mIntermediateMat.release();
    }

    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame)
    {
        final int viewMode = mViewMode;
        switch (viewMode)
        {
            case VIEW_MODE_GRAY:
                // input frame has gray scale format
                Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
                break;
            case VIEW_MODE_RGBA:
                // input frame has RBGA format
                mRgba = inputFrame.rgba();
                break;
            case VIEW_MODE_CANNY:
                // input frame has gray scale format
                mRgba = inputFrame.rgba();
                Imgproc.Canny(inputFrame.gray(), mIntermediateMat, 80, 100);
                Imgproc.cvtColor(mIntermediateMat, mRgba, Imgproc.COLOR_GRAY2RGBA, 4);
                break;
            case VIEW_MODE_FEATURES:
                // input frame has RGBA format
                mRgba = inputFrame.rgba();
                mGray = inputFrame.gray();
                FindFeatures(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
                break;
        }

        return mRgba;
    }

    public boolean onOptionsItemSelected(MenuItem item)
    {
        Log.i(TAG, "called onOptionsItemSelected; selected item: " + item);

        if (item == mItemPreviewRGBA)
        {
            mViewMode = VIEW_MODE_RGBA;
        }
        else if (item == mItemPreviewGray)
        {
            mViewMode = VIEW_MODE_GRAY;
        }
        else if (item == mItemPreviewCanny)
        {
            mViewMode = VIEW_MODE_CANNY;
        }
        else if (item == mItemPreviewFeatures)
        {
            mViewMode = VIEW_MODE_FEATURES;
        }

        return true;
    }

    public native void FindFeatures(long matAddrGr, long matAddrRgba);
}

I have added jniLibs folder under app--> src--> main and copy armeabi-v7a and x86_64 folders from openCV-SDK-->native-->libs. Also added jni folder under app--> src--> main and have three files Android.mk, Application.mk and jni_part.cpp

jni_part.cpp code

#include <jni.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
#include <vector>

using namespace std;
using namespace cv;

extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial2_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

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

    Ptr<FeatureDetector> detector = FastFeatureDetector::create(50);
    detector->detect(mGr, v);
    for( unsigned int i = 0; i < v.size(); i++ )
    {
        const KeyPoint& kp = v[i];
        circle(mRgb, Point(kp.pt.x, kp.pt.y), 10, Scalar(255,0,0,255));
    }
}
}

I am stuck here. Any type of help would be appreciated

1

There are 1 answers

0
Avinash On

its beacause android is looking for "libopenCVLibrary310.so" in your /jniLibs folder and cannot find it.

you should check your Android.mk file and android build.gradle file where you have mentioned

if you want to check opencv is succesfully integrated or not the you can try

System.loadLibrary("libopencv_java3");

if you still get error then you have integrated opencv wrong.