Я разрабатываю приложение Java для распознавания лиц на основе OpenCV (обработка изображений) и dlib (определение ориентира лица). Для этого я собрал и установил обе библиотеки вручную.
> git clone https://github.com/opencv/opencv.git
> cd opencv
> git checkout 3.4 && git reset --hard && git clean -qfdx
> mkdir release
> cd release
> cmake -D BUILD_SHARED_LIBS=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..
> make -j8
> make install
> cd ..
> git clone https://github.com/davisking/dlib.git
> cd dlib
> mkdir build
> cd build
> cmake --config Release -DBUILD_SHARED_LIBS=1 ..
> make -j 8
> make install
Я не видел способа создания привязки Java для dlib. Итак, мой подход заключается в создании динамической c библиотеки в C, которая выполняет некоторую операцию смешивания dlib и opencv.
В моем приложении Java я создал класс Java (ShapePredictor) с соответствующие нативные методы
public final class ShapePredictor {
static {
System.loadLibrary("dlibsp");
}
public final long nativeObj;
ShapePredictor(String file) {
nativeObj = n_shape_predictor(file);
}
public long predict(Mat img, int rowStart, int rowEnd, int colStart, int colEnd) {
long nativeLandmarks = n_predict(nativeObj, img.nativeObj, colStart, colEnd, rowStart, rowEnd);
return landmarks;
}
@Override
protected void finalize() throws Throwable {
n_delete(nativeObj);
super.finalize();
}
static native long n_predict(long nativeObj, long img, int rowStart, int rowEnd, int colStart, int colEnd);
static native long n_shape_predictor(String filePath);
// native support for java finalize()
static native void n_delete(long nativeObj);
}
После этого я создал файл заголовков (dlibsp / shape_predictor_ java .h)
javah -jni -cp target/face_recognition.jar -o build/include/dlibsp/shape_predictor_java.h es.bsc.compss.apps.utils.aligners.face.DlibAligner.ShapePredictor
и записал файл cpp (shape_predictor_ *) 1033 *. cpp) реализация таких методов.
#include <dlib/image_processing/shape_predictor.h>
#include <dlib/image_processing.h>
#include <dlib/opencv/cv_image.h>
#include <dlib/opencv.h>
#include <dlibsp/shape_predictor_java.h>
#include <opencv2/opencv.hpp>
#include <opencv2/objdetect/objdetect.hpp>
jlong Java_es_bsc_compss_apps_utils_aligners_face_DlibAligner_00024ShapePredictor_n_1shape_1predictor( JNIEnv *env, jclass obj, jstring path)
{
const char *str = (env)->GetStringUTFChars(path, 0);
dlib::shape_predictor *sp = new dlib::shape_predictor();
dlib::deserialize(str) >> *sp;
(env)->ReleaseStringUTFChars(path, str);
return (jlong)sp;
}
jlong Java_es_bsc_compss_apps_utils_aligners_face_DlibAligner_00024ShapePredictor_n_1predict(JNIEnv *env, jclass obj, jlong me, jlong mat_ptr, jint x_start, jint x_end, jint y_start, jint y_end)
{
dlib::shape_predictor *sp_ptr = (dlib::shape_predictor *)me;
dlib::shape_predictor sp = *sp_ptr;
cv::Mat *img = (cv::Mat *)mat_ptr;
cv::Mat img_cv = *(img);
cv::Mat gray;
cv::cvtColor(img_cv, gray, cv::COLOR_BGR2GRAY);
return (jlong) new cv::Mat(gray);
}
void Java_es_bsc_compss_apps_utils_aligners_face_DlibAligner_00024ShapePredictor_n_1delete(JNIEnv *env, jclass obj, jlong self)
{
delete (dlib::shape_predictor *)self;
}
Я компилирую файл для создания объекта .o, а затем создаю библиотеку .so со следующими командами:
cc -c -std=c++0x -fPIC -fpermissive shape_predictor_java.cpp -o shape_predictor_java.o -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64//include/linux -I/usr/local/include -Ibuild/include
cc -shared -Wl,-soname,libdlibsp.so -o libdlibsp.so shape_predictor_java.o -Wl,-rpath,/usr/local/lib:/usr/local/share/OpenCV/java -L/usr/local/lib -ldlib -L/usr/local/share/OpenCV/java -lopencv_java349
* 1017 Наконец, я скопировал файл библиотеки include и Dynami c в папку / usr / local / lib. При запуске приложения Java моя библиотека загружается нормально. Объект shape_predictor создан правильно, и когда вызывается метод прогнозирования, возникает ошибка
java: symbol lookup error: /usr/local/lib/libdlibsp.so: undefined symbol: _ZN2cv8cvtColorERKNS_11_InputArrayERKNS_12_OutputArrayEii
Я запустил nm на /usr/local/share/OpenCV/java/libopencv_java349.so, и там есть символ , Я также выполнил ldd в своей библиотеке, и по какой-то причине libopencv_java349 не указан в качестве зависимости. Таким образом, похоже, что существует какая-то проблема со связью.
ldd /usr/local/lib/libdlibsp.so
linux-vdso.so.1 => (0x00007ffed6100000)
libdlib.so.19.19.99 => /usr/local/lib/libdlib.so.19.19.99 (0x00007f3c048ea000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3c046d4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3c0430a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3c040ed000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f3c03d6b000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3c03a62000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3c05045000)
Я попытался добавить /usr/local/share/OpenCV/java/libopencv_java349.so в LD_LIBRARY_PATH и добавил флаг -Wl, -rpath на шаге компоновщика, чтобы попытаться заставить библиотеку быть загружен.