- 浏览: 145595 次
- 性别:
- 来自: 南京
最新评论
-
zbz0425:
不错。。eclipse 4 都能运行。。 官网反而成功安装后没 ...
Java代码质量工具插件之 Eclipse Metrics 插件整改完成 -
jdpxiaoming:
不错,可以使用
使用Android NDK编译OpenCV应用 -
loogson:
melord 写道loogson 写道麻烦问一下,你的Cone ...
OpenGL ES教程V之更多3D模型(原文对照) -
melord:
loogson 写道麻烦问一下,你的Cone类测试了没有,我使 ...
OpenGL ES教程V之更多3D模型(原文对照) -
loogson:
麻烦问一下,你的Cone类测试了没有,我使用你的Cone测试不 ...
OpenGL ES教程V之更多3D模型(原文对照)
OpenCV 在 Android 中的应用
使用 Android NDK 编译 so 库
简介
在 linuxt 系统下使用 OpenCV2.3 + NDK R6 编译 OpenCV 人脸检测应用
准备
Android NDK ( r5 或更高版本 ) http://developer.android.com/sdk/ndk/index.html
OpenCV Android 包 http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.3/
cmake( 可选,替代 NDK) http://www.cmake.org/
注: http://code.google.com/p/android-opencv/ 网站上说要使用 crystax ndk r4 代替 NDK 。估计可能是对于较旧的 Android 版本需要这样。如果 NDK 无法编译,请尝试使用 crystax ndk r4 编译。
OpenCV 设置
从网站上下载 OpenCV 2.3.0 for Android 后,解压到某个目录,如 ~/ 目录下
设置 OPENCV_PACKAGE_DIR 环境变量
$ export OPENCV_PACKAGE_DIR=~/enCV-2.3.0/
新建一个 Android 工程
在 eclipse 中新建一个 android 工程如 study.opencv ,并且在工程根目录下新建一个名为 jni 的目录。将下载的 android-ndk-r6 解压到某个目录下,如 ~/
从 ~/android-ndk-r6/sample 下某个 sample 中拷贝 Android.mk, Application.mk 到 study.opencv/jni 目录
设置编译脚本
在 Android.mk 中, include $(CLEAR_VARS) 后面,加入下行
include $(OPENCV_PACKAGE_DIR)/$(TARGET_ARCH_ABI)/share/opencv/OpenCV.mk
如果应用支持 ARM NEON 那么还需要加入以下行
include $(OPENCV_PACKAGE_DIR)/armeabi-v7a-neon/share/opencv/OpenCV.mk
LOCAL_ARM_NEON := true
在 Application.mk 中加入以下行
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
注:关于 Android.mk 与 Application.mk 的详细说明,请参考 ndk/docs 下 Android-mk.html 和 Application-mk.html 。
Java 层定义 native 接口
新建 study.opencv.FaceRec 类,定义一个人脸检测的本地接口
/**
* detect front face from image.
*
* @param xml
* opencv haarcascade xml file path
* @param infile
* input image file path
* @param outfile
* output image file path
*/
public native void detect(String xml, String infile, String outfile);
生成 jni 头文件
使用 javah 命令生成 jni 头文件
$ cd ~/workspace/study.opencv/bin
$ javah study.opencv.FaceRec
会在 bin 目录生成一个 study_opencv_FaceRec.h 文件。将此文件拷贝到 ../jni 目录中
注:如果接口有变更,请先手动删除生成的 .h 文件。以防止一些意外的错误。
在 c 层实现图像人脸检测
在 jni 目录中使用文本编辑器新建一个 facedetect.cpp ,实现图像人脸检测
#include "cv.h" #include "highgui.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <math.h> #include <float.h> #include <limits.h> #include <time.h> #include <ctype.h> #include <android/log.h> #include <study_opencv_FaceRec.h> #include <jni.h> #define LOG_TAG "opencv_face_detect" #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) static CvMemStorage* storage = 0; static CvHaarClassifierCascade* cascade = 0; void detect_and_draw( IplImage* image ); const char* cascade_name = "haarcascade_frontalface_alt.xml"; /* "haarcascade_profileface.xml";*/ /*int captureFromImage(char* xml, char* filename);*/ char* jstring2String(JNIEnv*, jstring); int captureFromImage(char* xml, char* filename, char* outfile) { LOGI("begin: "); // we just detect image // CvCapture* capture = 0; IplImage *frame, *frame_copy = 0; const char* input_name = "lina.png"; if(xml != NULL) { cascade_name = xml; } if(filename != NULL) { input_name = filename; } LOGI("xml=%s,filename=%s", cascade_name, input_name); // load xml cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); LOGI("load cascade ok ? %d", cascade != NULL ? 1 : 0); if( !cascade ) { LOGI("ERROR: Could not load classifier cascade\n" ); // I just won't write long full file path, to instead of relative path, but I failed. FILE * fp = fopen(input_name,"w"); if(fp == NULL){ LOGE("create failed"); } return -1; } storage = cvCreateMemStorage(0); // cvNamedWindow( "result", 1 ); IplImage* image = cvLoadImage( input_name, 1 ); if( image ) { LOGI("load image successfully"); detect_and_draw( image ); // cvWaitKey(0); if(outfile != NULL) { LOGI("after detected save image file"); cvSaveImage(outfile, image);//把图像写入文件 } cvReleaseImage( &image ); } else { LOGE("can't load image from : %s ", input_name); } } void detect_and_draw( IplImage* img ) { static CvScalar colors[] = { {{0,0,255}}, {{0,128,255}}, {{0,255,255}}, {{0,255,0}}, {{255,128,0}}, {{255,255,0}}, {{255,0,0}}, {{255,0,255}} }; double scale = 1.3; IplImage* gray = cvCreateImage( cvSize(img->width,img->height), 8, 1 ); IplImage* small_img = cvCreateImage( cvSize( cvRound (img->width/scale), cvRound (img->height/scale)), 8, 1 ); int i; cvCvtColor( img, gray, CV_BGR2GRAY ); cvResize( gray, small_img, CV_INTER_LINEAR ); cvEqualizeHist( small_img, small_img ); cvClearMemStorage( storage ); if( cascade ) { double t = (double)cvGetTickCount(); CvSeq* faces = cvHaarDetectObjects( small_img, cascade, storage, 1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/, cvSize(30, 30) ); t = (double)cvGetTickCount() - t; LOGI( "detection time = %gms\n", t/((double)cvGetTickFrequency()*1000.) ); for( i = 0; i < (faces ? faces->total : 0); i++ ) { CvRect* r = (CvRect*)cvGetSeqElem( faces, i ); CvPoint center; int radius; center.x = cvRound((r->x + r->width*0.5)*scale); center.y = cvRound((r->y + r->height*0.5)*scale); radius = cvRound((r->width + r->height)*0.25*scale); cvCircle( img, center, radius, colors[i%8], 3, 8, 0 ); } } // cvShowImage( "result", img ); cvReleaseImage( &gray ); cvReleaseImage( &small_img ); } JNIEXPORT void JNICALL Java_study_opencv_FaceRec_detect (JNIEnv * env, jobject obj, jstring xml, jstring filename, jstring outfile) { LOGI("top method invoked! ");/*LOGI("1"); char * c_xml = (char *)env->GetStringUTFChars(xml, JNI_FALSE); LOGI("char * = %s", c_xml); if(c_xml == NULL) { LOGI("error in get char*"); return; } char * c_file = env->GetStringCritical(env, filename, 0); if(c_xml == NULL) { LOGI("error in get char*"); return; } captureFromImage(c_xml, c_file); env->ReleaseStringCritical(env, xml, c_xml); env->ReleaseStringCritical(env, file_name, c_file); */ captureFromImage(jstring2String(env,xml), jstring2String(env,filename), jstring2String(env,outfile)); } //jstring to char* char* jstring2String(JNIEnv* env, jstring jstr) { if(jstr == NULL) { LOGI("NullPointerException!"); return NULL; } char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); LOGI("char*=%s",rtn); return rtn; }
Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
include $(OPENCV_PACKAGE_DIR)/$(TARGET_ARCH_ABI)/share/opencv/OpenCV.mk
LOCAL_MODULE := facedetect
LOCAL_CFLAGS := -Werror
LOCAL_SRC_FILES := \
facedetect.cpp \
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
Application.mk:
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-10
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
使用 NDK 进行编译
在工程 jni 目 录 下 执 行 ndk-build
$ cd ~/workspace/study.opencv/jni
$ ~/android-ndk-r6/ndk-build.
如果 编译 成功, 则 会在工程下面生成 libs/armeabi/facedetect.so 库 了 .
如有 编译 失 败 , 请 根据提示修改 错误
调用 JNI 接口
将 opencv 人 脸检测 要用到的 xml 文件 ( 位于 OpenCV-2.3.0/armeabi/share/opencv/haarcascades/ 目录下 ) 及 图 像文件使用 DDMS push 到 data/data/study.opencv/files 目 录 中。
在 activity 中新建一个 线 程, 调 用 FaceRec#detect 方法。
@Override
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. main );
final FaceRec face = new FaceRec();
new Thread() {
@Override
public void run() {
face.detect(
"/data/data/study.opencv/files/haarcascade_frontalface_alt2.xml" ,
"/data/data/study.opencv/files/wqw1.jpg" ,
"/data/data/study.opencv/files/wqw1_detected.jpg" );
}
}.start();
}
运行结果
经测试,对png,jpg,bmp图片正确识别人脸,不过速度太慢了。
参考
人 脸检测 http://www.opencv.org.cn/index.php/%E4%BA%BA%E8%84%B8%E6%A3%80%E6%B5%8B
评论
$ $NDK/ndk-build
Compile++ thumb: ImgFun <= /cygdrive/f/Eclipse-IDE-for-Java-EE-Developers/TestOp
enCV/HaveImgFun/jni/ImgFun.cpp
make: *** No rule to make target `/cygdrive/f/Eclipse-IDE-for-Java-EE-Developers
/TestOpenCV/HaveImgFun/obj/local/armeabi/libopencv_contrib.a', needed by `/cygdr
ive/f/Eclipse-IDE-for-Java-EE-Developers/TestOpenCV/HaveImgFun/obj/local/armeabi
/libImgFun.so'. Stop.
之前看了一些网上的评论,说是是要把Android.mk文件中多余的空格去掉,可是去掉之后还是出现了这种问题,请问要如何解决,谢谢!另外,我用这个命令去编译crystax ndk r4下自带的sample文件夹下的文件是可以得到.so文件的,但是一涉及到OpenCV的就无法编译通过,我的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_CPP_EXTENSION := cpp
LOCAL_MODULE := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp
include $(BUILD_SHARED_LIBRARY)
楼主啊,log里面我每次运行都出这个提示,????求解
请确认是你否生成了so库,so库有没有放到指定目录?java代码中是否有loadLibrary()来加载?
楼主啊,log里面我每次运行都出这个提示,????求解
没有哦, 我当初只是简单的用OpenCV实现人脸识别而已,不过,你可以去openCV wiki上查看一下, 我也是按照官网上给的指导 配置mk文件的.
设置 OPENCV_PACKAGE_DIR 环境变量
$ export OPENCV_PACKAGE_DIR=~/enCV-2.3.0/
在这里 $ export OPENCV_PACKAGE_DIR=~/enCV-2.3.0/ 是添加到那个环境变量里?是我的电脑 -》高级-path,还是 cygwin中?
添加到环境变量. 我的是Linux系统,你的是XP系统, 如果不行,也添加到cygwin中吧.
设置 OPENCV_PACKAGE_DIR 环境变量
$ export OPENCV_PACKAGE_DIR=~/enCV-2.3.0/
在这里 $ export OPENCV_PACKAGE_DIR=~/enCV-2.3.0/ 是添加到那个环境变量里?是我的电脑 -》高级-path,还是 cygwin中?
发表评论
-
解决编译Android 4.1.2 Error 41错误
2013-04-12 09:34 42972.3/3.0/3.1/3.2/4.0, 4.2都能编译通 ... -
Anroid自定义View的状态存储
2012-06-08 17:20 0Why? 为什么要存储状态呢?当转屏重新加载,或activi ... -
Thread.join()在AsyncTask中的妙用
2012-06-08 16:29 5361问题 在Android Email当中 ... -
Android中选择账户
2012-05-30 11:40 1667当系统中存在多个账户的时候,需要让用户手动选择或添加账户. A ... -
Android平台邮件自动发送功能实现
2012-03-31 18:01 22426Android 自动发送邮件 本文简述的是在Android平 ... -
黑莓指南针机场代码
2011-08-26 10:08 1250三字代码表 (个别代码可能有误,可直接输入经度纬度) 北京 P ... -
Android attr.xml文件中attr节点format属性有效值
2011-08-22 17:42 2199reference:引用,如其它图片资源 color: ... -
Android ADT插件扩展补丁发布
2011-07-19 21:00 2688项目已经托管到 https://github.com/Jam ...
相关推荐
本文将详细介绍如何使用NDK编译OpenCV源码,并在Android项目中应用。 首先,你需要确保已经安装了Android Studio、Android NDK以及OpenCV的源代码。OpenCV的源代码可以从其官方网站下载,通常包含各种平台的支持,...
在移动应用开发领域,尤其是涉及到图像处理和计算机视觉的应用中,Android NDK(Native Development Kit)结合OpenCV库成为了开发者的首选方案之一。OpenCV(Open Source Computer Vision Library),作为一款开源的...
本教程旨在指导用户如何在 Windows 系统环境下使用 Android NDK 来编译 OpenCV 3-contrib,从而生成安卓开发所需的 `.so` 文件。通过这种方式,开发者可以在 Android Studio 中使用 OpenCV 3 中的非免费(nonfree)...
总之,"opencv-3.4.0-android-sdk"是针对新版本NDK编译的OpenCV库,解决了旧版库与新NDK的兼容性问题,使得开发者能够在享受新NDK带来的优势的同时,利用OpenCV的强大功能进行Android上的计算机视觉开发。在实际应用...
openCV4.6.0+android-ndk-r22-windows-x86_64编译动、静态库(armeabi-v7a) CSDN审核可能较慢,如无法下载,可以过段时间再回来看下 仅供相关爱好者交流使用,请于下载24小时内删除
OpenCV 3.2.0-android-sdk这个压缩包就是为Android平台特别编译的OpenCV版本,适用于NDK 17及以上版本。 OpenCV的官方release版本可能与最新的NDK版本不兼容,因为它们在编译时使用的NDK可能是较旧的。在本案例中,...
总之,通过Android NDK和OpenCV的结合,开发者能够充分利用Android设备的硬件性能,实现高效、低延迟的图像处理和计算机视觉应用。这个过程虽然涉及多个步骤,但一旦设置完成,就能为Android应用带来强大的原生功能...
这是 OpenCV 4.9.0 版本的 Android SDK,适用于 Android 平台的开发者。OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,包含了超过2500种优化的算法。这个 SDK 包含了所有...
### OpenCV 2.4.13 在 Android 不同架构下的编译方法及注意事项 #### 一、准备工作 为了能够顺利地编译 OpenCV 2.4.13 的源码,首先需要确保具备以下环境: 1. **OpenCV 源码版本**:2.4.13 2. **OpenCV 源码路径...
NDK是一组工具,帮助开发者在Android应用中使用C和C++代码。在这个项目中,NDK被用来编译和链接JNI代码,生成.so库文件,这些文件可以在Android设备上运行,提高程序性能。 "so库"是Android平台上的动态链接库,...
在本项目中,NDK被用来编译和运行OpenCV库,因为OpenCV主要是用C++编写的,而Android应用通常使用Java或Kotlin。通过NDK,我们可以在Android应用中调用OpenCV的C++接口,实现高效的人脸检测功能。 3. **人脸检测**...
Qt+openCV学习笔记(十三)openCV4.5.5+android-ndk-r22-windows-x86_64编译的arm64-v8a动、静态库 https://blog.csdn.net/aggs1990/article/details/124526728 CSDN审核可能较慢,如无法下载,可以过段时间再回来...
在Android应用开发中,NDK扮演着至关重要的角色,它允许开发者使用原生代码(如C和C++)来编写部分应用,以提升性能或利用特定硬件功能。 NDK的主要用途包括: 1. **性能优化**:对于计算密集型任务,如图形处理、...
openCV4.6.0+android-ndk-r22-windows-x86_64编译的arm64-v8a动、静态库 https://blog.csdn.net/aggs1990/article/details/124527556 CSDN审核可能较慢,如无法下载,可以过段时间再回来看下 仅供相关爱好者交流使用...
本实例源码提供了一个完整的Android应用开发示例,旨在帮助开发者深入理解和实践Android与OpenCV的集成以及NDK的使用。 一、OpenCV简介 OpenCV是一个强大的跨平台计算机视觉库,它包含了众多图像处理和计算机视觉的...
NDK允许开发者在Android应用中使用原生代码,以实现高性能、低级别的硬件交互以及利用已有的C/C++库。在本案例中,我们关注的是"android-ndk-r26b-darwin.zip",这是一个专为macOS系统设计的NDK版本。 **Android ...
Android NDK则是一个让开发者在Android应用中使用C++代码的工具,它可以提供比Java更高的性能和更低级别的硬件访问。 OpenCV库主要由C++编写,但在Android平台上,通常通过Java API进行调用。然而,这种做法可能会...
Qt+openCV学习笔记(十三)openCV4.5.5+android-ndk-r22-windows-x86_64编译的armeabi-v7a动态库 https://blog.csdn.net/aggs1990/article/details/124526728 CSDN审核可能较慢,如无法下载,可以过段时间再回来看...
Qt+openCV学习笔记(七)openCV4.5.4+android-ndk-r21-windows-x86_64编译arm64-v8a动、静态库, https://blog.csdn.net/aggs1990/article/details/121254838 CSDN审核可能较慢,如无法下载,可以过段时间再回来...
然后使用`ndk-build`或Android Studio的CMake构建系统来编译C++代码。 4. **初始化OpenCV** 在你的应用程序中,通常会在`onCreate`方法中初始化OpenCV: ```java OpenCVLoader.initDebug(); // 或者在非调试...