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.