Неопределенная ссылка на 'cv::initModule_nonfree()' в Android

Я хочу создать приложение для Android, которое использует BOW + SVM в собственном коде (с использованием C++) для прогнозирования. К сожалению, у меня проблема с созданием нативной части. Поскольку несвободный модуль не включен в OpenCV SDK для Android, мне нужно собрать модуль самостоятельно, используя это руководство< /а>. Кажется, я успешно создал файл .so. Вот результат:

[armeabi-v7a] Prebuilt       : libopencv_java.so <= /home/crash-id/Development/SDK/OpenCV-2.4.9-android-sdk/sdk/native/jni/../libs/armeabi-v7a/
[armeabi-v7a] SharedLibrary  : libnonfree.so
[armeabi-v7a] Install        : libnonfree.so => libs/armeabi-v7a/libnonfree.so
[armeabi-v7a] Install        : libopencv_java.so => libs/armeabi-v7a/libopencv_java.so

Итак, проблема возникает здесь, когда мне нужно добавить этот файл .so в свой проект. Я добавил libnonfree.so в свою папку jni. Затем я отредактировал файл Android.mk. Здесь я предоставляю свои файлы .mk.

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := nonfree_prebuilt
LOCAL_SRC_FILES := libnonfree.so
include $(PREBUILT_SHARED_LIBRARY)


include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES   := on
OPENCV_INSTALL_MODULES  := on

include /home/crash-id/Development/SDK/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk
#LOCAL_SHARED_LIBRARIES := nonfree_prebuilt #if I add this, it says undefined reference for everything in the cv namespace.
LOCAL_SRC_FILES  := SVMDetector.cpp
LOCAL_MODULE     := svm_detector

LOCAL_C_INCLUDES        += /home/crash-id/Development/SDK/OpenCV-2.4.9-android-sdk/sdk/native/jni/include

LOCAL_CFLAGS            := -Werror -O3 -ffast-math 
LOCAL_LDLIBS            += -llog -ldl 

include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions

APP_ABI := armeabi-v7a

APP_PLATFORM := android-15

Но это не работает. Когда я пытаюсь собрать приложение, я получаю следующую ошибку:

./obj/local/armeabi-v7a/objs/svm_detector/SVMDetector.o: in function Java_org_elsys_thesisdiploma_cammect_FrameProcess_SVMDetect:jni/SVMDetector.cpp:23: error: undefined reference to 'cv::initModule_nonfree()'

Когда я нажимаю правую кнопку на initModule_nonfree();, Eclipse открывает файл nonfree.hpp, и вот его содержимое:

#ifndef __OPENCV_NONFREE_HPP__
#define __OPENCV_NONFREE_HPP__

#include "opencv2/nonfree/features2d.hpp"

namespace cv
{

CV_EXPORTS_W bool initModule_nonfree();

}

#endif

Но я не уверен, что компоновщик знает, где реализация этого метода. Так как это дает ошибку, это не так.

ИЗМЕНИТЬ

Если я добавлю LOCAL_ALLOW_UNDEFINED_SYMBOLS := true, проект успешно скомпилируется, но вызовет ошибку времени выполнения:

 02-17 00:15:58.197: E/AndroidRuntime(8793): FATAL EXCEPTION: main
02-17 00:15:58.197: E/AndroidRuntime(8793): Process: com.example.cammect, PID: 8793
02-17 00:15:58.197: E/AndroidRuntime(8793): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN2cv18initModule_nonfreeEv" referenced by "libsvm_detector.so"...

Вы знаете, что я делаю неправильно? Заранее спасибо!


