使用OpenCV 3.1在Android Studio 1.5中开发本机C ++应用程序

时间:2016-04-05 10:29:21

标签: android c++ opencv android-ndk

我目前正在进行" OpenCV Android编程示例"作者:Amgad Muhammad。

在第6章中,用户应该开发全景查看器。我在本章中坚持了大约两个星期,并且在尝试同步项目时仍然遇到错误。我已经尝试了其他几个代码调整,实验 - gradle-versions等,但没有一个有效。

这是我当前的build.gradle(项目):

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle-experimental:0.4.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
allprojects {
    repositories {
        jcenter()
    }
}
task clean(type: Delete) {
    delete rootProject.buildDir
}

这是我的build.gradle(模块):

apply plugin: 'com.android.model.application'
model {
android {
    compileSdkVersion = 23
    buildToolsVersion = "23.0.2"

    defaultConfig.with {
        applicationId = "com.example.moritz.ndktest"
        minSdkVersion.apiLevel = 11
        targetSdkVersion.apiLevel = 23
        versionCode = 1
        versionName = "1.0"
    }
}

android.ndk {
    moduleName = "Pano"
    ldLibs += ['log']
    cppFlags.add("-std=c++11") // Add provisions to allow C++11 functionality
    cppFlags.add("-fexceptions")
    cppFlags.add("-I${file("D:/Android/OpenCV-android-sdk/sdk/native/jni/include")}".toString())
    //cppFlags += "-I${file("D:/Android/OpenCV-android-sdk/sdk/native/jni/include/opencv")}".toString()
    ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log", "z"])
    stl = "gnustl_shared"
}

/*android.sources {
    main {
        jni {
            source {
                srcDir 'src/main/jni'
            }
        }
    }
}*/

android.buildTypes {
    release {
        minifyEnabled = false
        proguardFiles.add(file("proguard-rules.txt"))
    }
}

android.productFlavors {
    create("arm") {
        ndk.with{
            abiFilters.add("armeabi")

            File curDir = file('./')
            curDir = file(curDir.absolutePath)
            String libsDir = curDir.absolutePath + "\\src\\main\\jniLibs\\armeabi\\"

            ldLibs.add(libsDir + "libopencv_core.a")
            ldLibs.add(libsDir + "libopencv_highgui.a")
            ldLibs.add(libsDir + "libopencv_imgproc.a")
            ldLibs.add(libsDir + "libopencv_java3.so")
            ldLibs.add(libsDir + "libopencv_ml.a")

        }
    }
    create("armv7") {
        ndk.with {
            abiFilters.add("armeabi-v7a")

            File curDir = file('./')
            curDir = file(curDir.absolutePath)
            String libsDir = curDir.absolutePath + "\\src\\main\\jniLibs\\armeabi-v7a\\"
            ldLibs.add(libsDir + "libopencv_core.a")
            ldLibs.add(libsDir + "libopencv_highgui.a")
            ldLibs.add(libsDir + "libopencv_imgproc.a")
            ldLibs.add(libsDir + "libopencv_java3.so")
            ldLibs.add(libsDir + "libopencv_ml.a")
            ldLibs.add(libsDir + "libopencv_ts.a")

        }
    }
}
android.sources{
    main{
        jni{
            source{
                srcDirs += ['src/main/jni']
            }
        }
    }
}
} dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
//testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
//compile 'com.android.support:design:23.2.1'
compile project(':openCVLibrary310')
}

这是我的build.gradle(opencv310):

apply plugin: 'com.android.model.library'
model{
android {
    compileSdkVersion = 23
    buildToolsVersion = "23.0.2"

    defaultConfig {
        minSdkVersion.apiLevel = 11
        targetSdkVersion.apiLevel = 23
    }
}

android.buildTypes {
    release {
        minifyEnabled false
        proguardFiles.add(file("proguard-rules.txt"))
    }
}
}

在gradle.porperties中我有:

android.useDeprecatedNdk=true

和我的gradle-wrapper.properties看起来像:

#Mon Apr 04 13:55:17 CEST 2016
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip

我现在得到的错误:

  

