我已经获得了一个基于JavaCV编写的面部识别项目进行改进。我们的想法是使用C ++重写程序或者编写JNI绑定以使用Java。我做了一些研究,根据官方网站,OpenCV从版本2.4.4开始,它具有Java和Python的绑定。因此,既然官方网站已经说明了,我决定采用它。请注意我以前没有使用C ++编程,也没有编写任何JNI包装器。如果官方网站没有声明它包含Java绑定,我会用C ++使用Qt Digia编写它。
这样或那样,我做了我想用Java项目做的所有其他事情,并留下了面部识别部分。不幸的是(Relevant question #1,Relevant question #2)我发现FaceRecognizer存在一个错误,并且必须手工编写面部识别的JNI包装器。
我找到了一个非常好的jni c++ java tutorial,我尝试将其与上面链接的相关问题#1中提到的代码一起使用。下面的截图显示了我现在所拥有的内容。
代码如下:
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
总而言之,我设法创建了facerec.dll,但是存在许多问题。首先,当我创建facerec.dll时,LBPHFacerecognizer.java没有导入顶部,因为它抱怨它。我之后添加它只是为了不看错误。 其次,.c代码会抱怨所有内容,如下面的屏幕截图所示。
有趣的是它没有抱怨jni.h导入,而头文件如下面的截图所示。
就是这样,有人可以看看它并告诉我,如果我做得对吗?有什么我应该改变的吗?考虑到已创建dll的事实,这些错误是否正常?或者也许有人在过去做过,并且愿意分享dll文件。我还没有用Java等效的JavaCV代码来测试它。
我使用的是OpenCV 2.4.8,Win 7 64位,Mingw 64位,Java 64位7_0_51版本,Eclipse 64位。
提前致谢。
答案 0 :(得分:2)
#include "jni.h"
与#include <jni.h>
不同,这就是为什么它抱怨一个而不是另一个。引用意味着相对路径..换句话说,该文件与项目位于同一文件夹中。或者是子文件夹。否则,您使用<...>
,它包含编译器搜索目录中的文件。
签名采用参数:JNIEnv*, jclass, jint
应该是:JNIEnv*, jclass
。为什么?因为根据您在Java端private static native long n_createLBPHFaceRecognizer();
上的签名,它不需要任何参数。但是,您将它在本机端声明为采用int。
根据此签名名称:Java_org_matxx_n_createLBPHFaceRecognizer
,n_createLBPHFaceRecognizer
位于名为Java_org_matxxx
的包中,但您的java代码似乎不在任何其他包中&#34;默认&#34;封装
如果jni函数在Java端的名称中有下划线,则必须在本机端用_1
替换下划线。示例:
Java端(在com.foo.bar包中):n_createLBPHFaceRecognizer
原生方:Java_com_foo_bar_n_1createLBPHFaceRecognizer
作为一个简单的解决方法,明智的做法就是不要在名称中加上下划线。