7

I am trying to include Opencv to my native C code in an android studio project through Cmake. I did some research online and downloaded the FindOpenCV.cmake file from online and added it to the app directory of my android project. This is also where the CMakeLists.txt is located. I imported OpenCV onto my Android Studio project as a module using this tutorial: https://www.learn2crack.com/2016/03/setup-opencv-sdk-android-studio.html, and when I run:

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

I get that Opencv is loaded.

However, since I'm trying to add OpenCV to my native code, and not the Java code, I don't think I can use this. Here is the CMakeLists I have right now:

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

Here are the errors I'm getting while building the 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.

So my questions are:

  1. Can I use the imported OpenCV or do I have to download a different opencv and store it somewhere else?
  2. What do I have to change in my CMakeLists.txt for my gradle to build?

Ideally, I want to build and be able to add #include <opencv2/opencv.hpp> and using namespace cv to my c file and add functions that use opencv functions.

Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
ksivakumar
  • 481
  • 2
  • 5
  • 19
  • From your outputs it seems like the FindOpenCv.cmake is not being found. Have you tried adding it to {CMAKE_INSTALL_DIR}/share/modules and including it in the makefile? include(FindOpenCv) – Tiago Cunha May 04 '17 at 07:46
  • No, I can try this! How do I find out what the CMAKE_INSTALL_DIR is? – ksivakumar May 05 '17 at 19:09
  • 1
    Relevant Link: http://stackoverflow.com/a/10766438/7950680 – Tiago Cunha May 05 '17 at 19:31
  • Thank you for the link, it was very helpful! I am getting a new error now with this new CMakeLists.txt: Could not find OpenCV_CORE_INCLUDE_DIR, Could not find OPENCV_HIGHGUI_INCLUDE_DIR. Do I have to download other opencv libraries? – ksivakumar May 05 '17 at 20:01
  • Using Android Studio's C++ New project wizard: http://stackoverflow.com/questions/38958876/can-opencv-for-android-leverage-the-standard-c-support-to-get-native-build-sup – Dale May 18 '17 at 19:23

3 Answers3

17

UPDATE 21-Oct-19: Deprecated Git/Simpler Way in favor of new AndroidOpenCVGradlePlugin

UPDATE 22-May-18: Added missing step number 6.

UPDATE 10-May-17: New solution provides proper integration of OpenCV into application with CMake and Android Gradle plugin 2.3.1. Tested using Android Studio 2.3.1.

UPDATE 11-May-17: An additional solution has been provided

There are two ways of including OpenCV.

Using AndroidOpenCVGradlePlugin

Visit https://github.com/ahasbini/AndroidOpenCVGradlePlugin for more details.

Git/Simpler Way

Visit https://github.com/ahasbini/Android-OpenCV for more details.

Manual/Advanced Way

To include OpenCV libraries into Android Studio Project, its best to create a new Library Module in the project and port the files from OpenCV Android SDK bundle into it:

  1. Create a new module by selecting File>New Module.
  2. Select "Android Library", and then enter the details:
    • Library name: OpenCV
    • Module name: opencv
    • Package name: org.opencv
  3. Once the new module created, copy the contents of path_to_opencv_sdk/sdk/java/src directory into path_to_your_project/opencv/src/main/java.
  4. Under main, create the following directly path: aidl/org/opencv/engine and move main/java/org/opencv/engine/OpenCVEngineInterface.aidl into it.
  5. Copy the contents of path_to_opencv_sdk/sdk/java/res into path_to_your_project/opencv/src/main/res.
  6. Create sdk folder inside path_to_your_project/opencv/src/ and copy path_to_opencv_sdk/sdk/native folder into it.
  7. Within the opencv module, create CMakeLists.txt file and add the following lines in the following order:

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. Within the opencv module, edit the build.gradle file as such:

