Agregar OpenCV al código nativo de C a través de CMake en Android Studio
java-native-interface (3)
Estoy tratando de incluir Opencv en mi código C nativo en un proyecto de estudio de Android a través de Cmake. Investigué un poco en línea y descargué el archivo FindOpenCV.cmake en línea y lo agregué al directorio de aplicaciones de mi proyecto de Android. Aquí también se encuentra CMakeLists.txt. Importé OpenCV en mi proyecto de Android Studio como módulo usando este tutorial: https://www.learn2crack.com/2016/03/setup-opencv-sdk-android-studio.html , y cuando ejecuto:
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án las 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 obtengo 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:
- ¿Puedo usar el OpenCV importado o tengo que descargar un opencv diferente y almacenarlo en otro lugar?
- ¿Qué debo cambiar en mi CMakeLists.txt para que se construya mi gradle?
Idealmente, quiero construir y poder agregar
#include <opencv2/opencv.hpp>
y
using namespace cv
a mi archivo c y agregar funciones que usen funciones opencv.
¡Gracias por cualquier ayuda!
El método manual descrito por ahasbini funcionó ( Reg. Agregar 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 aparición de la
compile
con la
implementation
en (10) app build.gradle (
Todavía obteniendo advertencia: la configuración de ''compilación'' está obsoleta y ha sido reemplazada por ''implementación''
).
Y en (9) la aplicación CMakeLists.txt se asegura de reemplazar
YOUR_TARGET_LIB
con su lib de destino (por ejemplo,
native-lib
).
2 cambie el STL a
gnustl_shared
(
Vinculación de errores en Android con OpenCV 3.4.0 y NDK
);
edit (8) app build.gradle;
defaultConfig {
...
externalNativeBuild {
cmake {
...
arguments "-DANDROID_STL=gnustl_shared"
}
}
Esto evita errores de referencia dentro de bibliotecas opencv vinculadas (por ejemplo,
error: undefined reference to std:: ...
)
3 Para admitir C ++ 11 ( ¿Cómo habilitar C ++ 11 para Android Studio? / Problema de compilación de código nativo de Android OpenCV ); edit (8) app build.gradle;
defaultConfig {
...
externalNativeBuild {
cmake {
...
cppFlags "-std=c++11"
}
}
Luego agregue lo siguiente a (9) la 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
.
Utilicé la respuesta de @ ahasbini y produjo un error cuando quería acceder a las bibliotecas cv abiertas en mi archivo cpp nativo.
Produjo algún error al agregar las bibliotecas compartidas, pero solo si accedía a sus clases en mi archivo.
Cambiando
find_package(OpenCV REQUIRED)
A
find_package(OpenCV REQUIRED java)
Me lo arregló
ACTUALIZACIÓN 22 de mayo de 18: se agregó el paso número 6 que falta.
ACTUALIZACIÓN 10-mayo-17: la nueva solución proporciona una integración adecuada de OpenCV en la aplicación con CMake y el complemento Android Gradle 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 / manera más simple
Visite https://github.com/ahasbini/Android-OpenCV para obtener más detalles.
Manera manual / avanzada
Para incluir las bibliotecas de OpenCV en el proyecto Android Studio, es mejor crear un nuevo módulo de biblioteca en el proyecto y transferir los archivos del paquete de Android SDK de OpenCV:
- Cree un nuevo módulo seleccionando Archivo> Nuevo módulo.
-
Seleccione "Biblioteca de Android" y luego ingrese los detalles:
-
Nombre de la biblioteca:
OpenCV
-
Nombre del módulo:
opencv
-
Nombre del paquete:
org.opencv
-
Nombre de la biblioteca:
-
Una vez creado el nuevo módulo, copie el contenido del directorio
path_to_your_project/opencv/src/main/java
path_to_opencv_sdk/sdk/java/src
enpath_to_your_project/opencv/src/main/java
. -
En
main
, cree la siguiente ruta directa:aidl/org/opencv/engine
y muevamain/java/org/opencv/engine/OpenCVEngineInterface.aidl
dentro de ella. -
Copie el contenido de
path_to_opencv_sdk/sdk/java/res
enpath_to_your_project/opencv/src/main/res
. -
Cree la carpeta
sdk
dentro depath_to_your_project/opencv/src/
y copie la carpetapath_to_your_project/opencv/src/
path_to_opencv_sdk/sdk/native
en ella. -
Dentro del módulo
opencv
, cree el archivoCMakeLists.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})
-
Dentro del módulo
opencv
, edite el archivobuild.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'']
}
}
}
...
-
Dentro del módulo de la
app
(módulo de aplicación, podría ser otro nombre), cree / edite el archivoCMakeLists.txt
y agregue las siguientes líneas en el siguiente orden (OpenCV_DIR
cuenta la ruta diferente establecida enOpenCV_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})
-
Dentro del módulo de la
app
(módulo de aplicación, podría ser otro nombre), edite el archivobuild.gradle
como tal:
...
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions"
}
}
buildTypes {
...
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
...
compile project('':opencv'')
}
- Haga una sincronización de Gradle, y ahora se incluyen las bibliotecas nativas de OpenCV, los archivos de encabezado y las clases de contenedor Java.
Cuando se construye el proyecto y se inicia el apk, puede inspeccionar el apk empaquetado en
path_to_project/path_to_app_module/build/output/
(arrastre el apk a las pestañas del editor de texto de Android Studio)
Debería ver un
libopencv_java3.so
debajo de cada carpeta de arquitectura abi.
Inicialice el SDK de OpenCV en su clase de Java:
public class MyClass {
static {
if (BuildConfig.DEBUG) {
OpenCVLoader.initDebug();
}
}
...
}
Y debería ver dentro de los mensajes logcat que especifican que se ha cargado OpenCV (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)