Reg. Agregar OpenCV al código nativo C a través de CMake en Android Studio

Estoy tratando de incluir Opencv en mi código C nativo en un proyecto de estudio de Android a través de Cmake. Hice algunas investigaciones en línea y descargué el archivo FindOpenCV.cmake de en línea y lo agregué al directorio de la aplicación de mi proyecto de Android. Aquí también se encuentra el CMakeLists.txt. Importé OpenCV en mi proyecto de Android Studio como un módulo usando este tutorial: https://www.learn2crack.com/2016/03/setup-opencv-sdk-android-studio.html , y cuando corro:

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

Entiendo que Opencv está cargado.

Sin embargo, dado que estoy tratando de agregar OpenCV a mi código nativo, y no al código Java, no creo que pueda usar esto. Aquí está el CMakeLists que tengo ahora:

 # 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}) 

Aquí están los errores que estoy obteniendo al construir el 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. 

Entonces mis preguntas son:

  1. ¿Puedo usar el OpenCV importado o tengo que descargar un opencv diferente y almacenarlo en otro lugar?
  2. ¿Qué tengo que cambiar en mi CMakeLists.txt para que mi gradle se construya?

Idealmente, quiero comstackr y poder agregar #include y using namespace cv en mi archivo c y agregar funciones que usen funciones de opencv.

¡Gracias por cualquier ayuda!

ACTUALIZACIÓN 22-May-18: Se agregó el paso número 6 que faltaba.

ACTUALIZACIÓN 10-May-17: La nueva solución proporciona una integración adecuada de OpenCV en la aplicación con CMake y Android Gradle plugin 2.3.1. Probado con Android Studio 2.3.1.

ACTUALIZACIÓN 11-mayo-17: Se ha proporcionado una solución adicional

Hay dos formas de incluir OpenCV.

Git / Simpler Way

Visite https://github.com/ahasbini/Android-OpenCV para obtener más detalles.

Manera manual / avanzada

Para incluir las bibliotecas de OpenCV en Android Studio Project, es mejor crear un nuevo Módulo de biblioteca en el proyecto y portar los archivos del paquete de OpenCV Android SDK en él:

  1. Cree un nuevo módulo seleccionando Archivo> Nuevo módulo.
  2. Seleccione “Biblioteca de Android” y luego ingrese los detalles:
    • Nombre de la biblioteca: OpenCV
    • Nombre del módulo: opencv
    • Nombre del paquete: org.opencv
  3. Una vez que se haya creado el nuevo módulo, copie los contenidos del directorio path_to_your_project/opencv/src/main/java path_to_opencv_sdk/sdk/java/src en path_to_your_project/opencv/src/main/java .
  4. En main , crea la siguiente ruta directamente: aidl/org/opencv/engine y mueve main/java/org/opencv/engine/OpenCVEngineInterface.aidl en ella.
  5. Copie los contenidos de path_to_opencv_sdk/sdk/java/res en path_to_your_project/opencv/src/main/res .
  6. Cree la carpeta sdk dentro de path_to_your_project/opencv/src/ y copie la carpeta path_to_your_project/opencv/src/ path_to_opencv_sdk/sdk/native en ella.
  7. Dentro del módulo opencv , cree el archivo CMakeLists.txt y agregue las siguientes líneas en el siguiente orden:

 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. Dentro del módulo opencv , edite el archivo build.gradle como tal:

 ... 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. Dentro del módulo de la app (módulo de la aplicación, podría ser otro nombre), cree / edite el archivo CMakeLists.txt y agregue las siguientes líneas en el siguiente orden ( OpenCV_DIR cuenta la diferente ruta establecida en 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. Dentro del módulo de la app (módulo de la aplicación, podría ser otro nombre), edite el archivo build.gradle como tal:

 ... android { ... defaultConfig { ... externalNativeBuild { cmake { cppFlags "-frtti -fexceptions" } } buildTypes { ... } externalNativeBuild { cmake { path "CMakeLists.txt" } } } dependencies { ... compile project(':opencv') } 

  1. Haga una sincronización de gradle, y ahora se incluyen las librerías nativas de OpenCV, los archivos de encabezado y las clases de envoltura de Java.

Cuando se crea el proyecto y se lanza apk, se puede inspeccionar la aplicación empaquetada en path_to_project/path_to_app_module/build/output/ (arrastre la aplicación a las tabs del editor de texto de Android Studio)

Inspección de APK

Debería ver un libopencv_java3.so debajo de cada carpeta de architecture abi.

Inicialice el SDK de OpenCV en su clase java:

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

Y debería ver dentro de los mensajes de Logcat que se ha especificado que el OpenCV se ha cargado (el primer error es normal):

 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) 

El método manual descrito por ahasbini funcionó ( Reg. Agregando OpenCV al código nativo C a través de CMake en Android Studio ), sin embargo, se requirieron algunos ajustes menores para la versión actual de Android Studio / SDK (3.1.3);

1 reemplace la ocurrencia de la compile con la implementation en (10) app build.gradle ( sigue apareciendo una advertencia: la configuración ‘comstackr’ es obsoleta y ha sido reemplazada por ‘implementación’ ). Y en la aplicación (9) CMakeLists.txt, asegúrese de reemplazar YOUR_TARGET_LIB con su lib de destino (p. Ej., YOUR_TARGET_LIB native-lib ).

2 cambiar el STL a gnustl_shared ( Vinculación de errores en Android con OpenCV 3.4.0 y NDK ); editar (8) aplicación build.gradle;

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

Esto evita los errores de referencia dentro de las bibliotecas opencv vinculadas (por ejemplo, error: undefined reference to std:: ... )

3 Para admitir C ++ 11 ( ¿Cómo habilitar C ++ 11 para Android Studio? / OpenCV problema de comstackción de código nativo de Android ); editar (8) aplicación build.gradle;

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

A continuación, agregue lo siguiente a la (9) aplicación CMakeLists.txt antes de add_library() ;

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

Esto evita el siguiente error; relocation R_386_GOTOFF against preemptible symbol icv_ippJumpIndexForMergedLibs cannot be used when making a shared object .

Usé la respuesta de @ ahasbini y produjo un error cuando quería acceder a las bibliotecas cv abiertas en mi archivo nativo cpp.

Produjo algunos errores al agregar las librerías compartidas, pero solo si accedí a sus clases en mi archivo.

Cambiando

 find_package(OpenCV REQUIRED) 

A

 find_package(OpenCV REQUIRED java) 

Me lo arregló