...
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. Within the app (application module, could be another name) module, create/edit CMakeLists.txt file and add the following lines in the following order (Note the different path set to 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. Within the app (application module, could be another name) module, edit the build.gradle file as such:

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

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

  1. Do a gradle sync, and now the OpenCV native libs, header files and Java wrapper classes are included.

When project is built and apk is launched, you could inspect the packaged apk under path_to_project/path_to_app_module/build/output/ (drag the apk onto the text editor tabs of Android Studio)

APK Inspection

You should see a libopencv_java3.so under each abi architecture folder.

Initialize the OpenCV SDK in your java class :

public class MyClass {

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

    ...
}

And you should see within logcat messages specifying the OpenCV has been loaded (the first error is 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)
ahasbini
  • 6,761
  • 2
  • 29
  • 45
  • But this is for opencv in my Java files right? I want to be able to add opencv to the native C code – ksivakumar May 11 '17 at 14:08
  • Oh no, its for c code as well. I added includes that reference opencv header files and it compiled without any errors. I also inspected the lib that contains the include header file and it size was bigger than without the include, hence i assume CMake linked the opencv library to it properly – ahasbini May 11 '17 at 14:10
  • Oh I see, so I tried the steps until step 10 and the gradle did not build properly. I had a previous OpenCV module installed, could that have messed up things? – ksivakumar May 11 '17 at 14:25
  • Probably, could you see and post what the error is? If gradle failed usually errors show in the message view in Android Studio – ahasbini May 11 '17 at 14:26
  • Sure, I actually just deleted the module I made, let me redo the steps and I will post the error. – ksivakumar May 11 '17 at 14:27
  • One thing I'm doing is in my res folder when I'm copying things over, I'm merging rather than just overwriting. So the previous res file had a strings.xml and I'm adding a attrs.xml file along with it – ksivakumar May 11 '17 at 14:30
  • Here is the gradle error message: Could not find OpenCV_CORE_INCLUDE_DIR and Could not find OpenCV_HIGHGUI_INCLUDE_DIR. OpenCV required but some headers or libs not found. Please specify it's location with OpenCV_ROOT_DIR env. variable – ksivakumar May 11 '17 at 14:35
  • That's weird, there is no ```strings.xml``` file within the OpenCV Android SDK ```java``` folder. Are you sure you've downloaded the latest SDK? Here's the link to it just incase: http://opencv.org/releases.html. Latest version is 3.2.0. – ahasbini May 11 '17 at 14:36
  • 1
    Another error is "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" – ksivakumar May 11 '17 at 14:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/143986/discussion-between-ksivakumar-and-ahasbini). – ksivakumar May 11 '17 at 14:37
  • Thanks a lot,I was struggling for doing this since 2 days – kavie Jun 26 '17 at 10:15
  • 1
    @ahasbini - in step 6 and step 8, is there an extra 's' in 'CMakesLists.txt'? – Mick May 21 '18 at 21:44
  • 1
    I might well have missed a step, or maybe the directory structure has changed with OpenCV 3.4.0, but do you need a step to copy the 'sdk' folder into the new module also so that the CMakeLst file can find the jni files in the 'set(OpenCV_DIR "../opencv/src/sdk/native/jni")' line? – Mick May 21 '18 at 22:44
  • Apologies, I think I've missed a step but can't seem to confirm. Did you copy the `sdk/native` into `opencv/src/sdk`? – ahasbini May 21 '18 at 23:08
  • Yes sorry about that @Mick, I've accidentally missed putting this step, just did the edit and it's number 6. – ahasbini May 21 '18 at 23:16
  • Thanks @ahasbini! I'll try again later this week and see how I get on. – Mick May 22 '18 at 10:40
  • 1
    @ahasbini - just to note. I tried and it worked. Thanks. – Mick Jun 12 '18 at 21:19
  • Could the downvoter elaborate the need to down vote the answer? – ahasbini Aug 01 '18 at 13:42
4

The manual method outlined by ahasbini worked (Reg. Adding OpenCV to Native C code through CMake on Android Studio), however some minor adjustments were required for the current version of Android Studio/SDK (3.1.3);

1 replace the occurrence of compile with implementation in (10) app build.gradle (Still getting warning : Configuration 'compile' is obsolete and has been replaced with 'implementation'). And in (9) app CMakeLists.txt ensure to replace YOUR_TARGET_LIB with your target lib (e.g. native-lib).

2 change the STL to gnustl_shared (Linking errors on Android with OpenCV 3.4.0 and NDK); edit (8) app build.gradle;

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

This prevents referencing errors within linked opencv libraries (e.g. error: undefined reference to std:: ...)

3 To support C++11 (How to enable C++11 for Android Studio? / OpenCV Android native code build issue); edit (8) app build.gradle;

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

Then add the following to (9) app CMakeLists.txt before add_library();

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

This prevents the following error; relocation R_386_GOTOFF against preemptible symbol icv_ippJumpIndexForMergedLibs cannot be used when making a shared object.

user2585501
  • 596
  • 4
  • 17
1

I used @ahasbini's answer and it produced an error when I wanted to access the open cv libs in my native cpp file.

It produced some error when adding the shared libs but only if I accessed their Classes in my file.

Changing

find_package(OpenCV REQUIRED)

To

find_package(OpenCV REQUIRED java)

Fixed it for me

K.Dᴀᴠɪs
  • 9,945
  • 11
  • 33
  • 43
Marco Papula
  • 741
  • 2
  • 8
  • 18