错误:无法加载课程' com.android.build.gradle.managed.NdkConfig_Impl'。   此意外错误的可能原因包括:

  • Gradle的依赖关系缓存可能已损坏(这有时会在网络连接超时后发生。)   重新下载依赖项和同步项目(需要网络)
  • Gradle构建过程(守护程序)的状态可能已损坏。停止所有Gradle守护进程可以解决此问题。   停止Gradle构建过程(需要重新启动)
  • 您的项目可能正在使用第三方插件,该插件与项目中的其他插件或项目请求的Gradle版本不兼容。
对于损坏的Gradle进程,您还可以尝试关闭IDE,然后终止所有Java进程。

提前致谢!!!

修改 我将build.gradle(项目)中的类路径更改为:

classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha5'

因此我的gradle-wrapper.properties为:

distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

(在设置/构建,例外,部署/ Gradle 我已经选择"使用默认的gradle包装" btw。)

和我的buildToolsVersion到23.0.1似乎我向前迈出了一步,但现在我面临着一系列新的错误:

  

d:\的Android \ AndroidStudioProjects \ NDKtest \应用\ SRC \主\ JNI \ Pano.cpp   错误:(16,44)错误:没有匹配函数来调用' cv :: FastFeatureDetector :: FastFeatureDetector(int)'   信息:(16,44)候选人是:   在D:\ Android \ AndroidStudioProjects \ NDKtest \ app \ src \ main \ jni \ Pano.cpp:4:0中包含的文件中:   D:\ Android \ OpenCV-android-sdk \ sdk \ native \ jni \ include / opencv2 / features2d.hpp:411:20:注意:cv :: FastFeatureDetector :: FastFeatureDetector()   错误:(57,9)错误:' OrbFeatureDetector'不是' cv'的成员   错误:(58,9)错误:'检测器'在这方面没有申明   错误:(80,48)错误:没有匹配函数来调用' cv :: FastFeatureDetector :: FastFeatureDetector(int)'   信息:(80,48)候选人是:   在D:\ Android \ AndroidStudioProjects \ NDKtest \ app \ src \ main \ jni \ Pano.cpp:4:0中包含的文件中:   D:\ Android \ OpenCV-android-sdk \ sdk \ native \ jni \ include / opencv2 / features2d.hpp:411:20:注意:cv :: FastFeatureDetector :: FastFeatureDetector()   错误:(86,13)错误:' OrbFeatureDetector'不是' cv'的成员   错误:(87,13)错误:'检测器'在这方面没有申明   错误:(93,13)错误:' OrbDescriptorExtractor'不是' cv'的成员   错误:(94,13)错误:'描述符'在这方面没有申明   错误:(99,13)错误:' BriefDescriptorExtractor'不是' cv'的成员   错误:(100,13)错误:'描述符'在这方面没有申明   错误:(111,13)错误:' FREAK'不是' cv'的成员   错误:(112,13)错误:'描述符'在这方面没有申明                descriptor.compute(grayObject,objectKeyPoints,objectDescriptor);                ^   错误:任务':app:compilePanoArmeabiDebugArmSharedLibraryPanoMainCpp'执行失败。   构建操作失败。         编译Pano.cpp时C ++编译器失败。     请参阅完整日志:file:/// D:/Android/AndroidStudioProjects/NDKtest/app/build/tmp/compilePanoArmeabiDebugArmSharedLibraryPanoMainCpp/output.txt

我的Pano.cpp:

#include <jni.h>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/features2d.hpp>
#include <vector>

extern "C" {

JNIEXPORT void JNICALL Java_com_app3_pano_PanoActivity_FindFastFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
    cv::Mat& mGr  = *(cv::Mat*)addrGray;
    cv::Mat& mRgb = *(cv::Mat*)addrRgba;
    std::vector<cv::KeyPoint> v;

    cv::FastFeatureDetector detector(50);
    detector.detect(mGr, v);
    for( unsigned int i = 0; i < v.size(); i++ )
    {
        const cv::KeyPoint& kp = v[i];
        cv::circle(mRgb, cv::Point(kp.pt.x, kp.pt.y), 10, cv::Scalar(255,0,0,255));
    }
}

