How to Integrate Opencv into Qt Creator Android Project

How to integrate OpenCV into Qt Creator Android project

Edit: For OpenCV 4.x see the answers below. My answer was tested on OpenCV 2.4 only.

Original answer:


First, I downloaded OpenCV-2.4.10-android-sdk, and put into my project directory. It contains static libraries, and link order matters for static libraries for GCC. So you need to order them just so. This is how my .pro file looked in the end ($$_PRO_FILE_PWD_ refers to the project directory):

INCLUDEPATH += "$$_PRO_FILE_PWD_/OpenCV-2.4.10-android-sdk/sdk/native/jni/include"
android {
LIBS += \
-L"$$_PRO_FILE_PWD_/OpenCV-2.4.10-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a"\
-L"$$_PRO_FILE_PWD_/OpenCV-2.4.10-android-sdk/sdk/native/libs/armeabi-v7a"\
-llibtiff\
-llibjpeg\
-llibjasper\
-llibpng\
-lIlmImf\
-ltbb\
-lopencv_core\
-lopencv_androidcamera\
-lopencv_flann\
-lopencv_imgproc\
-lopencv_highgui\
-lopencv_features2d\
-lopencv_calib3d\
-lopencv_ml\
-lopencv_objdetect\
-lopencv_video\
-lopencv_contrib\
-lopencv_photo\
-lopencv_java\
-lopencv_legacy\
-lopencv_ocl\
-lopencv_stitching\
-lopencv_superres\
-lopencv_ts\
-lopencv_videostab

ANDROID_PACKAGE_SOURCE_DIR=$$_PRO_FILE_PWD_/android
}

After that the project will compile but it will fail to run with the error

E/AndroidRuntime(11873): java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1891]:   176 could not load needed library 'libopencv_java.so' for 'libMyProject.so' (load_library[1093]: Library 'libopencv_java.so' not found)

To overcome this, you need to add libopencv_java.so to your APK, and then manually load it from QtActivity.java. That's what the ANDROID_PACKAGE_SOURCE_DIR=$$_PRO_FILE_PWD_/android line at the end was for. Now you need to place libopencv_java.so here:

project_root/android/libs/armeabi-v7a/libopencv_java.so
project_root/android/src/org/qtproject/qt5/android/bindings/QtActivity.java

You can get QtActivity.java from the Android target build directory, in my case the full path was c:\Workspace\build-MyProject-Android_for_armeabi_v7a_GCC_4_9_Qt_5_4_0-Debug\android-build\src\org\qtproject\qt5\android\bindings\QtActivity.java, and just copy it.

Then you find those lines in it:

        // now load the application library so it's accessible from this class loader
if (libName != null)
System.loadLibrary(libName);

And load libopencv_java.so before them, so they become:

        // This is needed for OpenCV!!!
System.loadLibrary("opencv_java");

// now load the application library so it's accessible from this class loader
if (libName != null)
System.loadLibrary(libName);

Note that you pass opencv_java to System.loadLibrary(), even though the file is libopencv_java.so.


