【问题标题】:Adding OpenCV to Native C code through CMake on Android Studio在 Android Studio 上通过 CMake 将 OpenCV 添加到本机 C 代码
【发布时间】:2017-10-01 15:24:37
【问题描述】:

我正在尝试通过 Cmake 在 android studio 项目中将 Opencv 包含到我的本机 C 代码中。我在网上做了一些研究,从网上下载了 FindOpenCV.cmake 文件并将其添加到我的 android 项目的 app 目录中。这也是 CMakeLists.txt 所在的位置。我使用本教程将 OpenCV 作为模块导入到我的 Android Studio 项目中:https://www.learn2crack.com/2016/03/setup-opencv-sdk-android-studio.html,当我运行时:

if(!OpenCVLoader.initDebug()){
   System.out.println("Opencv not loaded");
} else {
   System.out.println("Opencv loaded");
}

我知道 Opencv 已加载。

但是,由于我试图将 OpenCV 添加到我的本机代码中,而不是 Java 代码中,我认为我不能使用它。这是我现在拥有的 CMakeLists:

# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} FindOpenCV.cmake)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

add_library(# Specifies the name of the library.
        apriltag

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        src/main/apriltag/apriltag.c
        src/main/apriltag/apriltag_jni.c
        src/main/apriltag/apriltag_quad_thresh.c
        src/main/apriltag/common/g2d.c
        src/main/apriltag/common/getopt.c
        src/main/apriltag/common/homography.c
        src/main/apriltag/common/image_f32.c
        src/main/apriltag/common/image_u8.c
        src/main/apriltag/common/image_u8x3.c
        src/main/apriltag/common/matd.c
        src/main/apriltag/common/pnm.c
        src/main/apriltag/common/string_util.c
        src/main/apriltag/common/svd22.c
        src/main/apriltag/common/time_util.c
        src/main/apriltag/common/unionfind.c
        src/main/apriltag/common/workerpool.c
        src/main/apriltag/common/zarray.c
        src/main/apriltag/common/zhash.c
        src/main/apriltag/common/zmaxheap.c
        src/main/apriltag/tag16h5.c
        src/main/apriltag/tag25h7.c
        src/main/apriltag/tag25h9.c
        src/main/apriltag/tag36artoolkit.c
        src/main/apriltag/tag36h10.c
        src/main/apriltag/tag36h11.c
        )

STRING(REPLACE "-O0" "-O4" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
STRING(REPLACE "-O2" "-O4" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})

include_directories(src/main/apriltag/)
include_directories(${OpenCV_INCLUDE_DIRS})

find_package(OpenCV REQUIRED)

find_library(log-lib log)
find_library(jnigraphics-lib jnigraphics)
target_link_libraries(apriltag ${log-lib} ${jnigraphics-lib})

这是我在构建 gradle 时遇到的错误:

By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project has 
asked CMake to find a package configuration file provided by "OpenCV", but 
CMake did not find one. 
Could not find a package configuration file provided by "OpenCV" with any of 
the following names:
OpenCVConfig.cmake
opencv-config.cmake
Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set 
"OpenCV_DIR" to a directory containing one of the above files. If "OpenCV" 
provides a separate development package or SDK, be sure it has been 
installed.

所以我的问题是:

  1. 我可以使用导入的 OpenCV 还是必须下载不同的 OpenCV 并将其存储在其他地方?
  2. 我必须在 CMakeLists.txt 中更改哪些内容才能构建我的 gradle?

理想情况下,我希望构建并能够将#include <opencv2/opencv.hpp>using namespace cv 添加到我的c 文件中,并添加使用opencv 函数的函数。

感谢您的帮助!

【问题讨论】:

  • 从您的输出看来,似乎找不到 FindOpenCv.cmake。您是否尝试将其添加到 {CMAKE_INSTALL_DIR}/share/modules 并将其包含在 makefile 中?包括(FindOpenCv)
  • 不,我可以试试这个!如何找出 CMAKE_INSTALL_DIR 是什么?
  • 感谢您的链接,它非常有帮助!我现在收到这个新的 CMakeLists.txt 的新错误:找不到 OpenCV_CORE_INCLUDE_DIR,找不到 OPENCV_HIGHGUI_INCLUDE_DIR。需要下载其他opencv库吗?
  • 使用 Android Studio 的 C++ 新建项目向导:stackoverflow.com/questions/38958876/…

标签: android opencv cmake java-native-interface


【解决方案1】:

19 年 10 月 21 日更新:弃用 Git/Simpler Way 以支持新的 AndroidOpenCVGradlePlugin