JNIEXPORT void JNICALL Java_com_app3_pano_PanoActivity_FindHarrisCorners(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
    cv::Mat& mGr  = *(cv::Mat*)addrGray;
    cv::Mat& mRgb = *(cv::Mat*)addrRgba;
    cv::Mat dst_norm;
    cv::Mat dst = cv::Mat::zeros(mGr.size(),CV_32FC1);
    int blockSize = 2;
    int apertureSize = 3;
    double k = 0.04;
    float threshold=150;

    cv::cornerHarris( mGr, dst, blockSize, apertureSize, k, cv::BORDER_DEFAULT );
    cv::normalize( dst, dst_norm, 0, 255, cv::NORM_MINMAX, CV_32FC1, cv::Mat() );

    for( unsigned int i = 0; i < dst_norm.rows; i++ )
    {
        float * row=dst_norm.ptr<float>(i);
        for(int j=0;j<dst_norm.cols;j++)
        {
            if(row[j]>=threshold)
            {
                cv::circle(mRgb, cv::Point(j, i), 10, cv::Scalar(255,0,0,255));
            }
        }
    }
}
JNIEXPORT void JNICALL Java_com_app3_pano_PanoActivity_FindORBFeatures(JNIEnv*, jobject, jlong addrRgba, jint featuresNumber)
{
    cv::Mat& mRgb = *(cv::Mat*)addrRgba;
    cv::Mat grayImg;
    std::vector<cv::KeyPoint> v;
    cv::cvtColor(mRgb,grayImg,cv::COLOR_RGBA2GRAY);
    cv::OrbFeatureDetector detector(featuresNumber);
    detector.detect(grayImg, v);
    cv::drawKeypoints(grayImg,v,mRgb,cv::Scalar::all(-1),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
}
JNIEXPORT void JNICALL Java_com_app3_pano_PanoActivity_FindMatches(JNIEnv*, jobject, jlong objectAddress, jlong sceneAddress,jint detectorID, jint descriptorID,jlong matchingResult)
{
    cv::Mat& object  = *(cv::Mat*)objectAddress;
    cv::Mat& scene = *(cv::Mat*)sceneAddress;
    cv::Mat& result = *(cv::Mat*)matchingResult;

    cv::Mat grayObject;
    cv::Mat grayScene;
    cv::cvtColor(object,grayObject,cv::COLOR_RGBA2GRAY);
    cv::cvtColor(scene,grayScene,cv::COLOR_RGBA2GRAY);

    std::vector<cv::KeyPoint> objectKeyPoints;
    std::vector<cv::KeyPoint> sceneKeyPoints;

    cv::Mat objectDescriptor;
    cv::Mat scenceDescriptor;

    if(detectorID==1)//FAST
    {
        cv::FastFeatureDetector detector(50);
        detector.detect(grayObject, objectKeyPoints);
        detector.detect(grayScene, sceneKeyPoints);
    }
    else if(detectorID==5)//ORB
    {
        cv::OrbFeatureDetector detector;
        detector.detect(grayObject, objectKeyPoints);
        detector.detect(grayScene, sceneKeyPoints);
    }

    if(descriptorID==3)//ORB
    {
        cv::OrbDescriptorExtractor descriptor;
        descriptor.compute(grayObject,objectKeyPoints,objectDescriptor);
        descriptor.compute(grayScene,sceneKeyPoints,scenceDescriptor);
    }
    else if(descriptorID==4)//BRIEF
    {
        cv::BriefDescriptorExtractor descriptor;
        descriptor.compute(grayObject,objectKeyPoints,objectDescriptor);
        descriptor.compute(grayScene,sceneKeyPoints,scenceDescriptor);
    }
    else if(descriptorID==5)//BRISK
    {
        cv::BRISK descriptor;
        descriptor.compute(grayObject,objectKeyPoints,objectDescriptor);
        descriptor.compute(grayScene,sceneKeyPoints,scenceDescriptor);
    }
    else if(descriptorID==6)//FREAK
    {
        cv::FREAK descriptor;
        descriptor.compute(grayObject,objectKeyPoints,objectDescriptor);
        descriptor.compute(grayScene,sceneKeyPoints,scenceDescriptor);
    }

    cv::BFMatcher matcher(cv::NORM_HAMMING);
    std::vector< cv::DMatch > matches;
    matcher.match( objectDescriptor, scenceDescriptor, matches);

    double min_dist = 100;
    for( int i = 0; i < objectDescriptor.rows; i++ )
    {
        double dist = matches[i].distance;
        if( dist < min_dist ) min_dist = dist;
    }
    std::vector< cv::DMatch > good_matches;
    for( int i = 0; i < objectDescriptor.rows; i++ )
    {
        if( matches[i].distance <= 3*min_dist )
        {
            good_matches.push_back( matches[i]);
        }
    }
    drawMatches( grayObject, objectKeyPoints, grayScene, sceneKeyPoints,good_matches, result, cv::Scalar::all(-1), cv::Scalar::all(-1),
                 std::vector<char>(),
                 cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS+cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);

}
}

