it-roy-ru.com

OpenCV - неопределенная ссылка на 'cv :: CascadeClassifier :: deteMultiScale () после обновления NDK

Вчера я обновил свою Android Studio, включающую NDK, до версии 17.0.4754217, и с тех пор я больше не могу запускать свое приложение. Когда я попытался повторно запустить код после обновления, он выдал мне ошибку ABIs [mips64, armeabi, mips] are not supported for platform. Supported ABIs are [armeabi-v7a, arm64-v8a, x86, x86_64], поэтому я исключил их из проекта в своем файле app.gradle следующим образом: abiFilters 'x86', 'x86_64', /*'armeabi',*/ 'armeabi-v7a', 'arm64-v8a'/*, 'mips', 'mips64'*/.

Однако с тех пор у меня возникла проблема с C++-файлом, где я использую OpenCV-функцию cv::CascadeClassifier::detectMultiScale

Всегда отображается ошибка: CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o: In function detectAndDisplay(cv::Mat, double, int, std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >, cv::CascadeClassifier&)': D:\Schule\OpenCV\ARcpp\app\src\main\cpp/native-lib.cpp:158: undefined reference to cv::CascadeClassifier::detectMultiScale(cv::_InputArray const&, std::__ndk1::vector<cv::Rect_<int>, std::__ndk1::allocator<cv::Rect_<int> > >&, double, int, int, cv::Size_<int>, cv::Size_<int>)'.

Я вызываю функцию следующим образом: cascadeClassifier.detectMultiScale(frame_gray, sights, scaleFactor, minNeighbours, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));. Остальная часть кода очень похожа на ту, что показана в OpenCV-учебнике https://docs.opencv.org/2.4/doc/tutorials/objdetect/cascade_classifier/cascade_classifier.html .

В дополнение к NDK я использую CMake и LLDB, и моя включенная библиотека OpenCV - openCVLibrary320. Опять же, все это работало, пока я не скачал упомянутое обновление NDK. 

Остальная часть ошибки, которая всегда появляется при сборке или выполнении приложения: Build command failed. Error while executing process C:\Users\chris\AppData\Local\Android\Sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build D:\Schule\OpenCV\ARcpp\app\.externalNativeBuild\cmake\debug\arm64-v8a --target native-lib} [1/1] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\arm64-v8a\libnative-lib.so FAILED: cmd.exe /C "cd . && C:\Users\chris\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-Android --gcc-toolchain=C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/toolchains/aarch64-linux-Android-4.9/prebuilt/windows-x86_64 --sysroot=C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sysroot -fPIC -isystem C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-Android -D__Android_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -std=c++11 -frtti -fexceptions -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/platforms/Android-21/Arch-arm64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -LC:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/arm64-v8a -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\arm64-v8a\libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -llog ../../../../src/main/jniLibs/arm64-v8a/libopencv_Java3.so -latomic -lm "C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_static.a" "C:/Users/chris/AppData/Local/Android/Sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++abi.a" && cd ." clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed.

Я действительно потерян, надеюсь, кто-то знает ответ. 

3
c_steidl

OpenCV построен с Android_STL = gnustl_static . После обновления ваш NDK вместо этого использует по умолчанию libc ++. Вы можете явно указать Android_STL в вашем app/build.gradle

Android { defaultConfig { externalNativeBuild { cmake {
    arguments '-DANDROID_STL=gnustl_static'
} } } }

(см. пример здесь ).

4
Alex Cohn

Более полный ответ для всех ищущих там. Использование встроенных OpenCVстатических библиотекв вашем проекте с собственным компонентом.

Вот что у меня есть для build.gradle:

defaultConfig {
    minSdkVersion 21
    targetSdkVersion 21
    externalNativeBuild {
        cmake {
            cppFlags "-fexceptions -std=gnu++11"
            arguments '-DANDROID_STL=gnustl_static'
        }
    }
    ndk {
        // Specifies the ABI configurations of your native
        // libraries Gradle should build and package with your APK.
        abiFilters 'armeabi-v7a', 'x86'
        stl = "gnustl_shared"
    }
}

Это CMakeLists.txt:

set(OPENCV_LIBRARIES ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libopencv_video.a
                     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libopencv_imgproc.a
                     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libopencv_core.a
                     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libopencv_highgui.a
                     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libtbb.a
                     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libcpufeatures.a
                     )

if (${Android_ABI} STREQUAL "x86")
    set(OPENCV_LIBRARIES ${OPENCV_LIBRARIES}
                         ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libippiw.a
                         ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libippicv.a
                         ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libittnotify.a
                         )
    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a")
endif()

if (${Android_ABI} STREQUAL "armeabi-v7a")
    set(OPENCV_LIBRARIES ${OPENCV_LIBRARIES}
                         ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${Android_NDK_ABI_NAME}/libtegra_hal.a
                         )
endif()

(затем используйте ${OPENCV_LIBRARIES} для своего target_link_libraries)

1
Roy Shilkrot

Когда вы связываете opencv с исполняемыми файлами вашего проекта, вы всегда должны ссылаться на общую библиотеку -lopencv_core . Но некоторые пакеты требуют дополнительных флагов ссылок. Например, , Если вы используете highgui, как в 

#include <opencv2/highgui/highgui.hpp>

вы должны добавить флаг ссылки opencv_highgui для: -lopencv_highgui .

В вашем случае, CascadeClassifiers определены в 

#include "opencv2/objdetect.hpp"

и, следовательно, требуется ссылка с opencv_objdetect -lopencv_objdetect .

Решение состоит в том, чтобы добавить флаг ссылки -lopencv_objdetect при компиляции.

1
JB Dumont