0

I have been developing with OpenCV (Java) on Eclipse. I am now to the point that I need to create a FisherFace for my FaceRecognizer class. Based on my searches, I found out that there doesn't seem to be any support for this. According to this question, it seems like it has to do with the Ptr class. Is it that Java doesn't have a Ptr class to handle the returned Ptr value? If so, then will this Java Ptr class handle it? If this is not a solution, is there any tutorials that can guide me on making the FaceRecognizer class? Thank you!

Community
  • 1
  • 1

1 Answers1

1

the whole problem is on the c++ side, so your java Ptr class won't help.

with opencv 2.4.8, you could try to rebuild the jni-adapter:

(note, that the cv::Ptr class in opencv3.0 won't be compatible with that)


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


extern "C" {


JNIEXPORT jlong JNICALL Java_org_matxx_n_createLBPHFaceRecognizer(JNIEnv* env, jclass, jint);

JNIEXPORT jlong JNICALL Java_org_matxx_n_createLBPHFaceRecognizer(JNIEnv* env, jclass, jint)
{
    try {

        cv::Ptr<cv::FaceRecognizer> ptr = cv::createLBPHFaceRecognizer();
        cv::FaceRecognizer * pf = ptr.get();
        ptr.addref(); //don't let it self-destroy here..
        return (jlong) pf;
    } catch (...) {
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "sorry, dave..");
    }
    return 0;
}
} // extern "C"

and a java 'factory' for that :


// LBPHFaceRecognizer.java

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


public class LBPHFaceRecognizer extends FaceRecognizer
{
    static{ System.loadLibrary("facerec.dll"); }

    private static native long n_createLBPHFaceRecognizer();

    public LBPHFaceRecognizer()
    {
        super(n_createLBPHFaceRecognizer());
    }
}

later, you can create a face reco:


FaceRecognizer facerec = new LBPHFaceRecognizer();
berak
  • 39,159
  • 9
  • 91
  • 89
  • Thank you! What do I do to make this work? I understand that the second batch of code is used to make a Class in my Java Project right? And I can access that from your third line of code. But what is the first line and how do I use it? Is it to make the "facerec.dll" and just copy that to my Java Project folder? Last question, what about FisherFace or Eigenface? Thank you for your feedback! It is really helpful! – Maxwell Tsai Feb 19 '14 at 13:37
  • 1. - you'll have to build a dll/so from the 1st part using jni and a c++ compiler(and ofc. the opencv libs) 2. - just replace LBPH with Fisher or Eigen – berak Feb 19 '14 at 13:41
  • Thank you, last question, will this work under Linux and Mac? I hope it works under Linux at least. Thank you! – Maxwell Tsai Feb 19 '14 at 15:45
  • you'll have to rebuild the dll/so for each os – berak Feb 19 '14 at 15:48
  • I compiled everything and can now create the FaceRecognizer in my java code, but I am still having issues with the predict method. Save/Load/ work fine, but the only predict method that is exposed is this one: `public void predict(org.opencv.core.Mat src, int[] label, double[] confidence)` Which does not match the C++ function, which requires two pointers. Do I also have to fix this with a new JNI mapping? – Nicholas Apr 04 '14 at 07:17
  • oh, let me check that – berak Apr 04 '14 at 07:20
  • @Nicholas, could not find any problem, C++ function is taking jdoubleArray, not pointers – berak Apr 04 '14 at 08:02
  • I am probably getting something wrong. I checked the [opencv docs](http://docs.opencv.org/modules/contrib/doc/facerec/facerec_api.html?highlight=facerecognizer#FaceRecognizer%20:%20public%20Algorithm) where this signature is listed: ` virtual void predict(InputArray src, int &label, double &confidence) const = 0;` I would expect to pass in a pointer to a label that can be written and a pointer to a double for the confidence value - not an array? If I pass in empty arrays to the FaceRecognizer I get null as the result. – Nicholas Apr 04 '14 at 11:24
  • 3
    `facerec = new LBPHFaceRecognizer(8,8); Mat m = Mat.eye(32,32,0); Mat z = Mat.zeros(32,32,0); List src = new ArrayList(); src.add(z); src.add(z); src.add(m); Mat labels = new Mat(1,3, CvType.CV_32S); int [] l = {1,2,3}; labels.put(0, 0, l); facerec.train(src, labels); int [] label = new int[1]; double [] conf = new double[1]; facerec.predict(m, label, conf); System.out.println("rec " + label[0] + " " + conf[0]); // rec 3 0.0` – berak Apr 04 '14 at 12:12