Undefined Link to 'cv :: initModule_nonfree ()' on Android

I want to create an Android application that uses BOW + SVM in native (using C ++) for forecasting. Unfortunately, I have a problem with creating a native part. Since the proprietary module is not included in the OpenCV SDK for Android, I need to create the module myself using this tutorial . It seems I have successfully created the .so file. Here is the result:

[armeabi-v7a] Prebuilt : libopencv_java.so <= /home/crash-id/Development/SDK/OpenCV-2.4.9-android-sdk/sdk/native/jni/../libs/armeabi-v7a/ [armeabi-v7a] SharedLibrary : libnonfree.so [armeabi-v7a] Install : libnonfree.so => libs/armeabi-v7a/libnonfree.so [armeabi-v7a] Install : libopencv_java.so => libs/armeabi-v7a/libopencv_java.so 

So, the problem arises here when I have to add this .so file to my project. I added libnonfree.so to the jni folder. Then I edited Android.mk. Here I provide my .mk files.

Android.mk

 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nonfree_prebuilt LOCAL_SRC_FILES := libnonfree.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) OPENCV_CAMERA_MODULES := on OPENCV_INSTALL_MODULES := on include /home/crash-id/Development/SDK/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk #LOCAL_SHARED_LIBRARIES := nonfree_prebuilt #if I add this, it says undefined reference for everything in the cv namespace. LOCAL_SRC_FILES := SVMDetector.cpp LOCAL_MODULE := svm_detector LOCAL_C_INCLUDES += /home/crash-id/Development/SDK/OpenCV-2.4.9-android-sdk/sdk/native/jni/include LOCAL_CFLAGS := -Werror -O3 -ffast-math LOCAL_LDLIBS += -llog -ldl include $(BUILD_SHARED_LIBRARY) 

Application.mk

 APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_ABI := armeabi-v7a APP_PLATFORM := android-15 

But that does not work. When I try to create an application, I get the following error:

 ./obj/local/armeabi-v7a/objs/svm_detector/SVMDetector.o: in function Java_org_elsys_thesisdiploma_cammect_FrameProcess_SVMDetect:jni/SVMDetector.cpp:23: error: undefined reference to 'cv::initModule_nonfree()' 

When I press the right button on initModule_nonfree(); , Eclipse opens the nonfree.hpp file and here it is:

 #ifndef __OPENCV_NONFREE_HPP__ #define __OPENCV_NONFREE_HPP__ #include "opencv2/nonfree/features2d.hpp" namespace cv { CV_EXPORTS_W bool initModule_nonfree(); } #endif 

But I'm not sure that the linker knows where the implementation of this method is. Since this gives an error, it is not.

EDIT

If I add LOCAL_ALLOW_UNDEFINED_SYMBOLS := true , the project compiles successfully, but raises a runtime error:

  02-17 00:15:58.197: E/AndroidRuntime(8793): FATAL EXCEPTION: main 02-17 00:15:58.197: E/AndroidRuntime(8793): Process: com.example.cammect, PID: 8793 02-17 00:15:58.197: E/AndroidRuntime(8793): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN2cv18initModule_nonfreeEv" referenced by "libsvm_detector.so"... 

Do you know what I am doing wrong? Thanks in advance!

+7
android linker opencv android-ndk opencv4android
source share
2 answers

My development environment is configured as follows:

  • android-ndk-r10d (installation path: D:\adt-bundle-windows-x86_64-20140702\android-ndk-r10d\ )
  • OpenCV-2.4.10-android-sdk (installation path: D:\CODE\OpenCV-2.4.10-android-sdk\ ), Download link
  • OpenCV-2.4.10 (installation path: D:\CODE\OpenCV-2.4.10\ ), Download link

Building a proprietary module

  • We just need to copy a few files from the OpenCV-2.4.10 source code into OpenCV-2.4.10-android-sdk , namely:
    Copy the nonfree folder from OpenCV-2.4.10\sources\modules\nonfree\include\opencv2\ to OpenCV-2.4.10-android-sdk\sdk\native\jni\include\opencv2 .

  • Create a folder to store our new project for libnonfree.so . Here I call it libnonfree . Create jni folder in libnonfree . Copy the following files from OpenCV-2.4.10\sources\modules\nonfree\src to the libnonfree\jni\ folder:

  • Building libnonfree.so :
    Create Android.mk and Application.mk scripts. This Android.mk used to build libnonfree.so .

    cd into the libnonfree project libnonfree and type ndk-build to build libnonfree.so .

So far, you have libnonfree.so along with libopencv_java.so and libgnustl_shared.so in the libnonfree\libs\armeabi-v7a .
You can easily create any SIFT or SURF application using these libraries. If you want to use SIFT and SURF in JAVA code in an Android application, you only need to write JNI interfaces for the functions you want to use.

Building a sample application

  • Create a libnonfree_demo project folder libnonfree_demo . Create the jni folder inside the project folder. Then copy libnonfree.so along with libopencv_java.so and libgnustl_shared.so to jni .

  • Create nonfree_jni.cpp in jni . This is a simple SIFT test program. It basically reads the image and detects the key points, then extracts the function descriptors, finally draws the key points on the output image.

  • Create Android.mk and Application.mk inside jni :

    cd into the libnonfree_demo project libnonfree_demo and enter ndk-build to build libnonfree_demo.so .

At this point, you can easily extend the sample application using SVMDetector . Just copy the source and include the int files in the libnonfree_demo\jni and add the cpp files to the LOCAL_SRC_FILES in Android.mk .

The entire source can be downloaded using https://github.com/bkornel/opencv_android_nonfree .

Original source: http://web.guohuiwang.com/technical-notes/sift_surf_opencv_android

+15
source share

May I add that in order to use the new libraries in the running application, the following steps must be performed:

1) in your folder libnonfree / libs / [TARGET PLATFORM] /, now there are 3 files: - libgnustl_shared.so - libnonfree.so - libopencv_java.so

in your own project (my IDE is Android Studio), you have the src / main / folder with subfolders: - Java - res

create a new folder (if it does not already exist): "jniLibs" [this folder is automatically analyzed using Gradle]

COPY the 3 above folders under "libnonfree / libs /" to the "jniLibs" folder. you get this structure: jniLibs screenshot

/ app / src / main / jniLibs / [armeabi, armeabi-v7a, ...] / [libgnustl_shared.so, libopencv_java.so, libnonfree.so]

2) Somewhere in your code you have a line like this:

 OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, this, mLoaderCallback); 

this line tells your application to dynamically load a precompiled library from a locally installed OpenCV Manager. To use the self-compiled non-free version, we replace the above line as follows:

  if(!OpenCVLoader.initDebug()) { } else { System.loadLibrary("nonfree"); } 

we took care of using the free libraries that we provide to the application.

3) well, run the SURF descriptor:

 Bitmap mPhotograph = BitmapFactory.decodeFile(_image_path); Mat real_image = new Mat(); Utils.bitmapToMat(mPhotograph, real_image); MatOfKeyPoint keypoints_real = new MatOfKeyPoint(); FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF); detector.detect(real_image, keypoints_real); 

before the application returns with a bad signal, this time it will do its job, and you can evaluate the key points received.

+3
source share

All Articles