使用 OpenCV 2.4.8 为 Java 编写 FaceRecognizer 的问题
Posted
技术标签:
【中文标题】使用 OpenCV 2.4.8 为 Java 编写 FaceRecognizer 的问题【英文标题】:Issue with writing FaceRecognizer for Java with OpenCV 2.4.8 【发布时间】:2014-04-08 21:29:07 【问题描述】:我收到了一个基于 JavaCV 编写的人脸识别的项目,有待改进。这个想法是要么使用 C++ 重写程序,要么编写 JNI 绑定以仍然使用 Java。我做了一些研究,根据官方网站 OpenCV 的版本 2.4.4 有 Java 和 Python 的绑定。所以,既然官网有说明,所以我决定去。请注意,我以前没有用 C++ 编程过,也没有写过任何 JNI 包装器。如果官方网站没有声明它包含 Java 绑定,我只会使用 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 文件。我还没有开始使用 JavaCV 代码的 java 等价物对其进行测试。
我使用 OpenCV 2.4.8、Win 7 64 位、Mingw 64 位、Java 64 位 7_0_51 版本、Eclipse 64 位。
提前致谢。
【问题讨论】:
哦,很抱歉在那儿马虎。也许update 有帮助 现在看起来好多了。为你工作? 您能否详细说明是什么让您离开了 JavaCV?我也许能够修复它的任何问题。谢谢! 【参考方案1】:#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 代码似乎不在“默认”包之外的任何包中。
如果 jni 函数在 Java 端的名称中包含下划线,则必须在本机端将下划线替换为 _1
。示例:
Java 端(在 com.foo.bar 包中):n_createLBPHFaceRecognizer
原生端:Java_com_foo_bar_n_1createLBPHFaceRecognizer
作为一种简单的解决方法,明智的做法是名称中不要包含下划线..
【讨论】:
以上是关于使用 OpenCV 2.4.8 为 Java 编写 FaceRecognizer 的问题的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV-2.4.8.2:imshow 与 imwrite 不同
使用 OpenCV 2.4.8 的 gstreamer 管道程序引发运行时错误
OpenCV:Visual Studio 2013 Ultimate中OpenCV 2.4.8 配置