使用 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 &lt;jni.h&gt; 不同,这就是为什么它抱怨一个而不是另一个的原因。引号表示相对路径。换句话说,该文件与您的文件位于同一文件夹中项目。或子文件夹。否则,您使用&lt;...&gt;,它包含编译器搜索目录中的文件。

    签名正在接受参数:JNIEnv*, jclass, jint,当它应该是:接受JNIEnv*, jclass。为什么?因为根据您在 Java 端 private static native long n_createLBPHFaceRecognizer();.. 的签名,它不带任何参数。但是,您在本机端将其声明为采用 int。

    根据此签名名称:Java_org_matxx_n_createLBPHFaceRecognizern_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 配置

OpenCV入门教程之一 OpenCV 2.4.8 +VS2010的开发环境配置

在 Python 中使用 Opencv 从图像中减去背景

在 OpenCV、Java 中从 Mat 中减去 double