OpenCV - 在NDK更新后出现“未定义引用到'cv::CascadeClassifier::detectMultiScale()'”问题

4
昨天我更新了我的Android Studio,包括NDK到版本17.0.4754217,自那以后我就无法再运行我的应用程序了。在更新后尝试重新运行代码时,它给出了错误信息ABIs [mips64, armeabi, mips]不支持该平台。支持的 ABIs 是 [armeabi-v7a、arm64-v8a、x86 和 x86_64],所以我在app.gradle文件中将它们从项目中排除,方法如下:abiFilters 'x86', 'x86_64', /*'armeabi',*/ 'armeabi-v7a', 'arm64-v8a'/*, 'mips', 'mips64'*/
然而,自那以后我在使用OpenCV函数cv::CascadeClassifier::detectMultiScale的C++文件中遇到了问题。
它总是显示错误: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.

我真的很困惑,希望有人知道答案。


我在使用最新的Android版本3.4.2时也遇到了相同的错误。无法使用“gnustl_static”作为参数,因为它现在不受NDK支持。需要帮助! - Sar
5个回答

6

OpenCV使用ANDROID_STL=gnustl_static进行构建。 升级后,您的NDK将使用默认的libc ++。 您可以在app / build.gradle中明确设置ANDROID_STL:

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

(查看示例此处


“gnustl_static”不再受支持。有没有什么解决方法? - Sar
@Sar:你可以使用c++_shared重新构建OpenCV,或者下载一个旧版本的NDK。 - Alex Cohn
2
我不知道如何使用c++_shared重新构建OpenCV。如果您能提供任何参考资料,那将会很有帮助。谢谢您的提示。 - Sar

2

当您将OpenCV与您的项目可执行文件链接时,您总是需要链接通用库-lopencv_core。但有些包需要额外的链接标志。例如,如果您使用高GUI,就像

#include <opencv2/highgui/highgui.hpp>

你需要为以下内容添加opencv_highgui链接标志:-lopencv_highgui。 在你的情况下,CascadeClassifiers被定义在:
#include "opencv2/objdetect.hpp"

因此需要与opencv_objdetect建立链接,代码中需添加链接标志“-lopencv_objdetect”。
解决方案是在编译时添加链接标志“-lopencv_objdetect”。

非常感谢您的回复,不幸的是我并不太清楚如何在Android Studio中完成这个任务。 - c_steidl
我刚刚注意到我已经在我的C++代码中包含了#include <opencv2/objdetect/objdetect.hpp>。这是你的意思吗?因为添加或删除它对上述错误没有影响。 - c_steidl

1
对于所有寻求帮助的人来说,这是一个更完整的答案。在本地组件中使用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()

然后在target_link_libraries中使用${OPENCV_LIBRARIES}


1

以下是关于链接的第一条评论,可以节省您很多时间:

"我有类似的问题。结果发现你必须使用与构建OpenCV Android SDK相同的Android NDK,对于版本~3.4来说,这是Android NDK 10。最近,发布了OpenCV Android SDK 4.0.1,它可以与最新的NDK版本(目前为19)一起使用。"

在本帖发布时,您可以找到4.1.2版本。您可以在此链接上检查是否有最新版本发布。

在选择最新版本(本例中为4.1.2)后,下载opencv-4.1.2-android-sdk.zip文件,解压缩并将sdk/native文件夹复制到yourprojectfolder/your-app/src/sdk/目录下。您已经准备就绪。

0

我通过使用混合 this OpenCV + contrib lib (opencv4_1_0_contrib) 和 official Java OpenCV 类(4.3)来解决了这个问题。成功在 Android 9 上运行了官方 OpenCV FaceDetection 示例。


一些有用的代码:

应用级别的 build.gradle 文件:

android{defaultConfig{
//...
externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
                abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
                //I import OpenCV as module and provide it path to CMake
                arguments "-DOpenCV_DIR=/" + rootProject.projectDir.path + "/sdk/native"
             }
        }
}}

externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }

My CMakeLists.txt:

# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)

#Add OpenCV 4 lib
include_directories(${OpenCV_DIR}/jni/include) #Path from gradle to OpenCV Cmake
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)

#Add Your Native Lib
add_library(native-lib SHARED native-lib.cpp)
add_library(detection_based_tracker SHARED detectionbasedtracker_jni.cpp)

#Add&Link Android Native Log lib with others libs
find_library(log-lib log)
target_link_libraries(detection_based_tracker lib_opencv ${log-lib})

NDK版本为21.0.611669。 另外,我不使用CMake的参数,例如-DANDROID_STL=gnustl_static


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接