我得到了一个基于人脸识别的项目,该项目是用 JavaCV 编写的,需要改进。当时的想法是要么使用 C++ 重写程序,要么编写 JNI 绑定(bind)以仍然使用 Java。我做了一些研究,根据 2.4.4 版的官方网站,OpenCV 具有 Java 和 Python 的绑定(bind)。所以,既然官方网站说了,所以我决定接受它。请注意,我以前没有用 C++ 编程过,也没有编写过任何 JNI 包装器。如果官方网站没有说明它包含 Java 绑定(bind),我会使用 Qt Digia 用 C++ 编写它。
通过这种或另一种方式,我完成了我想对 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"
生成文件
# 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 位。
提前致谢。
最佳答案
#include "jni.h"
与#include <jni.h>
不同这就是为什么它提示一个而不是另一个。引号意味着相对路径。换句话说,该文件与您的项目位于同一文件夹中。或子文件夹。否则你使用<...>
它包括编译器搜索目录中的文件。签名采用参数:
JNIEnv*, jclass, jint
什么时候应该:服用JNIEnv*, jclass
.为什么?因为根据您在 Java 端的签名private static native long n_createLBPHFaceRecognizer();
.. 它不带任何参数.. 但是,您在 native 端将其声明为采用 int。根据这个签名名称:
Java_org_matxx_n_createLBPHFaceRecognizer
,n_createLBPHFaceRecognizer
在一个名为Java_org_matxxx
的包中但是您的 Java 代码似乎不在“默认”包以外的任何包中。如果 jni 函数在 Java 端的名称中有下划线,您必须将下划线替换为
_1
在 native 方面..示例:
Java 端(在包 com.foo.bar 中):n_createLBPHFaceRecognizer
native 端:Java_com_foo_bar_n_1createLBPHFaceRecognizer
作为一个简单的解决方法,明智的做法是名称中不要包含下划线..
关于java - 使用 OpenCV 2.4.8 为 Java 编写 FaceRecognizer 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22948553/