由于项目的关系,需要在Android中使用OpenCV。网上也有很多相关的博文,但由于版本等问题,按照他们的步骤并不能顺利的完成环境的配置。我自己也尝试摸索了几天,现在将我在配置中遇到的问题,陈列出来,希望能给他人有些帮助。
首先需要搭建NDK环境。需要安装Eclipse、Cygwin和android-ndk。具体的安装过程就不在这里陈述,网上有很多这方面的介绍,按照他们的步骤完成即可。我使用的ndk版本是r6b,大家最好选择较高的版本;较低的版本对C++的支持不是很好。
下载OpenCV,我使用的是OpenCV版本是2.3.1,大家可以在http://opencv.willowgarage.com/wiki/Android下载,上面有直接编译好的OpenCV库。该网址上也有环境的配置,大家可以参考。我主要想说在使用OpenCV过程中遇到的问题。
问题1:在创建工程时,要选择Build Target版本Android2.3.1,我之前选择的是Android2.2,在编译cpp文件时,可以正确生成动态库,但在加载apk时,一直没有加载成功,会出现以下问题:
[2011-09-20 19:57:24 - testopencv] Installation failed due to invalid APK file!
[2011-09-20 19:57:24 - testopencv] Please check logcat output for more details.
[2011-09-20 19:57:24 - testopencv] Launch canceled!
(PS:后来测试在Android2.2,apk文件也可以加载成功,可能我当时设置有些错误。如果大家遇到一些奇怪的问题时,可以尝试改变一下Build Target版本)
问题2:Android.mk,该MakeFile文件,我们可以从OpenCV所带的例子中拷贝该文件到我们工程中。只需要修改LOCAL_MODULE和LOCAL_SRC_FILES,改成自己的cpp文件名字和模块名字。下面是我的Android.mk文件的内容
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include ../includeOpenCV.mk
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
#try to load OpenCV.mk from default install location
include $(TOOLCHAIN_PREBUILT_ROOT)/user/share/OpenCV/OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ImageConvert
LOCAL_SRC_FILES := ImageConvert.cpp
#LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
对于$(TOOLCHAIN_PREBUILT_ROOT)/user/share/OpenCV/OpenCV.mk,
该文件是在OpenCV-2.3.1\share\OpenCV中,由于涉及到相对路径,我们也要将OpenCV-2.3.1放在正确的位置。
OpenCV-2.3.1是和workspace放在同一级目录中的。
如下:我的testopencv所在的workspace是OpenCV,OpenCV-2.3.1位置如此。
问题3:Application.mk。将该文件从OpenCV自带的例子中拷贝到自己工程的jni文件夹下面,内容如下:
APP_STL :=gnustl_static
APP_CPPFLAGS :=-frtti -fexceptions
APP_ABI := armeabi
该文件主要是对STL库的一些选择;需要注意的是红色部分,APP_ABI是生成相应硬件平台的机器码。在OpenCV自带的例子的文件中,是armeabi-v7a,生成该平台的机器码,编译时可以成功,但在加载apk时会出现错误或者加载成功,但运行有错误。我们需要改成aremabi。
下面是我的测试代码,从sdcard中读出一张图片,然后保存为另外格式的图片
#include
#include
#include
#include
#include
#include
#include
extern "C"
{
jint Java_com_testopencv_testopencv_ConvertImage(
JNIEnv *env, jobject obj)
{
IplImage *pImg = NULL;
pImg = cvLoadImage("/mnt/sdcard/cat.jpg");
if (pImg == NULL)
{
return 1;
}
cvSaveImage("/mnt/sdcard/cc.bmp", pImg);
return 0;
}
}
这里需要注意修改权限,使我们能够读写sdcard中的文件,在AndroidManifest.xml中加入下面语句
以上描述有些混乱,大家有不太清楚的地方,或者发现有错误的地方,欢迎交流指正。