Useful Links to Get OpenCV to Work with Android

Posted on June 13, 2011

0


Why?

I do too much different things and might forget what I’ve figured out before. So this is a public note-to-self.

After playing around with open-source projects for quite a while I must add that they hardy ever work right the first time. Coders planning to attempt using any of the many wonderful open-source initiatives should be prepared to spend a fair amount of time in getting everything to work in “perfect” tandem. Although this struggle personally cost me much time I must admit that I considered it all worth the effort. On the upside, I learned a lot more of the development environment once I was unintentionally forced to digg deeper. Not to forget that there is nothing better then witnessing your code in action after a long struggle ;) — but then again I haven’t yet experienced enough in life to know for certain that there is nothing better than this.

Basically I’m just summing up a set of links that helped me find the answer to my problems. Maybe they might help someone else.

Reference android.libraries.src Not Found

Somehow a bunch of other coders seemed to have this problem after the names to certain Android SDK files seemed to have changed after the transition between SDK levels. The fellas and dames dropped a few solutions to this problem at http://code.google.com/p/android/issues/detail?id=13024.

Compile Error on NDK-build

Apparently compiling native code resulted in some compiler errors. I’ve scoured the internet for solutions and was led to believe that this problem had its source at the debuggable option set to true in the manifest. At the time of writing I haven’t yet found a workaround to this problem that didn’t involve playing around with the debuggable option. So here goes… http://stackoverflow.com/questions/3441297/internal-compiler-error-when-compiling-native-android-code. Pretty much the same conclusion can be drawn from this post on a google thread http://groups.google.com/group/android-ndk/browse_thread/thread/4dc0addd20cf23d0?tvc=2.

Custom Project Checklist

It might be helpful to remember these steps in creating a Android+OpenCV project:

  1. create jni directory
  2. extract contents of android_opencv.tar.gz to jni dir
  3. build jni (ndk-build)
  4. ant-compile android project

Other Interesting Links

Zixuan Wang did a project of his own using OpenCV. Just quickly glimpsing through this concisely written post gives any reader a overview of the steps involved in getting a Android+OpenCV project up and running. I found this post extremely useful and I think it’s size played a significant role herein. http://www.stanford.edu/~zxwang/android_opencv.html

CMake Trouble

Somewhere during my struggle to get my setup running I decided to go back to basic and start trying all needed tools seperately. I build a few NDK examples, which worked. Tried building a few cmake examples and got stuck at android-cmake. I’ve attempted to build the examples as instructed in the documentation with the following strange output as result.
coder@blackbox:~/src/testenv/android-cmake/hello-cmake/androidbuild$ android-cmake ..
-- Using default android API level android-8
-- If you prefer to use a different API level, please define the environment variable: ANDROID_LEVEL
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
dpkg-architecture: warning: Unknown gcc system type arm-linux-androideabi, falling back to default (native compilation)
-- Check for working C compiler: ~/sdks/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc
dpkg-architecture: warning: Unknown gcc system type arm-linux-androideabi, falling back to default (native compilation)
-- Check for working C compiler: ~/sdks/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc -- works
-- Detecting C compiler ABI info
dpkg-architecture: warning: Unknown gcc system type arm-linux-androideabi, falling back to default (native compilation)
CMake Error: Could not COPY_FILE.
OutputFile: ''
copyFile: '~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeDetermineCompilerABI_C.bin'
Unable to find executable for try_compile: tried "~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeTmp/cmTryCompileExec" and "~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeTmp/Debug/cmTryCompileExec" and "~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeTmp/Development/cmTryCompileExec".
-- Detecting C compiler ABI info - done
CMake Error at /usr/share/cmake-2.8/Modules/CMakeDetermineCompilerABI.cmake:40 (FILE):
file STRINGS file
"~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeDetermineCompilerABI_C.bin"
cannot be read.
Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/CMakeTestCCompiler.cmake:71 (CMAKE_DETERMINE_COMPILER_ABI)
CMakeLists.txt:2 (project)
-- Check for working CXX compiler: ~/sdks/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++
dpkg-architecture: warning: Unknown gcc system type arm-linux-androideabi, falling back to default (native compilation)
-- Check for working CXX compiler: ~/sdks/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++ -- works
-- Detecting CXX compiler ABI info
dpkg-architecture: warning: Unknown gcc system type arm-linux-androideabi, falling back to default (native compilation)
CMake Error: Could not COPY_FILE.
OutputFile: ''
copyFile: '~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeDetermineCompilerABI_CXX.bin'
Unable to find executable for try_compile: tried "~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeTmp/cmTryCompileExec" and "~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeTmp/Debug/cmTryCompileExec" and "~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeTmp/Development/cmTryCompileExec".
-- Detecting CXX compiler ABI info - done
CMake Error at /usr/share/cmake-2.8/Modules/CMakeDetermineCompilerABI.cmake:40 (FILE):
file STRINGS file
"~/src/testenv/android-cmake/hello-cmake/androidbuild/CMakeFiles/CMakeDetermineCompilerABI_CXX.bin"
cannot be read.
Call Stack (most recent call first):
/usr/share/cmake-2.8/Modules/CMakeTestCXXCompiler.cmake:64 (CMAKE_DETERMINE_COMPILER_ABI)
CMakeLists.txt:2 (project)
-- Configuring incomplete, errors occurred!
coder@blackbox:~/src/testenv/android-cmake/hello-cmake/androidbuild$