18 年 5 月 22 日更新:添加了缺少的第 6 步。

2017 年 5 月 10 日更新:新解决方案通过 CMake 和 Android Gradle 插件 2.3.1 将 OpenCV 正确集成到应用程序中。使用 Android Studio 2.3.1 测试。

2017 年 5 月 11 日更新:提供了额外的解决方案

包含 OpenCV 有两种方式。

使用 AndroidOpenCVGradlePlugin

访问https://github.com/ahasbini/AndroidOpenCVGradlePlugin了解更多详情。

Git/更简单的方式

访问https://github.com/ahasbini/Android-OpenCV了解更多详情。

手动/高级方式

要将 OpenCV 库包含到 Android Studio 项目中,最好在项目中创建一个新的库模块并将 OpenCV Android SDK 包中的文件移植到其中:

  1. 通过选择 File>New Module 创建一个新模块。
  2. 选择“Android Library”,然后输入详细信息:
    • 库名称:OpenCV
    • 模块名称:opencv
    • 包名:org.opencv
  3. 创建新模块后,将path_to_opencv_sdk/sdk/java/src 目录的内容复制到path_to_your_project/opencv/src/main/java
  4. main 下,直接创建以下路径:aidl/org/opencv/engine移动 main/java/org/opencv/engine/OpenCVEngineInterface.aidl 进入其中。
  5. path_to_opencv_sdk/sdk/java/res的内容复制到path_to_your_project/opencv/src/main/res中。
  6. path_to_your_project/opencv/src/ 中创建sdk 文件夹并将path_to_opencv_sdk/sdk/native 文件夹复制到其中。
  7. opencv 模块中,创建CMakeLists.txt 文件并按以下顺序添加以下行:

cmake_minimum_required(VERSION 3.4.1)
set(OpenCV_DIR "src/sdk/native/jni")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
include_directories(${OpenCV_INCLUDE_DIRS})

  1. opencv 模块中,编辑build.gradle 文件,如下所示:

...
android {
    ...

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 25
        versionCode 3200
        versionName "3.2.0"

        ...

        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
            }
        }
    }
    buildTypes {
        ...
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
    sourceSets {
        main {
            jni.srcDirs = [jni.srcDirs, 'src/sdk/native/jni/include']
            jniLibs.srcDirs = [jniLibs.srcDirs, 'src/sdk/native/3rdparty/libs', 'src/sdk/native/libs']
        }
    }
}
...

  1. app(应用程序模块,可以是另一个名称)模块中,创建/编辑CMakeLists.txt文件并按以下顺序添加以下行(注意不同的路径设置为OpenCV_DIR):

set(OpenCV_DIR "../opencv/src/sdk/native/jni")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
target_link_libraries(YOUR_TARGET_LIB ${OpenCV_LIBS})

  1. app(应用程序模块,可以是另一个名称)模块中,编辑build.gradle 文件,如下所示:

