Issue with writing FaceRecognizer for Java with OpenCV 2.4.8

I have been given a project based around face recognition written in JavaCV to be improved. The idea was to either rewrite the program using C++ or write JNI bindings to still use Java. I did some research and according to the official website OpenCV as of version 2.4.4 has bindings for Java and Python. And so, since the official website stated so I decided to go with it. Please note I haven't programmed in C++ before nor have I written any JNI wrappers in the past. If the official website didn't state that it includes bindings for Java I would just write it with C++ using Qt Digia.

This way or another I did everything else that I wanted to do with the Java project and was left with the face recognition part. Unfortunately according (Relevant question #1, Relevant question #2) I found out that there is a bug with FaceRecognizer and that JNI wrapper for face recognition has to be written by hand.

I found a pretty good jni c++ java tutorial and I tried to use that with the code mentioned in Relevant question #1 linked above. The screenshot below shows what I have got right now. The code is as follows: LBPHFaceRecognizer.java

import org.opencv.contrib.FaceRecognizer;
public class LBPHFaceRecognizer extends FaceRecognizer
{

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

private static native long n_createLBPHFaceRecognizer();

public LBPHFaceRecognizer()
{
    super(n_createLBPHFaceRecognizer());
}
FaceRecognizer facerec = new LBPHFaceRecognizer();
}  

LBPHFaceRecognizer.c

// 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"

makefile

# Define a variable for classpath
CLASS_PATH = ../bin

# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)

all : facerec.dll

# $@ matches the target, $< matches the first dependancy
facerec.dll : LBPHFaceRecognizer.o
gcc -m64 -Wl,--add-stdcall-alias -shared -o $@ $<

# $@ matches the target, $< matches the first dependancy
LBPHFaceRecognizer.o : LBPHFaceRecognizer.c LBPHFaceRecognizer.h
gcc -m64 -I"C:\Program Files\Java\jdk1.7.0_51\include" -I"C:\Program Files\Java\jdk1.7.0_51\include\win32"  -I"C:\Users\User\Desktop\OPENCVINSTALLATION\opencv" -I"C:\Users\User\Desktop\OPENCVINSTALLATION\opencv\build\java\x64" -c $< -o $@

# $* matches the target filename without the extension
LBPHFaceRecognizer.h : LBPHFaceRecognizer.class
javah -classpath $(CLASS_PATH) $*

clean :
rm LBPHFaceRecognizer.h LBPHFaceRecognizer.o facerec.dll

All in all I managed to create facerec.dll, but there are a number of problems. First when I was creating the facerec.dll the LBPHFacerecognizer.java did not have the import at the top, because it was complaining about it. I added it afterwards just not to see the error. Secondly the .c code complains about everything as seen on the screenshot below.

and interestingly enough it doesn't complain about the jni.h import whereas the header file as seen on screenshot below does.

That's it, can someone have a look at it and tell me if I've done it correctly? Is there something I should change? Are those errors ok considering the fact the the dll has been created? Or maybe someone has done it in the past and is willing to share the dll file. I haven't gotten around to testing it with the java equivalent of JavaCV code yet.

I use OpenCV 2.4.8, Win 7 64bit, Mingw 64 bit, Java 64 bit 7_0_51 release, Eclipse 64 bit.

Thanks in advance.

Answers


  1. #include "jni.h" isn't the same as #include <jni.h> That's why it complains about one and not the other.. Quotations means relative path.. In other words, the file is located in the same folder as your project. Or a sub-folder. Otherwise you use <...> and it includes files in the compiler's search directory.

  2. The signature is taking parameters: JNIEnv*, jclass, jint when it should be: taking JNIEnv*, jclass. Why? Because according to the signature you have on the Java side private static native long n_createLBPHFaceRecognizer();.. it takes no parameters.. However, you have it declared on the native side as taking an int.

  3. According to this signature name: Java_org_matxx_n_createLBPHFaceRecognizer, n_createLBPHFaceRecognizer is in a package called Java_org_matxxx but your java code doesn't seem to be in any package other than "default" package.

  4. If a jni function has an underscore in its name on the Java side, you must replace the underscore with an _1 on the native side.. Example:

Java side (in package com.foo.bar): n_createLBPHFaceRecognizer

Native side: Java_com_foo_bar_n_1createLBPHFaceRecognizer

As a simple work around, it is wise to just not have underscores in the name..


Need Your Help

unhashable type: 'numpy.ndarray' for optimization

python optimization scipy

I was performing the optimization to find out the best fit line, using the scipy.optimize library, to a data set that I generated. But I am getting the error "unhashable type: 'numpy.ndarray'"

Looking for an algorithm to generate a flat 2D map

algorithm random 2d parameterized

I'm not sure if "traditional" random noise-based height-map generation is what I need, because what I want to end up with is a very simple map consisting of two types of region.