java - 使用 OpenCV 2.4.8 为 Java 编写 FaceRecognizer 的问题

标签 java c++ opencv java-native-interface jniwrapper

我得到了一个基于人脸识别的项目,该项目是用 JavaCV 编写的,需要改进。当时的想法是要么使用 C++ 重写程序,要么编写 JNI 绑定(bind)以仍然使用 Java。我做了一些研究,根据 2.4.4 版的官方网站,OpenCV 具有 Java 和 Python 的绑定(bind)。所以,既然官方网站说了,所以我决定接受它。请注意,我以前没有用 C++ 编程过,也没有编写过任何 JNI 包装器。如果官方网站没有说明它包含 Java 绑定(bind),我会使用 Qt Digia 用 C++ 编写它。

通过这种或另一种方式,我完成了我想对 Java 项目执行的所有其他操作,剩下的就是人脸识别部分。不幸的是,根据(Relevant question #1Relevant question #2),我发现 FaceRecognizer 存在一个错误,并且必须手动编写用于人脸识别的 JNI 包装器。

我找到了一个不错的jni c++ java tutorial我尝试将其与上面链接的相关问题 #1 中提到的代码一起使用。下面的屏幕截图显示了我现在所得到的。 c++ jni project screenshot
代码如下: 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 代码提示所有内容,如下面的屏幕截图所示。 .c code errors

有趣的是,它不会提示 jni.h 导入,而下面屏幕截图中的头文件会提示。
error about jni.h

就是这样,有人可以看一下并告诉我我做的是否正确吗?有什么我应该改变的吗?考虑到 dll 已创建,这些错误是否正常?或者也许有人在过去做过并且愿意共享 dll 文件。我还没有抽出时间用 Java 等效的 JavaCV 代码来测试它。

我使用 OpenCV 2.4.8、Win 7 64 位、Mingw 64 位、Java 64 位 7_0_51 版本、Eclipse 64 位。

提前致谢。

最佳答案

  1. #include "jni.h"#include <jni.h> 不同这就是为什么它提示一个而不是另一个。引号意味着相对路径。换句话说,该文件与您的项目位于同一文件夹中。或子文件夹。否则你使用 <...>它包括编译器搜索目录中的文件。

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

  3. 根据这个签名名称:Java_org_matxx_n_createLBPHFaceRecognizer , n_createLBPHFaceRecognizer在一个名为 Java_org_matxxx 的包中但是您的 Java 代码似乎不在“默认”包以外的任何包中。

  4. 如果 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/

相关文章:

java - 我如何将时间从毫秒转换为日期?

java - sql 中的日期时间更改为我的应用程序中的日期

Java Tomcat UTF-8 问题

C++ for 循环/字符指针 "hack"

c++ - 在 C++ 中调试参数损坏?

c++ - 无法启动程序,访问被拒绝

c++ - 如何在 C++ 中处理多个 opencv 版本

java - Android/Java CheckBox 返回 null,即使已初始化

c++ - 无法用代码 1 编译程序退出

python - OpenCV 错误 : Assertion failed: cant get video feed working