Android 的 OpenCV 能否利用标准 C++ 支持在 Android Studio 2.2 Windows 上获得原生构建支持?

Can OpenCV for Android leverage the standard C++ Support to get native build support on Android Studio 2.2 for Windows?

关于为 android 构建正确获取本机 opencv 有很多问题和答案。一些使用 gradle,另一些使用外部工具。这些对原生 OpenCV 构建的众多、复杂且经常相互冲突的描述可以通过一致的起点进行简化;创建 Android Studio 2.2 Beta 项目时,有一种方法可以包含 C++ 支持:

此功能是在 2016 年 6 月左右添加的。有关详细信息,请参阅 Android tools technical docs

Using Android Studio 2.2 or higher with the Android plugin for Gradle version 2.2.0 or higher, you can add C and C++ code to your app by compiling it into a native library that Gradle can package with your APK. Your Java code can then call functions in your native library through the Java Native Interface (JNI). If you want to learn more about using the JNI framework, read JNI tips for Android.

检查 Include C++ Support 生成一个名为 CMakeLists.txt 的外部构建文件。

# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds it for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             # Associated headers in the same location as their source
             # file are automatically included.
             src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       $\{log-lib} )

要识别使用本机 (C++) OpenCV 代码的 Android 项目,该项目通常会包含一个 *.cpp 文件,其中包含 JNIEXPORT 条目以及使用 #include <opencv...hpp> 功能。这与导入 OpenCV 模块并将 libs 文件夹复制到 jniLibs 不同,后者只允许从 Java.

调用 OpenCV 功能

是否可以使用此起点配置 OpenCV 本机 'hello world' 应用程序,证明构建工作正常?

附加信息 8/22
由于这个难题是关于 CMake 而不是关于 OpenCV,我想我应该为那些对 OpenCV 不感兴趣的人提供一个项目起点。使用 OpenCV in Android Studio.

中的信息,您可以相当快速地启动起点项目

这里是一个 youtube video,它显示了创建一个新的 Android Studio 项目、导入 OpenCV、配置本机 C++ 构建,导致 OpenCV "hello world" 应用程序等于gitHub.

中的那个

附加信息 8/27
今天提交的版本,基于 Bruno Alexandre Krinski 的回答 does compile native OpenCV calls: https://github.com/sengsational/HelloCv 。关于 "Installation Blocked" 消息有一个单独的问题,在安装时,Android 警告用户 "This app contains code that attempts to bypass Android's security protections." 因为我不确定这是构建技术的问题,所以我不会展开这个问题包括那个问题(但如果有人对那个问题有意见,请告知)。

#Added 2 path definitions to support 20160825 additions
set(pathToProject C:/Users/Owner/AndroidStudioProjects/HelloCv)
set(pathToOpenCv C:/Users/Owner/OpenCV-3.1.0-android-sdk)

#Added by the IDE on project create
cmake_minimum_required(VERSION 3.4.1)

#Two sets suggested by Bruno Alexandre Krinski 20160825
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#Addition suggested by Bruno Alexandre Krinski 20160825
include_directories(${pathToOpenCv}/sdk/native/jni/include)

#Added by IDE on project create
add_library( native-lib SHARED src/main/cpp/native-lib.cpp )

#Addition suggested by Bruno Alexandre Krinski 20160825
add_library( lib_opencv SHARED IMPORTED )

#Addition suggested by Bruno Alexandre Krinski 20160825
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathToProject}/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)

#Added by IDE on project create
find_library( log-lib log )

#Added by IDE on project create, Removed and replace with additional parameter suggested by Bruno Alexandre Krinski 20160825
#target_link_libraries( native-lib $\{log-lib} )
target_link_libraries( native-lib $\{log-lib} lib_opencv)

看来您已经导入了 opencv 模块,现在,打开您的 CMakeList.txt 并添加以下行:

set(CMAKE_VERBOSE_MAKEFILE on)

add_library(lib_opencv SHARED IMPORTED)

set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION
path-to-your-project/MyApplication/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)


include_directories(path-to-opencv-directory/OpenCV-android-sdk/sdk/native/jni/include)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

并编辑:

target_link_libraries( # Specifies the target library.
                   native-lib
                   lib_opencv
                   # Links the target library to the log library
                   # included in the NDK.
                   $\{log-lib} )

包括您创建的 lib_opencv。最后,您添加以下行:

abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'

在您的模块应用中,像这样:

externalNativeBuild {

    cmake {
        cppFlags "-std=c++11 -frtti -fexceptions"
        abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
    }
}

您添加的 buildType 及以下:

sourceSets {
    main {
        jniLibs.srcDirs = ['path to your application /MyApplication/app/src/main/jniLibs/']
    }
}

更多详情可以看这个:https://github.com/googlesamples/android-ndk/tree/master/cmake/hello-libs

使用 OpenCV 3.2 配置实际上可能很短:

set(OpenCV_STATIC ON)
set(OpenCV_DIR ${OPENCV_HOME}/sdk/native/jni)
find_package (OpenCV REQUIRED)

target_link_libraries(native-lib ${OpenCV_LIBS})

就是这样,4 行,无需将任何内容复制到您的项目中。请确保 OPENCV_HOME 指向 OpenCV Android SDK 所在的目录。

这种方法的另一个好处 - 您可以 link 静态地使用 OpenCV,这将大大减少 app/library.

的大小

我在 Github 个项目中使用了这种方法:https://github.com/Fotoapparat/FaceDetector

与 Bruno Alexandre Krinski 的回答相同,但

代替这一行

abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'

放这行,(我不知道为什么这对我有用)

abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'

(除此之外,请遵循上述答案的所有说明)

Android 平台不支持 ABI [armeabi]

支持的 ABI 是 [arm64-v8a、armeabi-v7a、x86、x86_64]。

externalNativeBuild {
            cmake {
              //  cppFlags ""
                cppFlags "-std=c++11 -frtti -fexceptions"
               // abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'mips', 'mips64'
                abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
            }
        }