Use Android NDK to compile the OpenCV Application

Source: Internet
Author: User

 

Application of OpenCV in Android

Use Android NDK to compile the so Library

Introduction

Use OpenCV2.3 + NDK R6 to compile the OpenCV Face Detection application in the linuxt System

Preparation

Android NDK (r5 or later) http://developer.android.com/sdk/ndk/index.html

OpenCV Android pack http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.3/

Cmake (optional, alternative NDK) http://www.cmake.org/

Note: The http://code.google.com/p/android-opencv/ website says you want to use crystax ndk r4 instead of NDK. It may be necessary for older Android versions. If the NDK cannot be compiled, use crystax ndk r4 to compile it.

 

OpenCV settings

Download OpenCV 2.3.0 for Android from the website and decompress it to a directory, such ~ /Directory

Set OPENCV_PACKAGE_DIR environment variable

$ Export OPENCV_PACKAGE_DIR = ~ /EnCV-2.3.0/

Create an Android Project

 

Create an android project such as study. opencv in eclipse and create a directory named jni under the root directory of the project. Extract the downloaded android-ndk-r6 to a directory, such ~ /

SLAVE ~ /Android-ndk-r6/sample copy Android. mk, Application. mk to study. opencv/jni directory in a sample

Set the compilation script

In Android. mk, include $ (CLEAR_VARS) and add downstream

Include $ (OPENCV_PACKAGE_DIR)/$ (TARGET_ARCH_ABI)/share/opencv/OpenCV. mk

If the application supports arm neon, add the following lines:

Include $ (OPENCV_PACKAGE_DIR)/armeabi-v7a-neon/share/opencv/OpenCV. mk

LOCAL_ARM_NEON: = true

Add the following lines to Application. mk:

APP_STL: = gnustl_static

APP_CPPFLAGS: =-frtti-fexceptions

Note: For details about Android. mk and Application. mk, see android-mk.html and application-mk.html under ndk/docs.

Java layer defines native Interfaces

Create the study. opencv. FaceRec class and define a local interface for face detection.

/**

* 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 );

Generate jni header file

Use the javah command to generate the jni header file

$ Cd ~ /Workspace/study. opencv/bin

$ Javah study. opencv. FaceRec

A study_opencv_FaceRec.h file is generated in the bin directory. Copy the file to the./jni directory.

Note: If the API changes, manually delete the generated. h file. To prevent unexpected errors.

Image Face Detection on layer c

Use the text editor to create a facedetect. cpp in the jni directory to implement image face detection.

Cpp Code

# 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: cocould 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); // write the image to a file

}

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 }},

{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

Use NDK for compilation

Run ndk-build in the project jni directory

$ Cd ~ /Workspace/study. opencv/jni

$ ~ /Android-ndk-r6/ndk-build.

If the compilation is successful, the libs/armeabi/facedetect. so library will be generated under the project.

If any compilation failure occurs, modify the error as prompted.

Call JNI Interface

Use DDMS to push the xml file (located in the OpenCV-2.3.0/armeabi/share/opencv/haarcascades/directory) and image file to data/study. opencv/files.

Create a new thread in the activity and call the FaceRec # detect method.

@ 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/study. opencv/files/haarcascade_frontalface_alt2.xml ",

"/Data/study. opencv/files/wqw1.jpg ",

"/Data/study. opencv/files/wqw1_detected.jpg ");

}

}. Start ();

 

}

Running result

It was tested that correct face recognition for png, jpg, and bmp images was slow.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.