Android + OpenCV: Part 8 — DIY SDK + Contrib Modules on Windows & Android

Homan Huang
10 min readMay 17, 2020

--

The OpenCV SDK has two parts: Release and Contrib. The face landmark library is in the Contrib portion. If you want to continue your face recognition project, you have to compile it by yourself. 😭: No free lunch! In this part, I will show you how I make a Combo🍔 🍟🍹 SDK.

🔑1. CMake
🍾2. Download OpenCV Source & Contrib
🤓3. Compile For Windows-VS 2017/2019
🤗4–0. Install OpenCV SDK in VS 2017/2019
✍️4–1. OpenCV Webcam Test
☕️5. Configure and Build for Android
💯6–0. Install the Build for Android
💰 6–1. Tips to Compile &. Fix Errors
🔌7. Implement to Android Project

🔑1. Download CMake

This is Part 8, already. I guess that you knew what CMake is already from CMakeLists.txt. It’s our C compiler with linked resources. Now, you can use CMake independently by download it from CMake.org/download.🙂 Choose your platform and install it.

There will be a GUI icon pops on your desktop.

🍾2. Download OpenCV Source & Contrib

Please check these links for OpenCV 4.3.0.

All you need is the zip file of Source code. Please unzip to your local folder.

Next, you need to download Contrib for the release number, such as 4.3.0, from,

Please unzip Contrib to the same folder.

I create a new folder “my_android_opencv_vs” as my install directory for CMake.

🤓3. Compile For Windows-VS 2017/2019

Click the CMake (cmake-gui),

Place “opencv-4.3.0” as your source directory and “build_win” as your build directory.