After a bit of searching I attempted to do the same thing with the cmake-gui tool (as suggested in the Android CMake Dev Guide) and this amazingly seemed to work without a glitch.
The cmake gui tool could be installed in ubuntu by executing sudo apt-get install cmake-qt-gui.
As described in the guide, once the gui has been started one might click the configure button once to be confronted by some red marked entries (no need to panic). The values in the red marked entries have to be reviewed to confirm their validity after which the user could proceed by clicking configure once more to finalize configuration. After the configuration has been completed, all to be done is simply press the Generate button to finish the job.
the cmake-gui tool used to build the android-cmake example
Seemingly android-cmake does exactly the same. After the first attempt at executing, a CMakeCache.txt file is generated in the build directory. This file contains the very same variables that are displayed in the CMake tool’s GUI counterpart. After having made sure that these values made sense I succeeded in successfully finish the configuration by running android-cmake .. from my build directory for a second time.
After finishing up on the configuration stage all that is left to be done is to build the actual library. At this stage the project will have a vacant target-related directory in the project’s libs directory and a freshly baked Makefile in the build directory. The library can be generated by making it (execute: make) from the build directory where the Makefile resides. Lo and behold!!! The job is done.
I’ve confirmed this by building the libraries for two different arm targets (armeabi-v7a and armeabi)… it worked!!! :D

FindAndroidOpenCV.cmake

Another little thing I came across looked like this:
coder@blackbox:~/src/testenv/opencv/OpenCV_SAMPLE/jni$ android-cmake ..
CMake Error at jni/CMakeLists.txt:11 (FIND_PACKAGE):
Could not find module FindAndroidOpenCV.cmake or a configuration file for
package AndroidOpenCV.

Adjust CMAKE_MODULE_PATH to find FindAndroidOpenCV.cmake or set
AndroidOpenCV_DIR to the directory containing a CMake configuration file
for AndroidOpenCV. The file will have one of the following names:
AndroidOpenCVConfig.cmake
androidopencv-config.cmake

-- Configuring incomplete, errors occurred!

Trouble in paradise again. Locating all cmake files in the OpenCV directory produced a list that included the absolute paths to the needed files. Mind you that there is no such thing as the FindAndroidOpenCV script that the error message suggests is lost. The CMakeLists.txt file contains the references to the real wanted files in the following lines:
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/../../build
CACHE PATH "The path where you built opencv for android")
set(AndroidOpenCV_DIR ${CMAKE_SOURCE_DIR}/../../android-opencv/build
CACHE PATH "The path where you built android-opencv")

The pathnames to the wanted files are relative and ${CMAKE_SOURCE_DIR} refers to the directory from whence CMake was fired (source: CMake Useful Variables). Unless your project files are merely two levels below the android-opencv directory this won’t work. I got this problem because I copied the code from the original directories into development directories to avoid corrupting the original opencv download. This way I could always delete my development directory and copy the necessary “untouched” code from the original project when things went wrong. A bit of playing around with the message command could help one to analyse/debug CMake scripts. I’ve used it to figure out how CMake dealt with variables and to monitor which values it would pass to the find_package function. My solution to the problem involved adding a OPENCV environment variable and planting absolute pathnames in my CMakeLists.txt script. You can add environment variables by executing export OPENCV=/home/coder/blah. This export can be made permanent by appending it to your .bashrc script. After added the correct path the CMake tool would still cause some trouble until I removed the CACHE PATH parameters; the result being:
set(OpenCV_DIR $ENV{OPENCV}/android/build
CACHE PATH "The path where you built opencv for android")
set(AndroidOpenCV_DIR $ENV{OPENCV}/android/android-opencv/build)

After helping CMake find its configuration CMake scripts I ran android-cmake .. once more and this time it did manage to pass the configuration without a glitch.

coder@blackbox:~/src/testenv/opencv/OpenCV_SAMPLE/jni$ android-cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /home/david/src/testenv/opencv/OpenCV_SAMPLE/jni