所以看起来我通过cppFlags.add()链接到我的build.gradle(模块)中的opencv-include-folder无法正常工作。但我真的不知道它有什么问题吗?

开发环境:

  • Windows 10(x64)
  • Android Studio 1.5.1
  • jdk1.8.0_73
  • NDK-R11B
  • 的OpenCV-3-1-0

2 个答案:

答案 0 :(得分:2)

哦,我也正在读这本书。本书中的代码适用于旧版Opencv(2.4)。您需要阅读Opencv 3.1.0的参考,因为某些类(例如FastFeatureDetectorOrbFeatureDetecture,..)已更改。我的FindFastFeature和ORB功能:

p / s:不要只是复制代码,你应该修改它并逐个完成这些功能。

JNIEXPORT void JNICALL
Java_com_hieuvecto_softscanner2_MainActivity_FindFastFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba){
    cv::Mat& mGr = *(cv::Mat*)addrGray;
    cv::Mat& mRgb = *(cv::Mat*)addrRgba;
    std::vector<cv::KeyPoint> v;
    cv::Ptr<cv::FeatureDetector> detector = cv::FastFeatureDetector::create(50);
    detector->detect(mGr, v);
    for (unsigned int i=0; i<v.size(); i++) {
        const cv::KeyPoint& kp = v[i];
        cv::circle(mRgb, cv::Point(kp.pt.x, kp.pt.y), 10, cv::Scalar(255,0,0,255));
    }
}

JNIEXPORT void JNICALL
Java_com_hieuvecto_softscanner2_MainActivity_OrbFeaturesDetector(JNIEnv*, jobject, jlong addrRgba, jint featuresNumber) {
    cv::Mat& mRgb = *(cv::Mat*)addrRgba;
    cv::Mat grayImg;
    std::vector<cv::KeyPoint> v;
    cv::cvtColor(mRgb, grayImg, cv::COLOR_RGBA2GRAY);
    cv::Ptr<cv::FeatureDetector> detector = cv::ORB::create(featuresNumber);
    detector->detect(grayImg, v);
    cv::drawKeypoints(grayImg,v,mRgb,cv::Scalar::all(-1),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
}

我的app.gradle app模块:

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.3"

        defaultConfig.with {
            applicationId = "com.hieuvecto.softscanner2"
            minSdkVersion.apiLevel = 15
            targetSdkVersion.apiLevel = 23
            versionCode = 1
            versionName = "1.0"
        }
    }

    //Make  sure    to  build   with    JDK version 7


    android.buildTypes {
        release {
            // minifyEnabled = false
            // proguardFiles = getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    android.ndk {
        moduleName = "Pano"
        cppFlags.add("-I${file("D:/download/OpenCV-android-sdk/sdk/native/jni/include")}".toString())
        cppFlags.add("-std=c++11")
        cppFlags.add("-frtti")
        cppFlags.add("-fexceptions")
        ldLibs.addAll(["log", "opencv_java3"])
        stl    = "gnustl_static"
    }

    android.productFlavors {
        create("arm") {
            ndk.abiFilters.add("armeabi")
            ndk.ldFlags.add("-L${file('src/main/jniLibs/armeabi')}".toString())
        }
        create("arm7") {
            ndk.abiFilters.add("armeabi-v7a")
            ndk.ldFlags.add("-L${file('src/main/jniLibs/armeabi-v7a')}".toString())
        }
        create("arm8") {
            ndk.abiFilters.add("arm64-v8a")
            ndk.ldFlags.add("-L${file('src/main/jniLibs/arm64-v8a')}".toString())
        }
    }

}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile project(':openCVLibrary310')
    compile 'com.android.support:appcompat-v7:23.2.1'
}

答案 1 :(得分:0)

嗯,您使用静态库,但不预先构建它们。 检查this