Edit: I forgot to mention, but I already had installed OpenCV Manager on my phone when trying to run one of the samples that come with OpenCV-2.4.10-android-sdk, so I don't know if it's needed or not. In any event, keep it in mind, if it fail even after my steps, you might need to download OpenCV Manager (it's available on the Google Store).

Edit 2: I'm using adt-bundle-windows-x86-20140702, android-ndk-r10d, OpenCV-2.4.10-android-sdk, Qt Creator 3.3.0, and my build target is "Android for armeabi-v7a (GCC 4.9, Qt 5.4.0)".

Edit 3: From Daniel Saner's comment:

In OpenCV 3.x, opencv_java has been renamed to opencv_java3. Also, while I didn't look into the specific changes that might have effected this, the workaround regarding that library in the final step seems to no longer be necessary. The app compiles and runs without the ANDROID_PACKAGE_SOURCE_DIR line

Edit 4: @myk's comment:

Worked for me with OpenCV 3.2. To workaround the build issues with carotene finish the LIBS+ section with: -lopencv_videostab\ -ltegra_hal\ – myk 2 hours ago

QT Widget using OpenCV error deploying to Android

For option 2:

Change

LIBS += \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_contrib.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_legacy.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_ml.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_objdetect.a\
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_calib3d.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_video.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_features2d.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_highgui.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_androidcamera.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_flann.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_imgproc.a \
C:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a\libopencv_core.a \
C:\programs\opencvandroidsdk\sdk\native\3rdparty\libs\armeabi-v7a\liblibjpeg.a \
C:\programs\opencvandroidsdk\sdk\native\3rdparty\libs\armeabi-v7a\liblibpng.a \
C:\programs\opencvandroidsdk\sdk\native\3rdparty\libs\armeabi-v7a\liblibtiff.a \
C:\programs\opencvandroidsdk\sdk\native\3rdparty\libs\armeabi-v7a\liblibjasper.a \
C:\programs\opencvandroidsdk\sdk\native\3rdparty\libs\armeabi-v7a\libtbb.a \

to:

LIBS += -LC:\programs\opencvandroidsdk\sdk\native\libs\armeabi-v7a \  
-lopencv_legacy \
-lopencv_ml \
-lopencv_objdetect\
... \
-ltbb

Cannot link OpenCV Android inside Qt

The workaround is: either use OpenCV 3.1.0 or older or compile OpenCV 3.2.0 with CAROTENE disabled.

I can't seem to find any other solutions for now.

How to integrate QT 5.2.0 (win7 x86) with OpenCV2.4.6 and Android

The problem occurs due to a missing library definition in the pro file (libIlmImf.a).

corrected libraries definition in pro file is as follows:

ANDROID_OPENCV = C:/OpenCV-2.4.6-android-sdk/sdk/native
LIBS += \
$$ANDROID_OPENCV/libs/x86/libopencv_contrib.a \
$$ANDROID_OPENCV/libs/x86/libopencv_legacy.a \
$$ANDROID_OPENCV/libs/x86/libopencv_ml.a \
$$ANDROID_OPENCV/libs/x86/libopencv_objdetect.a \
$$ANDROID_OPENCV/libs/x86/libopencv_calib3d.a \
$$ANDROID_OPENCV/libs/x86/libopencv_video.a \
$$ANDROID_OPENCV/libs/x86/libopencv_features2d.a \
$$ANDROID_OPENCV/libs/x86/libopencv_highgui.a \
$$ANDROID_OPENCV/libs/x86/libopencv_androidcamera.a \
$$ANDROID_OPENCV/libs/x86/libopencv_flann.a \
$$ANDROID_OPENCV/libs/x86/libopencv_imgproc.a \
$$ANDROID_OPENCV/libs/x86/libopencv_core.a \
$$ANDROID_OPENCV/3rdparty/libs/x86/libIlmImf.a \
$$ANDROID_OPENCV/3rdparty/libs/x86/liblibpng.a \
$$ANDROID_OPENCV/3rdparty/libs/x86/liblibtiff.a \
$$ANDROID_OPENCV/3rdparty/libs/x86/liblibjpeg.a \
$$ANDROID_OPENCV/3rdparty/libs/x86/liblibjasper.a \
$$ANDROID_OPENCV/3rdparty/libs/x86/libtbb.a
  • (But another problem is occurred when running in android emulator caused by "shader program is not linked". I am still working on that but this is another question's issue)
  • EDIT: I solved the problem of "shader program is not linked" by switching the emulator from GenyMotion to AVD (NEXUS S, API17, w/o googleapi, x86) and setting the "Use Host GPU" flag and adding the CONFIG+= opengl to pro file

OpenCV with other GUI (like Qt or WxWidgets) on Win32 VC++

Okay. I've got the answer to my own question for WxWidgets. One key is not to fight openCV City Hall about RGB sequence. OpenCv really likes "BGR". WxWidgets uses "RGB" only. The opencv data structure has a field for byte sequence, but it is seldom honored. Even the highGui function (on MS Windows) that displays an image will put up spectacularly blue tangerines if the byte sequence is set to "RGB". I stubbornly fixed that bug in my local installation, but other operations failed also. So, I just sigh and set the byte order on the opencv side to "BGR" and do the byte swapping as necessary.

The C++ code below requires that the openCV images that it converts to wxImages are RGB, sequence "BGR", 8 bit depth and 3 interleaved channels, and have width_step = width*3. The routines don't check compatibility. Use at your own peril. A ready-for-primetime version would provide for regions of interest (ROI) and other fanciness.

#include "wx/wx.h"
#include "cv.h"
#include "highgui.h" // Optional


void copy_and_swap_rb(char *s, char *d, int size) {
// Copy image data source s to destination d, swapping R and B channels.
// Assumes 8 bit depth, 3 interleaved channels, and width_step = width*3
const int step = 3;
char *end = s + size;
while (s<end) {
d[0] = s[2];
d[1] = s[1];
d[2] = s[0];
d += step; s += step;
}
}

void wx2cv(wxImage &wx, IplImage *ipl) {
// Copy image data from wxWidgets image to Ipl (opencv) image
// Assumes ipl image has seq "GBR", depth 8, and 3 channels, and
// has the same size as the wxImage, and width_step = width*3.
copy_and_swap_rb((char*)wx.GetData(), ipl->imageData, ipl->imageSize);
}

void cv2wx(IplImage *ipl, wxImage &wx ) {
// Copy image data from Ipl (opencv) image to wxImage
// Assumes ipl image has seq "GBR", depth 8, and 3 channels, and
// has the same size as the wxImage, and width_step = width*3.
copy_and_swap_rb( ipl->imageData, (char*)wx.GetData(),
wx.GetWidth()*wx.GetHeight()*3);
}

IplImage *cv_from_wx(wxImage &wx) {
// Return a new IplImage copied from a wxImage.
// Must be freed by user with cvReleaseImage().
IplImage *ret = cvCreateImage(cvSize(wx.GetWidth(), wx.GetHeight()),
IPL_DEPTH_8U, 3);
wx2cv(wx, ret);
return ret;
}

wxImage wx_from_cv( IplImage *cx) {
// Return new wxImage copied from a compatible IplImage.
// Assumes ipl image has seq "GBR", depth 8, and 3 channels
// Fear not. The copy on return is cheap; does not deep-copy the data.
wxImage wx(cx->width, cx->height, (unsigned char*) malloc(cx->imageSize), false);
cv2wx(cx, wx);
return wx;
}


Related Topics



Leave a reply



Submit