Click “Configure”. I am using the Windows platform, so I choose VS15(VS 2017 or VS16(VS 2019) and Win32 or x64. (I am using x64.)

Finish. A lot of available options will pop out.

You need to fill in “OPENCV_EXTRA_MODULES_PATH” by {Contrib-Dir}/modules.

📥If you have an error.

That means some configurations are incompatible. You may need to delete the cache,

delete everything in the target directory and redo the whole process again.

🤗4–0. Install OpenCV SDK in VS 2017/2019

Next, please choose your installation directory: my_android_opencv_vs.

Next, let’s generate.

Now, we can install the new SDK: Go to “build_win” and click “OpenCV.sln”.

😏: Debug or Release?

I suggest that you run each of them for once, so you will have Debug+Release.

The VS 2017/2019 will start to build for release. There are 166 projects in the task list, you have to wait. 🎵 🎶 〰️

Next, CMake=>INSTALL=>Build

Let’s check the result.

Finally, let’s edit Windows Environment for the new SDK:

An OPENCV_DIR: (vc15 for VS 2017; vc16 for VS 2019)

✍️4–1. OpenCV Webcam Test

You can write a simple C++ code to test it.

Here is the configuration in VC++. Please open an empty C++ project in VS 2017/2019. Click Solution Explorer and Alt+Enter to open the property window.

✔️Include Directories

Please add your new {install directory}/include.

✔️Libraries Directories

Let’s insert the x64 library.

✔️Additional Dependencies — Debug Libraries

We need to link the libraries file to VC++ dependencies. All of the debug files are formatted like “*d.lib”.

Move down to Linker => Input =>(Configuration:) Debug => Additional Dependencies

We need to include all files with *d.*; so open a CMD and move to x64 library.

>cd {CV Path}\x64\vc16\lib>dir
Volume in drive D is 512 Gigabyte
Volume Serial Number is BE4E-1582
Directory of {CV Path}\x64\vc16\lib05/27/2020 12:38 AM <DIR> .
05/27/2020 12:38 AM <DIR> ..
05/27/2020 12:38 AM 1,777 dubug_libs.txt
05/26/2020 04:30 PM 433 OpenCVConfig-version.cmake
05/26/2020 11:05 PM 15,617 OpenCVConfig.cmake
05/27/2020 12:03 AM 29,760 OpenCVModules-debug.cmake
05/27/2020 12:03 AM 29,962 OpenCVModules-release.cmake
05/26/2020 11:06 PM 15,936 OpenCVModules.cmake
05/27/2020 12:21 AM 259,572 opencv_aruco430.lib
05/27/2020 12:08 AM 269,912 opencv_aruco430d.lib
...
05/27/2020 12:20 AM 206,400 opencv_xphoto430.lib
05/27/2020 12:08 AM 214,764 opencv_xphoto430d.lib
106 File(s) 29,073,281 bytes
2 Dir(s) 348,801,912,832 bytes free
>

All of the libraries have their debug twins. Let’s save them into a text file.

>dir /b *d.lib > debug_libs.txt

Edit the dubug_libs.txt with Notepad++. Remove all of the junks except the libraries.

Select All(Ctrl+a); copy(Ctrl+c) and paste(Ctrl+v) to window of Additional Dependencies.

✔️Additional Dependencies — Release Libraries

Now, we can switch the release.

Go back to Notepad++. Ctrl+h to replace “d.lib” to “.lib”.

Paste all of them to Additional Dependencies of Release.

Let’s write a main.cpp.

Input “main.cpp”.

#include <opencv2\opencv.hpp>

using namespace cv;

int main() {
// webcam
VideoCapture cam(0);

// open camera
if (!cam.isOpened())
return -1;

// capture frame
for (;;) {

Mat frame;
cam >> frame;

imshow("Webcam frame", frame);

// wait for key press to end
if (waitKey(30) >= 0)
break;
}


return 0;
}

I hope your webcam will pop up! Or LNK1104 error, which means you have inputted wrong about your library files.

☕️5. Configure and Build for Android

Let’s open CMake-GUI. I will build to “build” folder.

Now, click “Configure”. This time, I use ✅“MinGW Makefiles” “Specify toolchain file for cross-compiling”.

Next, please open your Android Studio => File => Project Structure; copy your NDK location. And you need to open the CMD window to paste your path.

Type: dir *toolchain.cmake /s

You will find your NDK toolchain file and paste the path in “Select File” window to select android.toolchain.

After that, the CMake shall start to configure the options. When it finishes, you can add these:

✔️Let’s add Extra Contrib Modules.

✔️Change the install folder. Mine is “my_android_opencv_4.3.0”.

❌Remove ✂️all the test cases. ( I don't’ suggest removing the tests. You don’t see me here🙈! )

You will build much faster. 🙈🙉 🙊Or please check the 6–1 section to see how I fix the errors.

✔️Add Clang and C++_static Entry

✔️Add Android ABI

Different CPU shall have different build folder. And you shall define CPU type before you generate the build.

32bit CPU type: armeabi-7v, x86
64bit CPU type: arm64-v8a, x86_64

If you want to build them all, you need to separate them into 4 build folders.

✔️Increase your Java memory heap in the Environment Variables.

Now, click “Generate”.

You need to make sure that Java wrappers are ON. Or you must change each source file from OFF to ON in the OpenCV resource folder and redo CMake again.

💯6–0. Install the Build for Android

CMD: In the build folder, let’s find the make.exe in the NDK folder.

Type: dir make.exe /s

Go back the build folder; paste the path + “/make” at the end. Now, the clang++ will build and install the SDK. It’ll take a while. Let’s hear some music 🔊🎵 🎶. Indeed, it’s quite long. Here is my experience:😤 I was stopped once at 35% after a half-hour because I forgot to uncheck the test cases and I had to rerun again.😱 Furthermore, I was stopped at 99% with Java heap overload and rerun again.

Finally,

BUILD SUCCESSFUL in 9s? That’s a Boast!

Next, let’s install the build: {NDK’s make.exe path}\make install

D:\Android\OpenCV-Android-Lib\build>c:make install
[ 0%] Built target libcpufeatures
...
[100%] Built target android_sample_tutorial-3-cameracontrol
Install the project...
-- Install configuration: "Release"
-- Installing: D:/Android/OpenCV-Android-Lib/my_android_opencv_4.3.0/samples/build.gradle
...
-- Installing: D:/Android/OpenCV-Android-Lib/my_android_opencv_4.3.0/samples/tutorial-3-cameracontrol/build.gradleD:\Android\OpenCV-Android-Lib\build>

The make program installs all of the files to CMAKE_INSTALL_PREFIX defined folder.

Excellent!

💰 6–1. Tips to Compile &. Fix Errors

✔️Arm 64bit has a different name to support cross-compiling. It starts as “aarch64-linux-android-”, like this:

❌undefined reference to `__write_chk’

Please search Cmake-GUI for *.a file and swap *.a file to *.so file.

❌Archive has no index


..\..\..\lib\arm64-v8a\libopencv_phase_unwrapping.a: error adding symbols: Archive has no index; run ranlib to add one
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Please find the ranlib.exe to create a new index. Here is my batch file:

@echo off
rem Please replace command with your ranlib at %NDK Path%/toolchains/llvm/prebuilt/windows-x86_64/bin/
C:/Users/Homan/AppData/Local/Android/Sdk/ndk/21.2.6472646/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-ranlib.exe %1 %2 %3 %4
echo "Fixed %1"

I save it as idx.bat. For example,

lib/arm64-v8a/Debug/libopencv_core.a: error adding symbols: Archive has no index; run ranlib to add one
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

This is the error at path = “lib/arm64-v8a/Debug/”, file = libopencv_core.a.

I will open two CMD Windows to make work easier. Both of Windows are at the same build folder.

In the 2nd CMD window, I create idx.bat at the root of the build folder.

build>copy idx.bat lib/arm64-v8a/Debug
1 file(s) copied.
build>cd lib/arm64-v8a/Debug
build\lib\arm64-v8a\Debug>

Let’s run idx.bat to fix the libopencv_core.a.

build\lib\arm64-v8a\Debug>idx libopencv_core.a
"Fixed libopencv_core.a"
build\lib\arm64-v8a\Debug>

In the 1st CMD window of root build folder to make again. The next error will pop up. And I can fix the next error in the 2nd CMD Window.

🔌7. Implement to Android Project

Let’s open the Android Studio to insert the new Custom Made SDK.

📌1: settings.gradle

rootProject.name='OpenCV Camera Demo'
include ':app'

def opencvsdk = '{My new SDK path.}'
include ':OpenCV430'
project(':OpenCV430').projectDir = new File(opencvsdk + '/sdk')
include ':CvBenchmark'

Replace {My new SDK path.} to your path. Mine (“\\” = “/”):

def opencvsdk = 'D:\\Android\\OpenCV-Android-Lib\\my_android_opencv_4.3.0'

📌2. build.gradle(Module: app)

...
def opencvsdk = '{My new SDK path.}'

android {
compileSdkVersion 29
buildToolsVersion "29.0.3"

defaultConfig {
...

ndk {
abiFilters 'armeabi-v7a', 'arm64-v8a'
}
externalNativeBuild {
cmake {
...
arguments "-DANDROID_TOOLCHAIN=clang",
"-DANDROID_STL=c++_static",
"-DANDROID_PLATFORM=android-21",
"-DOpenCV_DIR=" + opencvsdk + '/sdk'
}
}
}
...
}

dependencies {
...

// include OpenCV Manager and SDK
implementation project(':OpenCV430')
}

Replace {My new SDK path.} to your path. In this example, I only cross-compile one type of CPU — armeabi-v7a. At present, the Android Play store is required 64bit app, I suggest that you compile another 64bit “.so” file, arm64-v8a, if you want to upload your app.

📌3. CMakeLists.txt

If you have not changed your old path to ${OpenCV_DIR} defined by the app module, please change.

📌4. Android.mk

LOCAL_PATH := $(call my-dir)

CVROOT := 'D:/Android/OpenCV-Android-Lib/my_android_opencv_4.3.0/sdk/native/jni'

include $(CLEAR_VARS)
OPENCV_INSTALL_MODULES:=on

Replace CVROOT to your path.

📌5. Application.mk

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all
APP_PLATFORM := android-21

Replace “APP_ABI := all” to

APP_ABI := armeabi-v7a arm64-v8a

Sync, the new SDK is ready to use!

--

--

Homan Huang

Computer Science BS from SFSU. I studied and worked on Android system since 2017. If you are interesting in my past works, please go to my LinkedIn.