Проблема с написанием FaceRecognizer для Java с OpenCV 2.4.8

Мне дали проект, основанный на распознавании лиц, написанный на JavaCV, который нужно улучшить. Идея заключалась в том, чтобы либо переписать программу с использованием C++, либо написать привязки JNI, чтобы все еще использовать Java. Я провел некоторые исследования и, согласно официальному сайту OpenCV, начиная с версии 2.4.4, есть привязки для Java и Python. И так, так как официальный сайт заявил, что я решил пойти с ним. Обратите внимание, что я не программировал на C++ раньше и не писал никаких JNI-оболочек в прошлом. Если на официальном сайте не указано, что он содержит привязки для Java, я просто написал бы это на C++, используя Qt Digia.

Так или иначе, я сделал все остальное, что хотел сделать с проектом Java, и у меня осталась часть распознавания лиц. К сожалению, согласно ( Соответствующий вопрос № 1, Соответствующий вопрос № 2) я обнаружил, что в FaceRecognizer есть ошибка и что JNI-оболочка для распознавания лиц должна быть написана от руки.

Я нашел довольно хорошее руководство по jni C++ java и попытался использовать его с кодом, упомянутым в соответствующем вопросе № 1, связанном выше. На скриншоте ниже показано, что я получил прямо сейчас.C++ JNI скриншот проекта
Код выглядит следующим образом: 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 код ошибки

и что интересно, он не жалуется на импорт jni.h, тогда как заголовочный файл, как видно на скриншоте ниже, делает.
ошибка о jni.h

Вот и все, может кто-нибудь взглянуть на это и сказать мне, правильно ли я это сделал? Есть что-то, что я должен изменить? Эти ошибки в порядке, учитывая тот факт, что DLL был создан? Или, может быть, кто-то делал это в прошлом и хочет поделиться файлом DLL. Я еще не удосужился протестировать его с помощью Java-кода JavaCV.

Я использую OpenCV 2.4.8, Win 7 64 бит, Mingw 64 бит, Java 64 бит 7_0_51 релиз, Eclipse 64 бит.

Заранее спасибо.

1 ответ

  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_createLBPHFaceRecognizer, n_createLBPHFaceRecognizer находится в пакете под названием Java_org_matxxx но ваш код Java, кажется, не находится ни в каком пакете, кроме пакета "по умолчанию".

  4. Если у функции jni есть подчеркивание в ее имени на стороне Java, вы должны заменить подчеркивание на _1 на родной стороне.. Пример:

Сторона Java (в пакете com.foo.bar): n_createLBPHFaceRecognizer

Родная сторона: Java_com_foo_bar_n_1createLBPHFaceRecognizer

В качестве простого обходного решения целесообразно не использовать подчеркивания в названии.

Другие вопросы по тегам