From b422d078f80d6a592eda8a8561b775b34c62428c Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Tue, 22 May 2012 12:21:26 +0000 Subject: [PATCH] Face detection example updated. Dtetection base tracker mode added. --- samples/android/face-detection/CMakeLists.txt | 10 +- samples/android/face-detection/jni/Android.mk | 21 +++++ .../android/face-detection/jni/Application.mk | 3 + .../jni/DetectionBaseTracker.cpp | 53 +++++++++++ .../face-detection/jni/DetectionBaseTracker.h | 53 +++++++++++ .../samples/fd/DetectionBaseTracker.java | 47 ++++++++++ .../src/org/opencv/samples/fd/FdActivity.java | 26 ++++-- .../src/org/opencv/samples/fd/FdView.java | 93 +++++++++++++++---- 8 files changed, 281 insertions(+), 25 deletions(-) create mode 100644 samples/android/face-detection/jni/Android.mk create mode 100644 samples/android/face-detection/jni/Application.mk create mode 100644 samples/android/face-detection/jni/DetectionBaseTracker.cpp create mode 100644 samples/android/face-detection/jni/DetectionBaseTracker.h create mode 100644 samples/android/face-detection/src/org/opencv/samples/fd/DetectionBaseTracker.java diff --git a/samples/android/face-detection/CMakeLists.txt b/samples/android/face-detection/CMakeLists.txt index 3f3234905a..e683dfecee 100644 --- a/samples/android/face-detection/CMakeLists.txt +++ b/samples/android/face-detection/CMakeLists.txt @@ -1,6 +1,14 @@ set(sample example-face-detection) -add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET}) +if(BUILD_FAT_JAVA_LIB) + set(native_deps opencv_java) + ocv_include_modules(opencv_contrib) +else() + set(native_deps opencv_contrib) +endif() + +add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 11 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps}) if(TARGET ${sample}) add_dependencies(opencv_android_examples ${sample}) endif() + diff --git a/samples/android/face-detection/jni/Android.mk b/samples/android/face-detection/jni/Android.mk new file mode 100644 index 0000000000..8881e828aa --- /dev/null +++ b/samples/android/face-detection/jni/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +OPENCV_CAMERA_MODULES:=off + +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_SRC_FILES := DetectionBaseTracker.cpp +LOCAL_C_INCLUDES := $(LOCAL_PATH) +LOCAL_LDLIBS += -llog -ldl + +LOCAL_MODULE := detection_base_tacker + +include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/samples/android/face-detection/jni/Application.mk b/samples/android/face-detection/jni/Application.mk new file mode 100644 index 0000000000..c7de9c761b --- /dev/null +++ b/samples/android/face-detection/jni/Application.mk @@ -0,0 +1,3 @@ +APP_STL := gnustl_static +APP_CPPFLAGS := -frtti -fexceptions +APP_ABI := armeabi-v7a diff --git a/samples/android/face-detection/jni/DetectionBaseTracker.cpp b/samples/android/face-detection/jni/DetectionBaseTracker.cpp new file mode 100644 index 0000000000..b58d832d6f --- /dev/null +++ b/samples/android/face-detection/jni/DetectionBaseTracker.cpp @@ -0,0 +1,53 @@ +#include +#include +#include + +#include +#include + +using namespace std; +using namespace cv; + +vector RectFaces; + +inline void vector_Rect_to_Mat(vector& v_rect, Mat& mat) +{ + mat = Mat(v_rect, true); +} + +JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeCreateObject +(JNIEnv * jenv, jclass jobj, jstring jFileName, jint faceSize) +{ + const char* jnamestr = jenv->GetStringUTFChars(jFileName, NULL); + string stdFileName(jnamestr); + DetectionBasedTracker::Parameters DetectorParams; + if (faceSize > 0) + DetectorParams.minObjectSize = faceSize; + return (jlong)new DetectionBasedTracker(stdFileName, DetectorParams); +} + +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeDestroyObject +(JNIEnv * jenv, jclass jobj, jlong thiz) +{ + delete (DetectionBasedTracker*)thiz; +} + +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeStart +(JNIEnv * jenv, jclass jobj, jlong thiz) +{ + ((DetectionBasedTracker*)thiz)->run(); +} + +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeStop +(JNIEnv * jenv, jclass jobj, jlong thiz) +{ + ((DetectionBasedTracker*)thiz)->stop(); +} + +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeDetect +(JNIEnv * jenv, jclass jobj, jlong thiz, jlong imageGray, jlong faces) +{ + ((DetectionBasedTracker*)thiz)->process(*((Mat*)imageGray)); + ((DetectionBasedTracker*)thiz)->getObjects(RectFaces); + vector_Rect_to_Mat(RectFaces, *((Mat*)faces)); +} \ No newline at end of file diff --git a/samples/android/face-detection/jni/DetectionBaseTracker.h b/samples/android/face-detection/jni/DetectionBaseTracker.h new file mode 100644 index 0000000000..aaceef9868 --- /dev/null +++ b/samples/android/face-detection/jni/DetectionBaseTracker.h @@ -0,0 +1,53 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_opencv_samples_fd_DetectionBaseTracker */ + +#ifndef _Included_org_opencv_samples_fd_DetectionBaseTracker +#define _Included_org_opencv_samples_fd_DetectionBaseTracker +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_opencv_samples_fd_DetectionBaseTracker + * Method: nativeCreateObject + * Signature: (Ljava/lang/String;F)J + */ +JNIEXPORT jlong JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeCreateObject + (JNIEnv *, jclass, jstring, jint); + +/* + * Class: org_opencv_samples_fd_DetectionBaseTracker + * Method: nativeDestroyObject + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeDestroyObject + (JNIEnv *, jclass, jlong); + +/* + * Class: org_opencv_samples_fd_DetectionBaseTracker + * Method: nativeStart + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeStart + (JNIEnv *, jclass, jlong); + +/* + * Class: org_opencv_samples_fd_DetectionBaseTracker + * Method: nativeStop + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeStop + (JNIEnv *, jclass, jlong); + +/* + * Class: org_opencv_samples_fd_DetectionBaseTracker + * Method: nativeDetect + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_org_opencv_samples_fd_DetectionBaseTracker_nativeDetect + (JNIEnv *, jclass, jlong, jlong, jlong); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/samples/android/face-detection/src/org/opencv/samples/fd/DetectionBaseTracker.java b/samples/android/face-detection/src/org/opencv/samples/fd/DetectionBaseTracker.java new file mode 100644 index 0000000000..265bb88a47 --- /dev/null +++ b/samples/android/face-detection/src/org/opencv/samples/fd/DetectionBaseTracker.java @@ -0,0 +1,47 @@ +package org.opencv.samples.fd; + +import org.opencv.core.Mat; +import org.opencv.core.MatOfRect; + +public class DetectionBaseTracker +{ + public DetectionBaseTracker(String filename, int faceSize) + { + mNativeObj = nativeCreateObject(filename, faceSize); + } + + public void start() + { + nativeStart(mNativeObj); + } + + public void stop() + { + nativeStop(mNativeObj); + } + + public void detect(Mat imageGray, MatOfRect faces) + { + nativeDetect(mNativeObj, imageGray.getNativeObjAddr(), faces.getNativeObjAddr()); + } + + public void release() + { + nativeStop(mNativeObj); + nativeDestroyObject(mNativeObj); + mNativeObj = 0; + } + + protected long mNativeObj; + + protected static native long nativeCreateObject(String filename, int faceSize); + protected static native void nativeDestroyObject(long thiz); + protected static native void nativeStart(long thiz); + protected static native void nativeStop(long thiz); + protected static native void nativeDetect(long thiz, long inputImage, long resultMat); + + static + { + System.loadLibrary("detection_base_tacker"); + } +} diff --git a/samples/android/face-detection/src/org/opencv/samples/fd/FdActivity.java b/samples/android/face-detection/src/org/opencv/samples/fd/FdActivity.java index 3aec2a78de..59265e7c56 100644 --- a/samples/android/face-detection/src/org/opencv/samples/fd/FdActivity.java +++ b/samples/android/face-detection/src/org/opencv/samples/fd/FdActivity.java @@ -16,13 +16,18 @@ public class FdActivity extends Activity { private MenuItem mItemFace40; private MenuItem mItemFace30; private MenuItem mItemFace20; + private MenuItem mItemType; private FdView mView; - - public static float minFaceSize = 0.5f; + + private int mDetectorType = 0; + private String[] mDetectorName; public FdActivity() { Log.i(TAG, "Instantiated new " + this.getClass()); + mDetectorName = new String[2]; + mDetectorName[0] = "Cascade"; + mDetectorName[1] = "DBT"; } @Override @@ -57,6 +62,7 @@ public class FdActivity extends Activity { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); mView = new FdView(this); + mView.setDtetectorType(mDetectorType); setContentView(mView); } @@ -67,6 +73,8 @@ public class FdActivity extends Activity { mItemFace40 = menu.add("Face size 40%"); mItemFace30 = menu.add("Face size 30%"); mItemFace20 = menu.add("Face size 20%"); + mItemType = menu.add(mDetectorName[mDetectorType]); + return true; } @@ -74,13 +82,19 @@ public class FdActivity extends Activity { public boolean onOptionsItemSelected(MenuItem item) { Log.i(TAG, "Menu Item selected " + item); if (item == mItemFace50) - minFaceSize = 0.5f; + mView.setMinFaceSize(0.5f); else if (item == mItemFace40) - minFaceSize = 0.4f; + mView.setMinFaceSize(0.4f); else if (item == mItemFace30) - minFaceSize = 0.3f; + mView.setMinFaceSize(0.3f); else if (item == mItemFace20) - minFaceSize = 0.2f; + mView.setMinFaceSize(0.2f); + else if (item == mItemType) + { + mDetectorType = (mDetectorType + 1) % mDetectorName.length; + item.setTitle(mDetectorName[mDetectorType]); + mView.setDtetectorType(mDetectorType); + } return true; } } diff --git a/samples/android/face-detection/src/org/opencv/samples/fd/FdView.java b/samples/android/face-detection/src/org/opencv/samples/fd/FdView.java index 820d74ec65..3127a5a023 100644 --- a/samples/android/face-detection/src/org/opencv/samples/fd/FdView.java +++ b/samples/android/face-detection/src/org/opencv/samples/fd/FdView.java @@ -23,10 +23,48 @@ import android.view.SurfaceHolder; class FdView extends SampleCvViewBase { private static final String TAG = "Sample::FdView"; - private Mat mRgba; - private Mat mGray; - - private CascadeClassifier mCascade; + private Mat mRgba; + private Mat mGray; + private File mCascadeFile; + private CascadeClassifier mCascade; + private DetectionBaseTracker mTracker; + + public final int CASCADE_DETECTOR = 0; + public final int DBT_DETECTOR = 1; + + private int mDetectorType = CASCADE_DETECTOR; + + public static int mFaceSize = 200; + + public void setMinFaceSize(float faceSize) + { + int height = mGray.rows(); + if (Math.round(height * faceSize) > 0); + { + mFaceSize = Math.round(height * faceSize); + } + mTracker.release(); + mTracker = new DetectionBaseTracker(mCascadeFile.getAbsolutePath(), mFaceSize); + } + + public void setDtetectorType(int type) + { + if (mDetectorType != type) + { + mDetectorType = type; + + if (type == DBT_DETECTOR) + { + Log.i(TAG, "Detection Base Tracker enabled"); + mTracker.start(); + } + else + { + Log.i(TAG, "Cascade detectior enabled"); + mTracker.stop(); + } + } + } public FdView(Context context) { super(context); @@ -34,8 +72,8 @@ class FdView extends SampleCvViewBase { try { InputStream is = context.getResources().openRawResource(R.raw.lbpcascade_frontalface); File cascadeDir = context.getDir("cascade", Context.MODE_PRIVATE); - File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml"); - FileOutputStream os = new FileOutputStream(cascadeFile); + mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml"); + FileOutputStream os = new FileOutputStream(mCascadeFile); byte[] buffer = new byte[4096]; int bytesRead; @@ -45,14 +83,15 @@ class FdView extends SampleCvViewBase { is.close(); os.close(); - mCascade = new CascadeClassifier(cascadeFile.getAbsolutePath()); + mCascade = new CascadeClassifier(mCascadeFile.getAbsolutePath()); if (mCascade.empty()) { Log.e(TAG, "Failed to load cascade classifier"); mCascade = null; } else - Log.i(TAG, "Loaded cascade classifier from " + cascadeFile.getAbsolutePath()); + Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath()); - cascadeFile.delete(); + mTracker = new DetectionBaseTracker(mCascadeFile.getAbsolutePath(), 0); + cascadeDir.delete(); } catch (IOException e) { @@ -77,16 +116,29 @@ class FdView extends SampleCvViewBase { capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA); capture.retrieve(mGray, Highgui.CV_CAP_ANDROID_GREY_FRAME); - if (mCascade != null) { - int height = mGray.rows(); - int faceSize = Math.round(height * FdActivity.minFaceSize); - MatOfRect faces = new MatOfRect(); - mCascade.detectMultiScale(mGray, faces, 1.1, 2, 2 // TODO: objdetect.CV_HAAR_SCALE_IMAGE - , new Size(faceSize, faceSize), new Size()); - - for (Rect r : faces.toArray()) - Core.rectangle(mRgba, r.tl(), r.br(), new Scalar(0, 255, 0, 255), 3); + MatOfRect faces = new MatOfRect(); + + if (mDetectorType == CASCADE_DETECTOR) + { + if (mCascade != null) { + mCascade.detectMultiScale(mGray, faces, 1.1, 2, 2 // TODO: objdetect.CV_HAAR_SCALE_IMAGE + , new Size(mFaceSize, mFaceSize), new Size()); + } + } + else if (mDetectorType == DBT_DETECTOR) + { + if (mTracker != null) + { + mTracker.detect(mGray, faces); + } + } + else + { + Log.e(TAG, "Detection method is not selected!"); } + + for (Rect r : faces.toArray()) + Core.rectangle(mRgba, r.tl(), r.br(), new Scalar(0, 255, 0, 255), 3); Bitmap bmp = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.RGB_565/*.ARGB_8888*/); @@ -110,9 +162,14 @@ class FdView extends SampleCvViewBase { mRgba.release(); if (mGray != null) mGray.release(); + if (mCascadeFile != null) + mCascadeFile.delete(); + if (mTracker != null) + mTracker.release(); mRgba = null; mGray = null; + mCascadeFile = null; } } } -- GitLab