2016-01-10 2 views
4

В настоящее время я работаю над проектом, который использует OpenCV3 для обработки видео в реальном времени (с применением набора цветовых фильтров), и мне удалось получить его для работы с Java без каких-либо проблем.Android Studio, связывающая статические библиотеки OpenCV

То, что я пытаюсь сделать дальше, - реализовать всю мою Java-логику до C++ через NDK (для повышения производительности). Таким образом, мне не нужно будет преобразовывать объект MAT в байтовые буферы назад и форт, сохраняя пару циклов. Но я действительно застрял, пытаясь связать .so, .a статические библиотеки и файлы заголовков, используя gradle для использования в моих .CPP-файлах.

Это Gradle файл, который я использую:

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') 
} 

Я основывая свой Gradle файл на this пример, который я нашел на GitHub. Теперь одна из проблем, которые я обнаружил, пытаясь сделать это, состоит в том, что OPENCV имеет пару файлов статических библиотек, так как этот post говорит, что я должен добавить каждый из них в другую библиотеку на градиенте, чтобы связать их, так вот почему мой файл градиента заполнен повторяющимися определениями библиотек.

Теперь, когда я пытаюсь включить файлы заголовков в мой .CPP-код, Android Studio не может их найти (даже не использовать пространство имен). Это мой код CPP:

#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)); 
    } 
} 
} 

Я пропустил что-то, чтобы связать их правильно?

+1

Вы ссылки на статические библиотеки OpenCV, что очень важно, чтобы * ссылка * бинарный файл. Но, чтобы * скомпилировать * ваш код, вы должны указать ** cppFlags **. Почему вы прокомментировали эту часть с 'def jniPath' и дальше? –

+1

OMG вы были правы! Я удалил причину, по которой градиент cppFlags не смог прочитать файл конфигурации ... После некоторого копания я узнал, что они удаляют + = для назначения, и теперь у вас есть tad use .add и .addAll (как объект), и теперь gradle может найти все ссылки заголовков. Прошло некоторое время с тех пор, как я скомпилировал проект на C++ и забыл о флажках. – vicmns

+0

@AlexCohn Что именно должно идти в ** cppFlags ** переменная? –

ответ

3

Существуют зависимости между статическими библиотеками OpenCV. Поэтому вам нужно включить их в правильный порядок. .а и .o включает в порядок зависит в GCC, файлы, которые имеют зависимостей должны быть включены до файлов, которые они зависят от:

CV_LIBS = \ 
    $(CV_LIB_FOLDER)/libopencv_calib3d.a \ 
    $(CV_LIB_FOLDER)/libopencv_highgui.a \ 
    $(CV_LIB_FOLDER)/libopencv_video.a \ 
    $(CV_LIB_FOLDER)/libopencv_objdetect.a \ 
    $(CV_LIB_FOLDER)/libopencv_imgproc.a \ 
    $(CV_LIB_FOLDER)/libopencv_imgcodecs.a \ 
    $(CV_LIB_FOLDER)/libopencv_core.a \ 
    $(CV_LIB_FOLDER)/libopencv_hal.a 
Смежные вопросы