person dephinera    schedule 13.02.2015    source источник
comment
Вы можете скомпилировать демонстрационную программу (test_sift.cpp) с Android.mk, вложенным в zip-файл?   -  person Kornel    schedule 16.02.2015
comment
Я еще не пробовал. Попробую еще раз написать. Как вы думаете, все ли в порядке с моими скриптами mk?   -  person dephinera    schedule 16.02.2015
comment
Нет, потому что компоновщик не сможет разрешить несвободные символы в отсутствие LOCAL_SHARED_LIBRARIES.   -  person Kornel    schedule 16.02.2015
comment
Но, как я сказал в вопросе, если я добавлю строку с LOCAL_SHARED_LIBRARIES, в ней будет указана неопределенная ссылка для всего в пространстве имен cv.   -  person dephinera    schedule 16.02.2015
comment
Я запустил демонстрационный проект отсюда web.guohuiwang.com/technical-notes/ с успех. Тем не менее я не знаю, как исправить мое приложение.   -  person dephinera    schedule 16.02.2015
comment
У вас есть идеи, что делать?   -  person dephinera    schedule 16.02.2015
comment
найди мой ответ ниже   -  person Kornel    schedule 17.02.2015


Ответы (2)


Моя среда разработки настроена следующим образом:

Сборка несвободного модуля

  1. На самом деле нам нужно только скопировать несколько файлов из OpenCV-2.4.10 исходного кода в OpenCV-2.4.10-android-sdk, а именно:
    Скопируйте nonfree папка с OpenCV-2.4.10\sources\modules\nonfree\include\opencv2\ по OpenCV-2.4.10-android-sdk\sdk\native\jni\include\opencv2.

  2. Создайте папку для хранения нашего нового проекта для libnonfree.so. Здесь я называю это libnonfree. Создайте папку jni в папке libnonfree. Скопируйте следующие файлы из папки OpenCV-2.4.10\sources\modules\nonfree\src в папку libnonfree\jni\:

  3. Здание libnonfree.so:
    создайте сценарии Android.mk и Application.mk. Этот Android.mk используется для сборки libnonfree.so.

    cd в папку проекта libnonfree и введите ndk-build для создания файла libnonfree.so.

На данный момент у вас есть libnonfree.so вместе с libopencv_java.so и libgnustl_shared.so в папке libnonfree\libs\armeabi-v7a.
Вы можете легко создавать любые приложения SIFT или SURF, используя эти библиотеки. Если вы хотите использовать SIFT и SURF в коде JAVA в своем приложении для Android, вам нужно написать интерфейсы JNI только для тех функций, которые вы хотите использовать.

Создание примера приложения

  1. Создайте папку проекта с именем libnonfree_demo. Создайте папку jni внутри папки проекта. Затем скопируйте libnonfree.so вместе с libopencv_java.so и libgnustl_shared.so в jni.

  2. Создайте nonfree_jni.cpp в jni. Это простая тестовая программа SIFT. Он в основном считывает изображение и определяет ключевые точки, затем извлекает дескрипторы функций и, наконец, рисует ключевые точки в выходном изображении.

  3. Создайте Android.mk и Application.mk внутри jni:

    cd в папку проекта libnonfree_demo и введите ndk-build для создания файла libnonfree_demo.so.

На этом этапе вы можете легко расширить пример приложения с помощью вашего SVMDetector. Просто скопируйте исходный код и включите файлы в папку libnonfree_demo\jni и добавьте файлы cpp в LOCAL_SRC_FILES в Android.mk.

Весь исходный код можно загрузить по адресу: https://github.com/bkornel/opencv_android_nonfree.

Исходный источник: http://web.guohuiwang.com/technical-notes/sift_surf_opencv_android.

