【问题标题】:Can OpenCV for Android leverage the standard C++ Support to get native build support on Android Studio 2.2 for Windows?OpenCV for Android 能否利用标准 C++ 支持在适用于 Windows 的 Android Studio 2.2 上获得本机构建支持?
【发布时间】:2016-12-21 21:11:15
【问题描述】:

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

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

将 Android Studio 2.2 或更高版本与适用于 Gradle 版本 2.2.0 或更高版本的 Android 插件结合使用,您可以将 C 和 C++ 代码添加到您的应用中,方法是将其编译到 Gradle 可以与您的 APK 一起打包的本机库中。然后,您的 Java 代码可以通过 Java 本机接口 (JNI) 调用本机库中的函数。如果您想了解有关使用 JNI 框架的更多信息,请阅读适用于 Android 的 JNI 提示。

检查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++ 构建,从而生成了与 gitHub 中的相同的 OpenCV“hello world”应用程序。

附加信息 8/27
今天提交的版本,基于 Bruno Alexandre Krinski 的回答确实编译本机 OpenCV 调用:https://github.com/sengsational/HelloCv。关于“安装被阻止”消息还有一个单独的问题,在安装时,Android 会警告用户“此应用包含试图绕过 Android 安全保护的代码”。由于我不确定这是构建技术的问题,因此我不会扩展此问题以包含该问题(但如果有人对此问题有意见,请告知)。

#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 build.gradle 文件是什么样的?我们需要知道这些是您正在编译的静态库还是共享库。
  • 它看起来并没有做任何有趣的事情:github.com/sengsational/HelloCv/blob/master/openCVLibrary310/…
  • OpenCV 团队提供了更多关于在 Android 上执行本机代码的信息:docs.opencv.org/doc/tutorials/introduction/…
  • 我明白了,所以他们使用的是 Android.mk 而不是 Gradle-experimental NDK。因此,在这种情况下,您使用 Cmake 的方法很好。
  • 这个问题真的很好。我遇到的一些 AndroidNDK/OpenCV 教程采用了一种繁琐的方法(参见youtube.com/watch?v=Oq3oiCfSgbo),您必须在其中编译 jni 标头等,并且失去了 Android Studio 的 IntelliJ 魔法的力量。为问题 +1,为以下答案 +1。

标签: windows android-studio cmake java-native-interface opencv4android


【解决方案1】:

看来您已经导入了 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

【讨论】:

  • 这些建议的更改已合并到 GitHub 上的示例代码中,项目现在可以编译,尽管有安全警告。 github.com/sengsational/HelloCv
  • 你为什么写$\{log-lib}而不是${log-lib}
  • “set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION path to your project/MyApplication/app/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)”上缺少“/”,导致构建错误.我不能编辑帖子! (不会更改超过 6 个字符)感谢您的回答,救了我!
  • 关于如何在 Unity for Android 中使用此类东西的任何提示?
  • 我爱你先生,你救了我的命
【解决方案2】:

使用 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 所在的目录即可。

这种方法的另一个好处 - 您可以静态链接到 OpenCV,这将大大减少您的应用程序/库的大小。

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

【讨论】:

  • @abggcv 不是。如果您自己构建 OpenCV,则不需要 OpenCV Java SDK 和 OpenCV Manager。
  • 你说得对,我发现我正在处理的 android 项目正在使用一些 opencv android 功能,例如相机桥(类似的东西),这可能就是需要 OpenCV 管理器的原因。在另一个项目中,我只是使用 opencv 从文件中读取图像,并且不再需要 opencv 管理器。所以这很好用。我想补充的另一件事是,在我将路径添加到 CMakeLists.txt 之前,它对我不起作用:include_directories(${OPENCV_HOME}/sdk/native/jni/include)
  • 谢谢@Dimitry 我检查了你的仓库,还发现你有一个相机应用程序代码 Fotoapparat。这比安卓的 cwac、cwac2 相机应用程序更好吗?我正在开发相机应用程序,并希望通过代码控制对焦和曝光等相机功能。这是您的回购可以帮助的吗?此外,您的回购代码是否解决了旋转图片、显示尺寸等问题。
  • @abggcv 我们开发了 Fotoapparat,因为我们对 cwac 相机不再满意。至于 DJINNI_HOME - 检查这个 repo:github.com/dropbox/djinni
  • 这是我能找到的唯一解决方案,用于在 Android 上构建并使用来自 C++ 的 OpenCV 库,该库有效。您的 FaceDetector 应用程序是我尝试解决问题的非常有用的参考。非常感谢!
【解决方案3】:

和 Bruno Alexandre Krinski 的回答一样,但是

代替这一行

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

输入这一行,(我不知道为什么这对我有用)

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

(除此之外,请按照上述答案的所有说明进行操作)

【讨论】:

    【解决方案4】:

    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'
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 1970-01-01
      • 2013-05-10
      • 1970-01-01
      • 2011-12-20
      • 2017-08-15
      相关资源
      最近更新 更多