在OpenCV for Android 2.4.5中使用SURF(nonfree module)
2013-06-18 15:46
330 查看
在OpenCV4Android中没有nonfree module,因此也就没有了SURF和SIFT组件。但是我们可以通过OpenCV for Windows的nonfree module开源代码通过NDK将其编译为Android可以使用的.so库文件,然后通过JNI技术,将该.so文件挂载到JNI的库中。
具体实现方法如下:
OpenCV for Android
OpenCV for Windows(其实只需要两个头文件)
Android ADT
电脑操作系统为Windows7 x86,Android开发环境为ADT 20130512。下面说明如何在OpenCV中使用nonfree module:
nonfree module 的源代码存储在C:\Program Files\opencv\modules\nonfree\src中,头文件存储在C:\Program Files\opencv\modules\nonfree\include\opencv2\nonfree中。
编译的过程中需要两个头文件,一个为nonfree.hpp,一个为features2d.hpp,将这两个头文件拷贝至OpenCV4Android SDK的include文件夹下:E:\My Documents\Android\OpenCV-2.4.5-android-sdk\sdk\native\jni\include\opencv2\nonfree文件夹下。
为了编译库文件,我们还需要nonfree module的源代码。源代码为C:\Program Files\opencv\modules\nonfree\src中的nonfree_init.cpp,precomp.cpp,sift.cpp,surf.cpp和precomp.hpp五个文件。为了简单起见,我们需要一个简单的Android JNI的工程来帮我们编译这些源代码。
博主NDK的位置为C:\android-ndk-r8e,在系统变量中创建NDKROOT,变量值为C:\android-ndk-r8e,在该文件夹下有ndk-build.cmd脚本命令文件,该文件是使用NDK编译C代码的关键。配置完毕后,在Android工程中配置C++编译命令,配置如下所示,意味使用环境变量中NDKROOT/ndk-build.cmd进行编译
在Behaviour选项卡中勾选Build on resource save(Auto build)。至此NDK配置完毕
在Android.mk中使用了OpenCV.mk的路径和jni/include的路径,我的工程是和OpenCV SDK放在同一文件夹下的,因此可以这样写。两处使用绝对路径也可以,但是不能有空格。
在Application.mk中代码如下
如果之前勾选了Auto Build,这里工程会自动编译,在libs下会生成两个库,为libnonfree.so和libopencv_java.so,这两个库就是需要的库文件了。使用这两个库文件,就可以通过JNI技术在Android中使用SURF算法。
编写Android.mk文件如下:
编写Application.mk文件如下:
此时你会发现各种语法错误和不能解析的变量。其实他们并不影响编译,所有的头文件在Android.mk和Application.mk中已经声明,编译仍然会成功,但是自己编写程序时为了使用Eclipse的提示功能,需要对工程进行如下设置。
在C/C++ General->Paths and Symbols中设置Includes为:
${NDKROOT}/platforms/android-14/arch-arm/usr/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.7/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include
../OpenCV-2.4.5-android-sdk/sdk/native/jni/include
参见
OpenCV4Android文档
你会发现所有都正常了,此时工程结构组织如下:
在libs下的libSurf.so库就是我们需要使用的JNI库。
OpenCV文档。需等待OpenCV库加载完毕后才能加载我们编写的库。2.4.5中应该不用添加initial_nonfree()这个函数了。运行能够成功。
一定要顺序加载,否则会报错。至此就能够在JAVA中使用Native函数了。
网上这方面资料很少,希望对大家有所帮助。
具体实现方法如下:
需要的工具:
NDKOpenCV for Android
OpenCV for Windows(其实只需要两个头文件)
Android ADT
电脑操作系统为Windows7 x86,Android开发环境为ADT 20130512。下面说明如何在OpenCV中使用nonfree module:
1.编译nonfree module库
博主OpenCV for Windows安装路径为C:\Program Files\opencv,OpenCV4Android路径为 E:\My Documents\Android\OpenCV-2.4.5-android-sdk。nonfree module 的源代码存储在C:\Program Files\opencv\modules\nonfree\src中,头文件存储在C:\Program Files\opencv\modules\nonfree\include\opencv2\nonfree中。
编译的过程中需要两个头文件,一个为nonfree.hpp,一个为features2d.hpp,将这两个头文件拷贝至OpenCV4Android SDK的include文件夹下:E:\My Documents\Android\OpenCV-2.4.5-android-sdk\sdk\native\jni\include\opencv2\nonfree文件夹下。
为了编译库文件,我们还需要nonfree module的源代码。源代码为C:\Program Files\opencv\modules\nonfree\src中的nonfree_init.cpp,precomp.cpp,sift.cpp,surf.cpp和precomp.hpp五个文件。为了简单起见,我们需要一个简单的Android JNI的工程来帮我们编译这些源代码。
2.配置NDK环境
在Android中创建JNI工程的方法是在一个已经创建好的Android工程上点击右键,new->Ohter->Convert to a C/C++ Project(Adds C/C++ Nature),并在Android工程目录中创建jni文件夹,将上述5个源代码文件拷贝至jni文件夹中。并在jni文件夹中创建Android.mk和Application.mk文件。此时文件组织如下:博主NDK的位置为C:\android-ndk-r8e,在系统变量中创建NDKROOT,变量值为C:\android-ndk-r8e,在该文件夹下有ndk-build.cmd脚本命令文件,该文件是使用NDK编译C代码的关键。配置完毕后,在Android工程中配置C++编译命令,配置如下所示,意味使用环境变量中NDKROOT/ndk-build.cmd进行编译
在Behaviour选项卡中勾选Build on resource save(Auto build)。至此NDK配置完毕
3.编写makefile文件
在Android.mk中代码如下LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) OPENCV_INSTALL_MODULES:=on OPENCV_CAMERA_MODULES:=off include ..\OpenCV-2.4.5-android-sdk\sdk\native\jni\OpenCV.mk LOCAL_C_INCLUDES:= ../OpenCV-2.4.5-android-sdk/sdk/native/jni/include LOCAL_MODULE := nonfree LOCAL_CFLAGS := -Werror -O3 -ffast-math LOCAL_LDLIBS += -llog LOCAL_SRC_FILES := nonfree_init.cpp \ precomp.cpp \ sift.cpp \ surf.cpp include $(BUILD_SHARED_LIBRARY)
在Android.mk中使用了OpenCV.mk的路径和jni/include的路径,我的工程是和OpenCV SDK放在同一文件夹下的,因此可以这样写。两处使用绝对路径也可以,但是不能有空格。
在Application.mk中代码如下
#APP_ABI := armeabi APP_ABI := armeabi-v7a APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_PLATFORM := android-8这里可能有问题,APP_PLATFORM按照Andoird工程建立时最小SDK填写,否则编译不过。
如果之前勾选了Auto Build,这里工程会自动编译,在libs下会生成两个库,为libnonfree.so和libopencv_java.so,这两个库就是需要的库文件了。使用这两个库文件,就可以通过JNI技术在Android中使用SURF算法。
4. 在Android中使用SURF的例子
和2中一样,首先创建一个带有NDK工程的Android工程,并创建jni文件夹,用javah生成native的类头文件(如何生成类文件请参看另一边博文),并将刚才编译好的libnonfree.so和libopencv_java.so拷贝值jni文件夹下(当然你也可以把这两个东西放到OpenCV的库文件夹下,一劳永逸,只要能在链接的时候能搜索到就行了)。编写好native方法的c++实现,这里我实现了利用SURF的特征点检测和描述符生成。代码如下:#include "NativeSurf.h" #include <opencv2/opencv.hpp> #include <stdio.h> #include <opencv2/nonfree/features2d.hpp> #include <opencv2/nonfree/nonfree.hpp> using namespace cv; using namespace std; void KeyPoint2Mat(vector<KeyPoint>& keypoints, Mat& mat) { int i = 0; int size = keypoints.size(); mat.create(size,1,CV_32FC(7)); float* buff = (float*)mat.data; for(i=0;i<size;i++) { KeyPoint kp = keypoints[i]; buff[7*i+0] = kp.pt.x; buff[7*i+1] = kp.pt.y; buff[7*i+2] = kp.size; buff[7*i+3] = kp.angle; buff[7*i+4] = kp.response; buff[7*i+5] = kp.octave; buff[7*i+6] = kp.class_id; } } JNIEXPORT void JNICALL Java_com_ruif_nativeSurf_NativeSurf_SurfDetect (JNIEnv *, jclass, jlong imgObj, jlong keyPointsObj, jlong descriptorObj) { //Create Mats Mat* img = (Mat*)imgObj; //img Mat* descriptor = (Mat*)descriptorObj; //Descriptor Mat* keyPointsMat = (Mat*)keyPointsObj; vector<KeyPoint> keyPointvec; SurfFeatureDetector surfDetector(1000); SurfDescriptorExtractor surfExtractor; surfDetector.detect(*img,keyPointvec); surfExtractor.compute(*img,keyPointvec,*descriptor); KeyPoint2Mat(keyPointvec,*keyPointsMat); }
编写Android.mk文件如下:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nonfree LOCAL_SRC_FILES := libnonfree.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := opencv_java_prebuilt LOCAL_SRC_FILES := libopencv_java.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) include ../OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk LOCAL_MODULE := Surf LOCAL_CFLAGS := -Werror -O3 -ffast-math LOCAL_LDLIBS += -llog -ldl LOCAL_SHARED_LIBRARIES := nonfree opencv_java_prebuilt LOCAL_SRC_FILES := Surf.cpp include $(BUILD_SHARED_LIBRARY)
编写Application.mk文件如下:
APP_ABI := armeabi-v7a APP_STL := gnustl_static APP_CPPFLAGS := -frtti -fexceptions APP_PLATFORM := android-8
此时你会发现各种语法错误和不能解析的变量。其实他们并不影响编译,所有的头文件在Android.mk和Application.mk中已经声明,编译仍然会成功,但是自己编写程序时为了使用Eclipse的提示功能,需要对工程进行如下设置。
在C/C++ General->Paths and Symbols中设置Includes为:
${NDKROOT}/platforms/android-14/arch-arm/usr/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.7/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/4.7/libs/armeabi-v7a/include
../OpenCV-2.4.5-android-sdk/sdk/native/jni/include
参见
OpenCV4Android文档
你会发现所有都正常了,此时工程结构组织如下:
在libs下的libSurf.so库就是我们需要使用的JNI库。
5.使用JNI库
该JNI库需要结合OpenCV使用,因此仍然需要调用OpenCV4Anroid库,调用的方法参见OpenCV文档。需等待OpenCV库加载完毕后才能加载我们编写的库。2.4.5中应该不用添加initial_nonfree()这个函数了。运行能够成功。
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) { @Override public void onManagerConnected(int status) { switch (status) { case LoaderCallbackInterface.SUCCESS: { Log.i(Unity.TAG,"OpenCV loaded successfully"); System.loadLibrary("nonfree"); System.loadLibrary("opencv_java"); System.loadLibrary("Surf"); isOpenCVLoad = true; } break; default: { Log.i(Unity.TAG,"OpenCV loaded Failed!"); super.onManagerConnected(status); } break; } } };
一定要顺序加载,否则会报错。至此就能够在JAVA中使用Native函数了。
网上这方面资料很少,希望对大家有所帮助。
相关文章推荐
- 【转+补充】在OpenCV for Android 2.4.5中使用SURF(nonfree module)
- 在OpenCV for Android 2.4.5中使用SURF(nonfree module)
- 在OpenCV for Android 2.4.5中使用SURF(nonfree module)
- 在OpenCV for Android 中使用SURF(nonfree module)
- android opencv2.4.10使用SIFT编译出libnonfree.so
- 编译并使用带有OpenCL模块的OpenCV for android SDK
- <opencv for android 入门积累>Findcontours函数在android中的使用
- android开发 android studio配置opencv for android sdk,使用opencv的java函数
- Android Studio 2.2 让你5分钟配置好 OpenCV for Android(java层和native层都可以使用)
- OpenCV for Android 使用(Linux)
- 编译并使用带有OpenCL模块的OpenCV for android SDK
- <Opencv for Android 调试>加载XML模型,使用SVM.predict出现的NullPointerException问题
- porting android for FreeSkyle imx6 sabre-6q sd-card & nfs
- 如何在Android中使用OpenCV
- Android笔记——startActivityForResult使用
- Android平台下使用OpenCV灰度化图片的两种方式
- opencv for android 教程(环境搭建篇)
- 我的Android使用openCV记录(1)
- 编译OpenCV for Android
- Android NDK——使用Android Studio引用so库,jar包、module以及导入Eclipse项目并使用JNI的正确姿势