person Kornel    schedule 17.02.2015
comment
@Kornel, это отличное резюме. И хорошее обновление нового пакета OpenCV. Я давно не обновлял эту статью (извините, слишком ленив). Я прикреплю эту ссылку к статье, чтобы люди, которым нужна более новая информация, могли извлечь пользу из вашего отличного ответа. - person Robert Wang; 18.03.2015
comment
@kornel Я выполнил этот шаг, но он не работает. Я получаю следующую ошибку. В файле, включенном из jni/nonfree_init.cpp:43:0: jni/precomp.hpp:46:22: фатальная ошибка: cvconfig.h: Нет такого файла или каталога #include cvconfig.h ^ компиляция прекращена. make.exe: *** [obj/local/armeabi-v7a/objs/nonfree/nonfree_init.o] Ошибка 1 - person nawara; 23.03.2015
comment
Вы должны поместить строку #include "cvconfig.h" в комментарий в precomp.hpp. - person Kornel; 23.03.2015
comment
Если вы ищете предварительно скомпилированные файлы libnonfree.so. В этом репозитории github есть: github.com/beartung/nonfree-opencv-android - person Taiko; 14.12.2015
comment
@Kornel Как я могу получить несвободные библиотеки в OpenCV 3.1 для Android? - person xsorifc28; 04.02.2016
comment
@Kornel LOCAL_SRC_FILES указывает на ошибку отсутствия файла в ndk-build. можете ли вы ответить stackoverflow.com/questions/42874357/ вопрос - person Yirga; 18.03.2017
comment
@Kornel У меня возникли проблемы с вашим уроком, не могли бы вы мне помочь? stackoverflow.com/questions/44212588/ Спасибо - person Megatron300; 27.05.2017
comment
Есть ли обновленная версия этого процесса для 2.4.13.3? Все, что старше, имеет уязвимость libpng и не может быть загружено в игровой магазин. - person Dale; 18.08.2017

Могу ли я добавить, что для использования новых библиотек в работающем приложении необходимо выполнить следующие шаги:

1) в вашей папке libnonfree/libs/[ЦЕЛЕВАЯ ПЛАТФОРМА]/ теперь 3 файла: - libgnustl_shared.so - libnonfree.so - libopencv_java.so

в вашем собственном проекте (моя IDE - это Android Studio) у вас есть папка src/main/ с подпапками: - java - res

создайте новую папку (если ее еще нет): «jniLibs» [эта папка автоматически анализируется Gradle]

КОПИРУЙТЕ 3 вышеупомянутые папки из "libnonfree/libs/" в папку "jniLibs". вы получите такую ​​структуру: скриншот папки jniLibs

/app/src/main/jniLibs/[armeabi, armeabi-v7a, ...]/[libgnustl_shared.so, libopencv_java.so, libnonfree.so]

2) Где-то в вашем коде есть такая строка:

OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION
    if(!OpenCVLoader.initDebug())
    {

    }
    else
    {
        System.loadLibrary("nonfree");
    }
4_10, this, mLoaderCallback);

эта строка указывает вашему приложению динамически загружать предварительно скомпилированную библиотеку из локально установленного диспетчера OpenCV. Чтобы использовать самостоятельно скомпилированную несвободную версию, мы заменим приведенную выше строку следующей:

    if(!OpenCVLoader.initDebug())
    {

    }
    else
    {
        System.loadLibrary("nonfree");
    }

теперь мы позаботились о том, чтобы использовать несвободные библиотеки, которые мы предоставляем вместе с приложением.

3) запускаем дескриптор SURF:

Bitmap mPhotograph = BitmapFactory.decodeFile(_image_path);
Mat real_image = new Mat();
Utils.bitmapToMat(mPhotograph, real_image);
MatOfKeyPoint keypoints_real = new MatOfKeyPoint();
FeatureDetector detector = FeatureDetector.create(FeatureDetector.SURF);
detector.detect(real_image, keypoints_real);

в то время как раньше приложение возвращалось с плохим сигналом, на этот раз оно выполняет свою работу, и вы можете оценить полученные ключевые точки.

person CKBergen    schedule 07.10.2015
comment
Если вам нужны предварительно скомпилированные файлы .so. Вот они: github.com/beartung/nonfree-opencv-android/ дерево/мастер/библиотеки - person Taiko; 14.12.2015
comment
Этот ответ + готовые файлы libnonfree.so и libopencv_java.so сотворили со мной чудеса. (По какой-то причине мне не нужно было добавлять libgnustl_shared.so) - person Taiko; 14.12.2015