Now all there is left to do is generate the library which will be linked into the android app.

Android-Opencv Libraries

Some of the libraries necessary for building android opencv components are located in the $OPENCVROOT/android/build/lib$ directories. The next set of errors have to do with the linker being unable to find the necessary libraries. Make sure to have build the android opencv files. The output of the make will give a indication of the libraries that will be linked in this phase.

coder@blackbox:~/sdks/opencv/android/build$ sudo make install
[sudo] password for coder:
[ 0%] Built target opencv_imgproc_pch_dephelp
[ 1%] Built target pch_Generate_opencv_imgproc
[ 4%] Built target zlib
[ 5%] Built target opencv_core_pch_dephelp
[ 5%] Built target pch_Generate_opencv_core
[ 8%] Built target opencv_core
[ 15%] Built target opencv_imgproc
[ 16%] Built target opencv_calib3d_pch_dephelp
[ 16%] Built target pch_Generate_opencv_calib3d
[ 16%] Built target opencv_features2d_pch_dephelp
[ 16%] Built target pch_Generate_opencv_features2d
[ 17%] Built target opencv_flann_pch_dephelp
[ 18%] Built target pch_Generate_opencv_flann
[ 18%] Built target opencv_flann
[ 24%] Built target libtiff
[ 24%] Built target opencv_highgui_pch_dephelp
[ 24%] Built target pch_Generate_opencv_highgui
[ 29%] Built target libjasper
[ 37%] Built target libjpeg
[ 40%] Built target libpng
[ 43%] Built target opencv_highgui
[ 46%] Built target opencv_features2d
[ 48%] Built target opencv_calib3d
[ 48%] Built target opencv_test_calib3d_pch_dephelp
[ 48%] Built target pch_Generate_opencv_test_calib3d
[ 49%] Built target opencv_ts_pch_dephelp
[ 50%] Built target pch_Generate_opencv_ts
[ 50%] Built target opencv_ts
[ 53%] Built target opencv_test_calib3d
[ 53%] Built target opencv_test_core_pch_dephelp
[ 53%] Built target pch_Generate_opencv_test_core
[ 55%] Built target opencv_test_core
[ 55%] Built target opencv_test_features2d_pch_dephelp
[ 56%] Built target pch_Generate_opencv_test_features2d
[ 58%] Built target opencv_test_features2d
[ 59%] Built target opencv_test_imgproc_pch_dephelp
[ 59%] Built target pch_Generate_opencv_test_imgproc
[ 62%] Built target opencv_test_imgproc
[ 62%] Built target opencv_video_pch_dephelp
[ 62%] Built target pch_Generate_opencv_video
[ 64%] Built target opencv_video
[ 64%] Built target opencv_legacy_pch_dephelp
[ 64%] Built target pch_Generate_opencv_legacy
[ 76%] Built target opencv_legacy
[ 76%] Built target opencv_contrib_pch_dephelp
[ 77%] Built target pch_Generate_opencv_contrib
[ 77%] Built target opencv_ml_pch_dephelp
[ 77%] Built target pch_Generate_opencv_ml
[ 80%] Built target opencv_ml
[ 80%] Built target opencv_objdetect_pch_dephelp
[ 81%] Built target pch_Generate_opencv_objdetect
[ 84%] Built target opencv_objdetect
[ 85%] Built target opencv_contrib
[ 85%] Built target opencv_test_ml_pch_dephelp
[ 86%] Built target pch_Generate_opencv_test_ml
[ 87%] Built target opencv_test_ml
[ 87%] Built target opencv_test_objdetect_pch_dephelp
[ 87%] Built target pch_Generate_opencv_test_objdetect
[ 88%] Built target opencv_test_objdetect
[ 88%] Built target opencv_test_video_pch_dephelp
[ 88%] Built target pch_Generate_opencv_test_video
[ 89%] Built target opencv_test_video
[ 90%] Built target opencv_haartraining_engine
[ 92%] Built target opencv_traincascade
[ 92%] Built target opencv_createsamples
[ 92%] Built target opencv_haartraining
[ 92%] Built target opencv_performance
[ 92%] Built target opencv_gpu_pch_dephelp
[ 92%] Built target pch_Generate_opencv_gpu
[ 96%] Built target opencv_gpu
[ 96%] Built target opencv_test_gpu_pch_dephelp
[ 96%] Built target pch_Generate_opencv_test_gpu
[100%] Built target opencv_test_gpu
Install the project...

The rest of the output is not that important right now.

Cannot Find -landroid-opencv

After all my troubleshooting and seemingly solving the problems one by one I ran into another minor setback.

