Features2D + Homography OpenCV链接错误

时间:2016-10-19 07:16:46

标签: android opencv android-studio android-ndk java-native-interface

我一直在尝试使用 Android NDK OpenCV-2.4.10 Android Studio 2.2 中编译this源代码和 OpenCV-2.4.10-android-sdk 。 我已经能够使用这个thread和Android NDK编译库,但问题是,当我运行应用程序时,它崩溃了这个例外:

10-19 13:16:52.401 27219-27219/? W/System.err: Native code library failed to load.
10-19 13:16:52.401 27219-27219/? W/System.err: java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader[DexPathList[[dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-support-annotations-24.2.1_fed5c262a94aefc942781eb9d084010e5bac6a17-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-internal_impl-24.2.1_c5ce2ccc24f48fdeeaa83795c4a9965b3b0000bd-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-internal_impl-24.2.1_9180b436d4d87e2a23c5c519d7114d01fff80862-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-internal_impl-24.2.1_758040e3c9887b663eba33123666f0d3d8eb7843-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-internal_impl-24.2.1_756c53f48345dbb2e71bd2438ac9f2c3ae9d1134-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-internal_impl-24.2.1_62ee59c260ed6ea416c5d3215fa59796bfc5182d-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-vector-drawable-24.2.1_d52f38f279dcae00c9d3cbbeafe8ac633a0ecca4-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-v4-24.2.1_d95c4ed9fe44ddeb9a8a8aae5e16887920d4daf8-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-media-compat-24.2.1_9fa2c3bc1a23639dc03b19b5edb12c0d69de4a65-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-fragment-24.2.1_5761e83f1e521bc942c5fda0d5d1732e153d7fc2-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-core-utils-24.2.1_a2346acb90d9291006f5de9a4c03663e9a37e36b-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-core-ui-24.2.1_fb6dfb901874f3fff658664f859ae460d253e846-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-support-compat-24.2.1_b0964989f1de3db4f3e423aa1bea8410573c9efe-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-appcompat-v7-24.2.1_4842b08591f3514a767dfa2e4af7ee994ac6115e-classes.dex", dex file "/data/data/com.example.shahzeb.testingndk/files/instant-run/dex/slice-com.android.support-animated-vector-drawable-24.2.1_889e0b48597230c226324f209f1b26d855496bb4-classes.dex"],nativeLibraryDirectories=[/data/app/com.example.shahzeb.testingndk-2/lib/arm, /vendor/lib, /system/lib]]] couldn't find "libhomography.so"
java.lang.UnsatisfiedLinkError: No implementation found for void com.example.testingndk.MainActivity.runDemo() (tried Java_com_example_testingndk_MainActivity_runDemo and Java_com_example_testingndk_MainActivity_runDemo__)
                                                           at com.example.testingndk.MainActivity.runDemo(Native Method)
                                                           at com.example.testingndk.MainActivity.onCreate(MainActivity.java:34)
                                                           at android.app.Activity.performCreate(Activity.java:6251)
                                                           at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                                                           at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                                                           at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                                                           at android.app.ActivityThread.-wrap11(ActivityThread.java)
                                                           at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                                                           at android.os.Handler.dispatchMessage(Handler.java:102)
                                                           at android.os.Looper.loop(Looper.java:148)
                                                           at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                           at java.lang.reflect.Method.invoke(Native Method)
                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

我检查了我的包和方法名称,它们是相同的。我必须在Android.mk中遗漏一些东西。完整的源代码如下。

Android.mk

LOCAL_PATH  := $(call my-dir)
OPENCV_PATH := C:/OpenCV-2.4.10-android-sdk/sdk/native/jni

include $(CLEAR_VARS)
OPENCV_INSTALL_MODULES := on
OPENCV_CAMERA_MODULES  := off
include $(OPENCV_PATH)/OpenCV.mk

LOCAL_C_INCLUDES :=             \
    $(LOCAL_PATH)               \
    $(OPENCV_PATH)/include

LOCAL_SRC_FILES :=              \
    demo.cpp                    \
    nonfree_init.cpp            \
    sift.cpp                    \
    surf.cpp


LOCAL_MODULE := homography
LOCAL_CFLAGS := -Werror -O3 -ffast-math
LOCAL_LDLIBS := -llog -ldl

include $(BUILD_SHARED_LIBRARY)

demo.cpp

#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <android/log.h>

#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/nonfree.hpp"

using namespace cv;

#define  LOG_TAG    "nonfree_jni_demo"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

typedef unsigned char uchar;

void run_demo();

void run_demo()
{

    Mat img_object = imread( "/sdcard/DCIM/Camera/test1.jpg", CV_LOAD_IMAGE_GRAYSCALE );
    Mat img_scene = imread( "/sdcard/DCIM/Camera/test2.jpg", CV_LOAD_IMAGE_GRAYSCALE );

    if( !img_object.data || !img_scene.data ) {
//        std::cout<< " --(!) Error reading images " << std::endl;
        LOGI("Could not open or find the image!\n");
    }

    //-- Step 1: Detect the keypoints using SURF Detector
    int minHessian = 400;

    SurfFeatureDetector detector( minHessian );

    std::vector<KeyPoint> keypoints_object, keypoints_scene;

    detector.detect( img_object, keypoints_object );
    detector.detect( img_scene, keypoints_scene );

    //-- Step 2: Calculate descriptors (feature vectors)
    SurfDescriptorExtractor extractor;

    Mat descriptors_object, descriptors_scene;

    extractor.compute( img_object, keypoints_object, descriptors_object );
    extractor.compute( img_scene, keypoints_scene, descriptors_scene );

    //-- Step 3: Matching descriptor vectors using FLANN matcher
    FlannBasedMatcher matcher;
    std::vector< DMatch > matches;
    matcher.match( descriptors_object, descriptors_scene, matches );

    double max_dist = 0; double min_dist = 100;

    //-- Quick calculation of max and min distances between keypoints
    for( int i = 0; i < descriptors_object.rows; i++ )
    { double dist = matches[i].distance;
        if( dist < min_dist ) min_dist = dist;
        if( dist > max_dist ) max_dist = dist;
    }

//    printf("-- Max dist : %f \n", max_dist );
//    printf("-- Min dist : %f \n", min_dist );

    //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )
    std::vector< DMatch > good_matches;

    for( int i = 0; i < descriptors_object.rows; i++ )
    { if( matches[i].distance < 3*min_dist )
        { good_matches.push_back( matches[i]); }
    }

    Mat img_matches;
    drawMatches( img_object, keypoints_object, img_scene, keypoints_scene,
                 good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
                 vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

    //-- Localize the object
    std::vector<Point2f> obj;
    std::vector<Point2f> scene;

    for( int i = 0; i < good_matches.size(); i++ )
    {
        //-- Get the keypoints from the good matches
        obj.push_back( keypoints_object[ good_matches[i].queryIdx ].pt );
        scene.push_back( keypoints_scene[ good_matches[i].trainIdx ].pt );
    }

    Mat H = findHomography( obj, scene, CV_RANSAC );

    //-- Get the corners from the image_1 ( the object to be "detected" )
    std::vector<Point2f> obj_corners(4);
    obj_corners[0] = cvPoint(0,0); obj_corners[1] = cvPoint( img_object.cols, 0 );
    obj_corners[2] = cvPoint( img_object.cols, img_object.rows ); obj_corners[3] = cvPoint( 0, img_object.rows );
    std::vector<Point2f> scene_corners(4);

    perspectiveTransform( obj_corners, scene_corners, H);

    //-- Draw lines between the corners (the mapped object in the scene - image_2 )
    line( img_matches, scene_corners[0] + Point2f( img_object.cols, 0), scene_corners[1] + Point2f( img_object.cols, 0), Scalar(0, 255, 0), 4 );
    line( img_matches, scene_corners[1] + Point2f( img_object.cols, 0), scene_corners[2] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
    line( img_matches, scene_corners[2] + Point2f( img_object.cols, 0), scene_corners[3] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );
    line( img_matches, scene_corners[3] + Point2f( img_object.cols, 0), scene_corners[0] + Point2f( img_object.cols, 0), Scalar( 0, 255, 0), 4 );

    //-- Show detected matches
    imshow( "Good Matches & Object detection", img_matches );

    waitKey(0);
}

void readme();

/** @function readme */
void readme(){
//    std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl;
    LOGI(" Usage: ./SURF_descriptor <img1> <img2>\n");
}

extern "C" {
    JNIEXPORT void JNICALL Java_com_example_testingndk_MainActivity_runDemo(JNIEnv * env, jobject obj);
};

JNIEXPORT void JNICALL Java_com_example_testingndk_MainActivity_runDemo(JNIEnv * env, jobject obj)
{
    LOGI( "Start run_demo! \n");
    run_demo();
    LOGI( "End run_demo!\n");
}

MainActivity.java

package com.example.testingndk;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;


public class MainActivity extends AppCompatActivity {

    static
    {
        try
        {
            // Load necessary libraries.
            System.loadLibrary("homography");
        }
        catch( UnsatisfiedLinkError e )
        {
            System.err.println("Native code library failed to load.\n" + e);
        }
    }

    public static native void runDemo();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.v("nonfree_jni_demo", "start runDemo");
        // Call the JNI interface
        runDemo();
    }


}

1 个答案:

答案 0 :(得分:0)

@uelordi感谢您的支持。

我已将 jni 文件夹放在项目目录的根目录中,因此在使用ndk-build进行编译后,我从libs文件夹中复制了生成的*.so文件(在编译后生成同一目录)到myapp / src / main / jniLibs我现在可以运行 OpenCV 代码了。我希望它可以帮助别人。