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
How to Place Fragment Arrylist Scrollabletabsactivity
Storing Dimensions in Xml File in Android
Android Listview Refresh Single Row
Handle Screen Rotation Without Losing Data - Android
How to Change Progressbar's Progress Indicator Color in Android
Android Spinner:Avoid Onitemselected Calls During Initialization
How to Start Android Service on Installation
Why Does Eclipse Automatically Add Appcompat V7 Library Support Whenever I Create a New Project
Webview Shouldinterceptrequest Example
How to Add a Notification Badge/Count to Application Icon on Sony Xperia Devices
Android Log.V(), Log.D(), Log.I(), Log.W(), Log.E() - When to Use Each One
What Does Porterduff.Mode Mean in Android Graphics.What Does It Do
How to Marshall and Unmarshall a Parcelable to a Byte Array with Help of Parcel
How to Create Edittext Accepts Alphabets Only in Android
Why Does the Google Play Store Say My Android App Is Incompatible with My Own Device
Notification to Restore a Task Rather Than a Specific Activity
Is There a List of Screen Resolutions for All Android Based Phones and Tablets