coder@blackbox:~/src/testenv/opencv/OpenCV_SAMPLE/jni$ make
Linking CXX shared module ../../libs/armeabi-v7a/libOpenCV_SAMPLE.so
/home/david/sdks/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld: cannot find -landroid-opencv
collect2: ld returned 1 exit status
make[2]: *** [../libs/armeabi-v7a/libOpenCV_SAMPLE.so] Error 1
make[1]: *** [jni/CMakeFiles/OpenCV_SAMPLE.dir/all] Error 2
make: *** [all] Error 2

This looks fairly simple, the link option requires a library which does not exist. I can’t really seem to find out where things went wrong on my system. Guess the entire installation went bad… I’m not really sure. Anyways… throwing a few @echo "xxx"‘s might help one to narrow down the region of the makefile scripts that are failing. In my case I’ve narrowed it down to the following statement in Makefile2:
@echo $(MAKE) -f jni/CMakeFiles/OpenCV_SAMPLE.dir/build.make jni/CMakeFiles/OpenCV_SAMPLE.dir/build
In such cases using the --just-print parameters to the make command might prove extremely useful to looking under the hood of this make device. A few handy makefile debugging tips can be found in the excerpt of the book Managing Projects with GNU Make, Third Edition.
Finally I’ve narrowed it all down to that very file within which -landroid-opencv has been hardcoded somewhere in the /jni/jni/CMakeFiles/OpenCV_SAMPLE.dir directory (it’s all in the link.txt).

/home/david/sdks/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-g++ -fPIC --sysroot=/home/david/sdks/android-ndk-r5b/platforms/android-8/arch-arm/ -fPIC -DANDROID -Wno-psabi -fsigned-char -mthumb -march=armv7-a -mfloat-abi=softfp -Wl,--no-undefined -Wl,--fix-cortex-a8 -L/home/david/sdks/android-ndk-r5b/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a -lstdc++ -lsupc++ -shared -Wl,-soname,libOpenCV_SAMPLE.so -o ../../libs/armeabi-v7a/libOpenCV_SAMPLE.so CMakeFiles/OpenCV_SAMPLE.dir/OpenCV_SAMPLEJAVA_wrap.cxx.o CMakeFiles/OpenCV_SAMPLE.dir/cvsample.cpp.o -L/usr/local/lib -L/usr/local/lib/../3rdparty/lib -L/home/david/sdks/opencv/android/build/3rdparty/lib -L/usr/local/lib/3rdparty/lib -landroid-opencv -ldl -lm -lpthread -lrt -lstdc++ -lopencv_calib3d -lopencv_objdetect -lopencv_features2d -lopencv_imgproc -lopencv_video -lopencv_highgui -lopencv_ml -lopencv_legacy -lopencv_flann -lopencv_core -llibjpeg -llibpng -llibtiff -llibjasper -lzlib -llog -ldl -lm -lpthread -lrt -lstdc++ -lopencv_calib3d -lopencv_objdetect -lopencv_features2d -lopencv_imgproc -lopencv_video -lopencv_highgui -lopencv_ml -lopencv_legacy -lopencv_flann -lopencv_core -llibjpeg -llibpng -llibtiff -llibjasper -lzlib -llog -Wl,-rpath,/usr/local/lib:/usr/local/lib/../3rdparty/lib:/home/david/sdks/opencv/android/build/3rdparty/lib:/usr/local/lib/3rdparty/lib

Some information about this could be found on a android-opencv Issues post but this information wasn’t really helpful to me.

If all went right there might be a libandroid-opencv.so library file lurking somewhere in the android-opencv/build directorytree. That’s the file we’re looking for. We have two options to solve this problem:

  1. Pass the library’s directory -L/dir to the linker
  2. Create symlink to or copy of libandroid-opencv.so in a directory that’s being checked by the linker

I just added a symlink to libandroid-opencv.so to my /usr/local/lib directory and that seemed to work.

sudo ln -s /OPENCVROOT/android/android-opencv/build/jni/libandroid-opencv.so /usr/local/lib/libandroid-opencv.so

NOTE: Be careful which target the library was build for. There is a significant difference between code build for the armeabi versus code build for the armeabi-v7a. In my case I build all my code for the armeabi-v7a. But the symlinked libandroid-opencv.so will only cause us more trouble if we intent to build code for the armeabi. You might be better of passing a project-specific -L directive to the linker to the directory that contains the necessary libraries for that project. That would mean messing around with that links.txt file instead of symlinks. Other then this I don’t really have much better solutions to this problem. I’m sorry :(.

Cannot Find -lpthread

The libpthread.so library… I’ll figure this out next weekend. :) Gotta do some homework.

Posted in: coding, projects