Неопределенная ссылка на метод opencv во время выполнения при использовании openCV из библиотеки Dynami c - PullRequest
0 голосов
/ 07 февраля 2020

Я разрабатываю приложение 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 на шаге компоновщика, чтобы попытаться заставить библиотеку быть загружен.

...