当前位置:操作系统 > 安卓/Android >>

使用Android NDK编译OpenCV应用

 

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 ,实现图像人脸检测

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);//把图像写入文件 

    

补充:移动开发 , Android ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,