Currently I'm working on a project that uses OpenCV3 for realtime video processing (applying a set of color filters), and I managed to get the it to work with Java without any problem.
What I try to do next is to implement all my Java logic to C++ through NDK (in order to improve performance). This way I won't need to convert MAT object to byte buffers back and fort, saving a couple of cycles. But I'm really stuck trying to link the .so, .a static libraries and headers files using gradle to be used on my .CPP files.
This is the gradle file that I'm using:
apply plugin: 'com.android.model.application'
def opencvandroid_sdk_path = file(project(':opencvandroid').projectDir).absolutePath + "/src/main"
model {
repositories {
libs(PrebuiltLibraries) {
opencv {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_calib3d.a")
}
}
opencv1 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_core.a")
}
}
opencv2 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_features2d.a")
}
}
opencv3 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_flann.a")
}
}
opencv4 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_highgui.a")
}
}
opencv5 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_imgcodecs.a")
}
}
opencv6 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_imgproc.a")
}
}
opencv7 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_ml.a")
}
}
opencv8 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_objdetect.a")
}
}
opencv9 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_photo.a")
}
}
opencv10 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_shape.a")
}
}
opencv11 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_stitching.a")
}
}
opencv12 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_superres.a")
}
}
opencv13 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_video.a")
}
}
opencv14 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_videoio.a")
}
}
opencv15 {
headers.srcDir "${opencvandroid_sdk_path}/jni/include/opencv2"
binaries.withType(StaticLibraryBinary) {
staticLibraryFile = file("${opencvandroid_sdk_path}/jniLibs/${targetPlatform.getName()}/libopencv_videostab.a")
}
}
}
}
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "com.example"
minSdkVersion.apiLevel = 16
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = "1.0"
}
}
/*
* native build settings
*/
android.ndk {
moduleName = "hello-jni"
/*
* Other ndk flags configurable here are
* cppFlags += "-fno-rtti"
* cppFlags += "-fno-exceptions"
* ldLibs = ["android", "log"]
* stl = "system"
*/
platformVersion = 16 //same as minSdkVersion.apiLevel for better compatibility
/*def jniPath = opencvandroid_sdk_path + "jniLibs"
cppFlags += "-I${file(jniPath)}".toString()
file(jniPath).eachDirRecurse { dir ->
cppFlags += "-I${file(dir)}".toString()
}*/
stl = "c++_static"
ldLibs.addAll(["atomic", "log", "android"])
}
android.sources {
main {
jni {
dependencies {
library "opencv1" linkage "static"
library "opencv2" linkage "static"
library "opencv3" linkage "static"
library "opencv4" linkage "static"
library "opencv5" linkage "static"
library "opencv6" linkage "static"
library "opencv7" linkage "static"
library "opencv8" linkage "static"
library "opencv9" linkage "static"
library "opencv10" linkage "static"
library "opencv11" linkage "static"
library "opencv12" linkage "static"
library "opencv13" linkage "static"
library "opencv14" linkage "static"
library "opencv15" linkage "static"
}
}
}
}
android.buildTypes {
release {
minifyEnabled = false
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile project(':opencvandroid')
}
I'm basing my gradle file on this example that I found on github. Now, one of the issues that I discover trying to do so, is that OPENCV have a couple of static libraries files, so as this post says, I have to add each one on a different lib on gradle in order to link them, so that's why my gradle file is filled with repeating library definitions.
Now when I'm trying to include the headers files on my .CPP code, Android Studio cannot find them (not even the namespace to use). This is my CPP code:
#include <jni.h>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/features2d/features2d.hpp"
#include <vector>
using namespace std;
using namespace cv;
extern "C" {
JNIEXPORT void JNICALL Java_com_example_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);
JNIEXPORT void JNICALL Java_com_example_Tutorial2Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
Mat& mGr = *(Mat*)addrGray;
Mat& mRgb = *(Mat*)addrRgba;
vector<KeyPoint> v;
Ptr<FeatureDetector> detector = FastFeatureDetector::create(50);
detector->detect(mGr, v);
for( unsigned int i = 0; i < v.size(); i++ )
{
const KeyPoint& kp = v[i];
circle(mRgb, Point(kp.pt.x, kp.pt.y), 10, Scalar(255,0,0,255));
}
}
}
Am I missing something in order to link them correctly?