...    
android {
    ...
    defaultConfig {
        ...
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
        }
    }
    buildTypes {
        ...
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

dependencies {
    ...
    compile project(':opencv')
}

  1. 进行 gradle 同步,现在包括 OpenCV 原生库、头文件和 Java 包装类。

当项目构建完成并启动 apk 后,您可以在path_to_project/path_to_app_module/build/output/ 下查看打包好的 apk(将 apk 拖到 Android Studio 的文本编辑器选项卡上)

您应该在每个 abi 架构文件夹下看到一个 libopencv_java3.so

在您的 java 类中初始化 OpenCV SDK:

public class MyClass {

    static {
        if (BuildConfig.DEBUG) {
            OpenCVLoader.initDebug();
        }
    }

    ...
}

并且您应该在 logcat 消息中看到指定 OpenCV 已加载(第一个错误是正常的):

05-10 10:42:31.451 D/OpenCV/StaticHelper: Trying to get library list
05-10 10:42:31.452 E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV
05-10 10:42:31.452 D/OpenCV/StaticHelper: Library list: ""
05-10 10:42:31.452 D/OpenCV/StaticHelper: First attempt to load libs
05-10 10:42:31.452 D/OpenCV/StaticHelper: Trying to init OpenCV libs
05-10 10:42:31.452 D/OpenCV/StaticHelper: Trying to load library opencv_java3
05-10 10:42:32.031 D/OpenCV/StaticHelper: Library opencv_java3 loaded
05-10 10:42:32.031 D/OpenCV/StaticHelper: First attempt to load libs is OK
05-10 10:42:32.045 I/OpenCV/StaticHelper: General configuration for OpenCV 3.2.0 =====================================
05-10 10:42:32.045 I/OpenCV/StaticHelper:   Version control:               3.2.0
05-10 10:42:32.045 I/OpenCV/StaticHelper:   Platform:
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Timestamp:                   2016-12-23T13:04:49Z
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Host:                        Linux 4.8.0-25-generic x86_64
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Target:                      Linux 1 x86_64
05-10 10:42:32.045 I/OpenCV/StaticHelper:     CMake:                       2.8.12.2
05-10 10:42:32.045 I/OpenCV/StaticHelper:     CMake generator:             Ninja
05-10 10:42:32.045 I/OpenCV/StaticHelper:     CMake build tool:            /usr/bin/ninja
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Configuration:               Release
05-10 10:42:32.045 I/OpenCV/StaticHelper:   C/C++:
05-10 10:42:32.045 I/OpenCV/StaticHelper:     Built as dynamic libs?:      NO
05-10 10:42:32.045 I/OpenCV/StaticHelper:     C++ Compiler:                /usr/bin/ccache /opt/android/android-ndk-r10e/toolchains/x86_64-4.9/prebuilt/linux-x86_64/bin/x86_64-linux-android-g++ (ver 4.9)

【讨论】:

  • 但这适用于我的 Java 文件中的 opencv 对吧?我希望能够将 opencv 添加到本机 C 代码中
  • 另一个错误是“找不到由“OpenCV”提供的具有以下任何名称的包配置文件:OpenCVConfig.cmake opencv-config.cmake,“将“OpenCV”的安装前缀添加到CMAKE_PREFIX_PATH 或将“OpenCV_DIR”设置为包含上述文件之一的目录。如果“OpenCV”提供单独的开发包或SDK,请确保已安装”
  • @ahasbini - 在第 6 步和第 8 步中,'CMakesLists.txt' 中是否有额外的 's'?
  • 我很可能错过了一个步骤,或者目录结构可能随着 OpenCV 3.4.0 发生了变化,但是您是否需要一个步骤来将“sdk”文件夹也复制到新模块中,以便CMakeLst 文件可以在 'set(OpenCV_DIR "../opencv/src/sdk/native/jni")' 行中找到 jni 文件吗?
  • @ahasbini - 请注意。我试过了,它奏效了。谢谢。
【解决方案2】:

ahasbini 概述的手动方法有效 (Reg. Adding OpenCV to Native C code through CMake on Android Studio),但是当前版本的 Android Studio/SDK (3.1.3) 需要进行一些小调整;

1 将 (10) app build.gradle (Still getting warning : Configuration 'compile' is obsolete and has been replaced with 'implementation') 中出现的compile 替换为implementation。并在 (9) 应用程序 CMakeLists.txt 中确保将 YOUR_TARGET_LIB 替换为您的目标库(例如 native-lib)。

2 将 STL 更改为 gnustl_shared (Linking errors on Android with OpenCV 3.4.0 and NDK);编辑 (8) app build.gradle;

defaultConfig {
...
externalNativeBuild {
  cmake {
    ...
    arguments "-DANDROID_STL=gnustl_shared"
  }
}

这可以防止链接的 opencv 库中的引用错误(例如 error: undefined reference to std:: ...

3 支持 C++11 (How to enable C++11 for Android Studio? / OpenCV Android native code build issue);编辑 (8) app build.gradle;

defaultConfig {
...
externalNativeBuild {
  cmake {
    ...
    cppFlags "-std=c++11"
  }
}

然后将以下内容添加到(9)app CMakeLists.txt add_library()之前;

set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a")

这可以防止以下错误; relocation R_386_GOTOFF against preemptible symbol icv_ippJumpIndexForMergedLibs cannot be used when making a shared object.

【讨论】:

    【解决方案3】:

    我使用了@ahasbini 的答案,当我想访问我的原生 cpp 文件中的开放 cv 库时,它产生了错误。

    添加共享库时会产生一些错误,但前提是我在文件中访问了它们的类。

    变化

    find_package(OpenCV REQUIRED)
    

    find_package(OpenCV REQUIRED java)
    

    帮我修好了

    【讨论】:

    • 如果您能分享您遇到的错误,我们很乐意提供帮助。另外,如果您能详细说明这里的 java 是做什么的?
    • 非常感谢你。这对我也有用。不知道为什么。
    猜你喜欢
    • 2016-11-07
    • 2015-07-14
    • 1970-01-01
    • 2022-07-18
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多