Ask Your Question
1

Missing createFisherFaceRecognizer method on android.

asked 2014-05-30 05:46:42 -0600

caaarlos gravatar image

updated 2014-05-30 06:15:14 -0600

berak gravatar image

I'm followed this [tutorial] to detect facial expression. I build this using my pc and saved "model->save(fileName)". Now I want to load this on my android phone. But I cant find this method. What I have to do?

Thanks. (http://docs.opencv.org/modules/contrib/doc/facerec/tutorial/facerec_gender_classification.html#id6)

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
5

answered 2014-05-30 06:47:35 -0600

berak gravatar image

updated 2014-05-30 06:51:59 -0600

hi caaarlos,

unfortunately, the createFisherFaceRecognizer() method (as well as the other 2 createXXXFaceRecognizer()) were skipped during the java wrapper code generation, it's a known , yet unsolved problem. you will have to fill in the hole using jni/ndk, and write a replacement.

you will have to build:

  • an .so file with the native c++ code, let's call it facerec.so
  • an additional java wrapper class calling that, FisherFaceRecognizer.java

sadly, can't help much with ndk(no such thing here), but it worked nicely on desktop/eclipse (the dll/so would go right into your project folder), so here's the code (quite a wall of it).


// --- 8< --------- facerec.cpp -------------------------------

#include "jni.h"
#include "opencv2/contrib/contrib.hpp"



#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jlong JNICALL Java_FisherFaceRecognizer_createFisherFaceRecognizer_10(JNIEnv* env, jclass);
JNIEXPORT jlong JNICALL Java_FisherFaceRecognizer_createFisherFaceRecognizer_10(JNIEnv* env, jclass) {
    try {
        cv::Ptr<cv::FaceRecognizer> pfr = cv::createFisherFaceRecognizer();
        pfr.addref(); // this is for the 2.4 branch, 3.0 would need a different treatment here
        return (jlong) pfr.obj;
    } catch (...) {
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "sorry, dave..");
    }
    return 0;
}

JNIEXPORT jlong JNICALL Java_FisherFaceRecognizer_createFisherFaceRecognizer_11(JNIEnv* env, jclass, jint num_components);
JNIEXPORT jlong JNICALL Java_FisherFaceRecognizer_createFisherFaceRecognizer_11(JNIEnv* env, jclass, jint num_components) {
    try {
        cv::Ptr<cv::FaceRecognizer> pfr = cv::createFisherFaceRecognizer(num_components);
        pfr.addref();
        return (jlong) pfr.obj;
    } catch (...) {
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "sorry, dave..");
    }
    return 0;
}

JNIEXPORT jlong JNICALL Java_FisherFaceRecognizer_createFisherFaceRecognizer_12(JNIEnv* env, jclass, jint num_components, jdouble threshold);
JNIEXPORT jlong JNICALL Java_FisherFaceRecognizer_createFisherFaceRecognizer_12(JNIEnv* env, jclass, jint num_components, jdouble threshold) {
    try {
        cv::Ptr<cv::FaceRecognizer> pfr = cv::createFisherFaceRecognizer(num_components,threshold);
        pfr.addref();
        return (jlong) pfr.obj;
    } catch (...) {
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "sorry, dave..");
    }
    return 0;
}

#ifdef __cplusplus
}
#endif

// --- 8< --------- FisherFaceRecognizer.java -----------------

import org.opencv.contrib.FaceRecognizer;
import org.opencv.core.Core;


public class FisherFaceRecognizer extends FaceRecognizer {

    static{ System.loadLibrary("facerec"); }

    private static native long createFisherFaceRecognizer_0();
    private static native long createFisherFaceRecognizer_1(int num_components);
    private static native long createFisherFaceRecognizer_2(int num_components, double threshold);

    public FisherFaceRecognizer () {
        super(createFisherFaceRecognizer_0());
    }
    public FisherFaceRecognizer (int num_components) {
        super(createFisherFaceRecognizer_1(num_components));
    }
    public FisherFaceRecognizer (int num_components, double threshold) {
        super(createFisherFaceRecognizer_2(num_components, threshold));
    }
}

once you got all this compiled (congrats!!), you would call it like this:

   FaceRecognizer  facerec = new FisherFaceRecognizer();
   facerec.load("/sdcard/smile.yml"); // note, that it can't read from apk or zip, so you need to copy it somewhere

   Mat img = ...//test face
   int [] label = new int[1];
   double [] conf = new double[1];
   facerec.predict(img, label, conf);
edit flag offensive delete link more

Comments

Hi @berak, I did what you said to me. But I'm in trouble, ndk build is telling me that it can't find contrib.cpp. Look my sreenshot.http://www.zimagez.com/zimage/screenshot-31-05-2014-110913.php.

If I change facerec.cpp to facerec.so, ndk-build inform that facerec.so is unsupported. See: http://www.zimagez.com/zimage/screenshot-31-05-2014-111158.php

I tried to change include to #include contrib.hpp, because on my include folder there is one folder /usr/local/include/opencv2/contrib. And, again, it not works. I think it is one eclipse problem, because I create one myPatch/test.c and add myPatch/ to my include patch, and eclipse does not found test.c. What do you think about it?

Thanks again to really helping me!!

caaarlos gravatar imagecaaarlos ( 2014-06-01 07:17:22 -0600 )edit
  • there must be a place in eclipse, where you add the include folders, add your_opencv/build/include there. then the include should work as is.

  • no dear, you can't just rename the cpp file to .so, you have to compile it, and the outcome will be the .so, but again, no real idea about ndk

berak gravatar imageberak ( 2014-06-01 07:32:32 -0600 )edit

@berak, look this http://www.zimagez.com/zimage/screenshot-01-06-2014-150638.php

I can import contrib.hpp, but when eclipse build my app, it tells me that contrib.hpp not exists.

caaarlos gravatar imagecaaarlos ( 2014-06-01 13:12:35 -0600 )edit

I managed to compile the example, apparently just tweaking .mk files: In android.mk i added the line:

"include /home/&lt;Path_to&gt;/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk"

And i also created the Application.mk file :

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := x86 armeabi armeabi-v7a
APP_PLATFORM := android-8

(If you don't want to compile for x86 , remove it from APP_ABI)

I hope it helps you

fatmatto gravatar imagefatmatto ( 2014-06-27 02:57:28 -0600 )edit

^^ thanks, @fatmatto, that looks useful ;)

berak gravatar imageberak ( 2014-06-27 03:01:21 -0600 )edit

@berak Hi, thanks for posting this, I came across the same problem and following your answer I think I am close to solving it. I used your code and built the library facerec.so using QT. Then, using netbeans I included the library and the missing wrapper class... so far so good, it compiles without any error message or warning. But then while running my program (just a dummy program to test that this solution works) i get the following error:

symbol lookup error: /usr/local/share/OpenCV/java/libfacerec.so.1.0.0: undefined symbol: _ZN2cv26createFisherFaceRecognizerEid

Needless to say, this caused by the line: FaceRecognizer facerec = new FisherFaceRecognizer();

Do you have any suggestion as to what I may be doing wrong? Cheers!

alfonsord gravatar imagealfonsord ( 2014-10-20 18:18:50 -0600 )edit

@berak, do you know if there any fork of opencv repo with implemented JNI wrappers for all FaceRecognizers?

kemter2013 gravatar imagekemter2013 ( 2015-04-16 22:53:41 -0600 )edit
1

yes, just wait a few days for opencv3 !

berak gravatar imageberak ( 2015-04-17 00:32:59 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2014-05-30 05:46:42 -0600

Seen: 5,313 times

Last updated: May 30 '14