使用OpenCV 2.4.8编写FaceRecognizer for Java的问题

时间:2014-04-08 21:29:08

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

我已经获得了一个基于JavaCV编写的面部识别项目进行改进。我们的想法是使用C ++重写程序或者编写JNI绑定以使用Java。我做了一些研究,根据官方网站,OpenCV从版本2.4.4开始,它具有Java和Python的绑定。因此,既然官方网站已经说明了,我决定采用它。请注意我以前没有使用C ++编程,也没有编写任何JNI包装器。如果官方网站没有声明它包含Java绑定,我会用C ++使用Qt Digia编写它。

这样或那样,我做了我想用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"

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代码会抱怨所有内容,如下面的屏幕截图所示。.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 个答案:

答案 0 :(得分:2)

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

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

  3. 根据此签名名称:Java_org_matxx_n_createLBPHFaceRecognizern_createLBPHFaceRecognizer位于名为Java_org_matxxx的包中,但您的java代码似乎不在任何其他包中&#34;默认&#34;封装

  4. 如果jni函数在Java端的名称中有下划线,则必须在本机端用_1替换下划线。示例:

  5. Java端(在com.foo.bar包中):n_createLBPHFaceRecognizer

    原生方:Java_com_foo_bar_n_1createLBPHFaceRecognizer

    作为一个简单的解决方法,明智的做法就是不要在名称中加上下划线。