Showing posts with label AOSP. Show all posts
Showing posts with label AOSP. Show all posts

Thursday, May 11, 2017

Compiling Opencv 2.4 for AOSP 5.1 using built-in NDK

I have tried to include OpenCV 2.4 to AOSP as a third party library, so that we can use OpenCV dealing with images in the kernel.  The idea is to copy the source code of OpenCV2.4 for Android directly to the AOSP as an external package and then call the built-in NDK to compile it to a static library. Then, codes in the kernel can directly import this library and call APIs.

Here I show you how to do this step by step.

STEP 1: Download OpenCV4Android SDK. Here is a link to SDK.
.
|-- etc
|   |-- haarcascades
|   |-- lbpcascades
|-- java
|   |-- assets
|   |-- bin
|   |-- gen
|   |-- javadoc
|   |-- res
|   |-- src
|-- native
    |-- 3rdparty
    |-- jni

    |-- libs

STEP 2: Create a directory under AOSP external folder. For example, I have create a folder named opencv24 in /Volumes/android/external/opencv24

STEP 3: Copy the native folder in the OpenCV4Android SDK to the folder you created in STEP 2.
Here is my directory tree. Specifically, I also copied the folder of haarcascades under etc/ in OpenCV4Android SDK to opencv24/.
.
|-- haarcascade
|-- native
    |-- 3rdparty
    | -- libs
    |-- jni
    | -- include
    |-- libs
        |-- armeabi
        |-- armeabi-v7a
        |-- mips

        |-- x86


STEP 4: Create an Android.mk file in the folder your created, e.g., opencv24/

The biggest challenge is to set up the configuration of NDK and then compile OpenCV 2.4 package correctly. The following a few steps are to introduce the main part in Android.mk.


1. Link gnustl_static
In NDK for app development like my other blog, we must define APP_STL := gnustl_static in Application.mk. However, while compiling Opencv 2.4 for AOSP, we must link gnustl_static in Android.mk. Even though the grammar of NDK looks similar for app development and AOSP compilation, they are actually different. Therefore, we must be able to fulfill APP_STL := gnustl_static in AOSP compilation following the discussion.

In your Android.mk

LOCAL_NDK_STL_VARIANT := gnustl_static
NDK_ROOT :=prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9
LOCAL_C_INCLUDES := $(NDK_ROOT)/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/libs/armeabi-v7a/include

#add the following line after the last LOCAL_LDLIBS
LOCAL_LDLIBS += $(NDK_ROOT)/libs/armeabi-v7a/libgnustl_static.a

2. In the last step, we use the ndk 9 for our compilation. However, it will cause a problem:

prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include/bits/ctype_base.h:67:32: error: '_CTYPE_N' was not declared in this scope

     static const mask digit  = _N;

The problem of ctype_bash.h in ndk has been lasted for a very long time.  In this discussion, they reported similar problem in ndk 6. In ndk 9, they resolved most of the problem, but left _CTYPE_N unresolved. Fortunately, some one in the discussion posted a patch file which we can use. My solution is to add a line of code (this code is from the patch file) to the ctype_base.h we are using.

Add
#define _CTYPE_N        0x04
to the file 
prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include/bits/ctype_base.h

3. When meeting the following problem, add a line LOCAL_CFLAGS += -Wno-error=non-virtual-dtor to your Android.mk. It will convert this error to warning.

core.hpp:1337:18: error: 'class cv::_InputArray' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]
 class CV_EXPORTS _InputArray

Here is the content of my Android.mk :
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
TARGET_ARCH_ABI := armeabi-v7a
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=STATIC

#link gnustl
LOCAL_NDK_STL_VARIANT := gnustl_static
NDK_ROOT :=prebuilts/ndk/9/sources/cxx-stl/gnu-libstdc++/4.9
LOCAL_C_INCLUDES := $(NDK_ROOT)/include
LOCAL_C_INCLUDES += $(NDK_ROOT)/libs/armeabi-v7a/include
LOCAL_LDLIBS += $(NDK_ROOT)/libs/armeabi-v7a/libgnustl_static.a

include $(LOCAL_PATH)/native/jni/OpenCV.mk

LOCAL_MODULE     := libopencv24
LOCAL_CFLAGS += -Wall -Wextra -Wno-error=non-virtual-dtor
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/native/jni/include/ \                 $(LOCAL_PATH)/native/jni/include/opencv $(NDK_ROOT)/include \ $(NDK_ROOT)/libs/armeabi-v7a/include


include $(BUILD_STATIC_LIBRARY)

Finally, you can call make -j4 to compile your package and check the log to see whether the compilation process succeeds or not. You may probably meet many other wired errors, don't panic, search them one by one and try to add something to LOCAL_CFLAGS or change a few line of codes to solve them. Have fun!



The following is the overall directory tree in my external/opencv24/.


.
|-- Android.mk
|-- haarcascade
|   |-- haarcascade_anger.xml
|   |-- haarcascade_disgust.xml
|   |-- haarcascade_eye_new.xml
|   |-- haarcascade_fear.xml
|   |-- haarcascade_frontalface_alt_tree.xml
|   |-- haarcascade_mcs_mouth.xml
|   |-- haarcascade_mcs_nose.xml
|   |-- haarcascade_mcs_righteye.xml
|   |-- haarcascade_mouth.xml
|   |-- haarcascade_sad.xml
|   |-- haarcascade_smile.xml
|   |-- haarcascade_surprise.xml
|-- native
    |-- 3rdparty
    |   `-- libs
    |-- jni
    |   |-- OpenCV.mk
    |   |-- OpenCVConfig-version.cmake
    |   |-- OpenCVConfig.cmake
    |   |-- OpenCVModules_armeabi-release.cmake
    |   |-- OpenCVModules_armeabi.cmake
    |   |-- OpenCVModules_armeabi_v7a-release.cmake
    |   |-- OpenCVModules_armeabi_v7a.cmake
    |   |-- OpenCVModules_mips-release.cmake
    |   |-- OpenCVModules_mips.cmake
    |   |-- OpenCVModules_x86-release.cmake
    |   |-- OpenCVModules_x86.cmake
    |   |-- android.toolchain.cmake
    |   |-- include
    |-- libs
        |-- armeabi
        |-- armeabi-v7a
        |-- mips
    |-- x86