不满足的链接错误 - OpenCV for Android 非本地化

17
几天前,我在这里询问了一个关于非本机OpenCV代码运行时出现的UnsatisfiedLinkError问题。我认为通过重新安装Eclipse并关闭/重新打开所有包后问题已经解决了,但是当我将OpenCV代码放入现有的onCreate()方法中后,问题又出现了。
我创建了一个名为Start的活动的新Android应用程序。然后,我进入项目属性并将OpenCV添加为库。以下是该活动的代码(Start.java):
package com.test;

import org.opencv.core.Mat;
import org.opencv.highgui.Highgui;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;

public class Start extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_start);

        Mat Image = Highgui.imread("/image.jpg");
        if (Image == null) {
            AlertDialog ad = new AlertDialog.Builder(this).create(); 
            ad.setMessage("Fatal error: can't open /image.jpg!");  
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_start, menu);
        return true;
    }
}

这是日志:

08-13 12:26:14.791: E/Trace(1067): error opening trace file: No such file or directory (2)
08-13 12:26:15.191: W/dalvikvm(1067): No implementation found for native Lorg/opencv/highgui/Highgui;.imread_1:(Ljava/lang/String;)J
08-13 12:26:15.191: D/AndroidRuntime(1067): Shutting down VM
08-13 12:26:15.191: W/dalvikvm(1067): threadid=1: thread exiting with uncaught exception (group=0x40a13300)
08-13 12:26:15.201: E/AndroidRuntime(1067): FATAL EXCEPTION: main
08-13 12:26:15.201: E/AndroidRuntime(1067): java.lang.UnsatisfiedLinkError: Native method not found: org.opencv.highgui.Highgui.imread_1:(Ljava/lang/String;)J
08-13 12:26:15.201: E/AndroidRuntime(1067):     at org.opencv.highgui.Highgui.imread_1(Native Method)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at org.opencv.highgui.Highgui.imread(Highgui.java:324)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at com.test.Start.onCreate(Start.java:18)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.Activity.performCreate(Activity.java:5008)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.access$600(ActivityThread.java:130)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.os.Looper.loop(Looper.java:137)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at android.app.ActivityThread.main(ActivityThread.java:4745)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at java.lang.reflect.Method.invokeNative(Native Method)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at java.lang.reflect.Method.invoke(Method.java:511)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
08-13 12:26:15.201: E/AndroidRuntime(1067):     at dalvik.system.NativeStart.main(Native Method)

再次强调,这是非本地代码,因此出现Unsatisfied Link Error并没有太多意义。


2
但这是Java包装器,因此它从Java代码调用本地(C ++)函数。确保您的apk包含“opencv_java.so”。 - ArtemStorozhuk
1
你也可以在这里提出问题:http://answers.opencv.org/questions/ 这是官方的OpenCV维基,看起来是以StackOverflow为模板。 - Iain_b
@Astor 我意识到尽管目录结构完好无损,但版本控制已经删除了实际的库,所以我不得不替换它们。做得好!不幸的是,我仍然遇到相同的错误。在\OpenCV\sdk\native\libs\中有三个libopencv_java.so的版本:一个在\armeabi中,一个在armeabi-v7a中,还有一个在\x86中。 - 1''
@lain_b 好主意,我也会去问问那里。 - 1''
8个回答

38

在大量搜索后,我发现了这篇文章:

"3. 如果您的应用程序项目没有 JNI 部分,则只需将相应的 OpenCV 原生库从 /sdk/native/libs/ 复制到您的项目目录中的 libs/ 文件夹。"

因此,这意味着需要复制 \armeabi、\armeabi-v7a 和 \x86 文件夹。

"4. 在调用 OpenCV API 之前,启用 OpenCV 在您的应用程序中的最后一步是 Java 初始化代码。例如,它可以在 Activity 类的静态部分中完成,该部分仅在创建类的任何实例之前执行一次:

static {
    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    }
}

或者,您可以将其放在onCreate方法中:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_load_image);
    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    }
    [...]
}

现在它可以工作了!


1
静态块在onCreate内部创建时会出错。它说要添加“EnumBody”才能完成块。这是什么意思?我仍然遇到了unsatisfiedLinkError错误。 - Rekha
2
静态部分已经为我完成了工作。当然,它应该被放在方法之外并放在主活动本身中。 - Mahm00d
我尝试了你上面提到的相同方法。但是当我执行程序时,出现了异常。java.lang.UnsatisfiedLinkError: Native method not found: org.opencv.highgui.Highgui.imread_1:(Ljava/lang/String;)J - Ajay S
@TGMCians 你确定在 <yourapp>\libs\armeabi-v7a 下有 libopencv_highgui.a 吗?并且 OpenCVLoader.initDebug() 成功了吗? - 1''
它起作用了,我在Android Studio中将*.so文件复制到了错误的位置,谢谢。 - Ajay S
非常感谢您,1先生。我一直在处理这个问题已经4个小时了,最终我来到了这里,按照您的建议,将项目中的所有.so文件都复制了一遍,现在它正常工作了。 - Manpreet

8
你应该使用:

标签


if (!OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack))
{
    Log.e("TEST", "Cannot connect to OpenCV Manager");
}

在 OnCreate() 中使用

private BaseLoaderCallback  mOpenCVCallBack = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                               Mat Image = Highgui.imread("/image.jpg");
                               if (Image == null) {
                                   AlertDialog ad = new AlertDialog.Builder(this).create(); 
                                   ad.setMessage("Fatal error: can't open /image.jpg!");  
                                }
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
    }
    };

这在声明opencv类型的成员时给了我很多不满意的链接异常。静态初始化有所帮助。 - Bachi
OpenCVLoader.OPENCV_VERSION_(USE_LATEST_VERSION) - AMD

7
在大多数情况下,在调用openCV之前加上这样一行代码就足够了:"System.loadLibrary(Core.NATIVE_LIBRARY_NAME);"

这仅适用于Java项目,无法在Android上运行。 - Shridutt Kothari

3
我正在将OpenCV添加到我的Android Studio项目中。当本地文件在运行时不可用时,会发生此错误。因此,您需要将本地文件复制到正确的位置。
首先,在此位置 /app/src/main/ 创建jniLibs文件夹,并将从OpenCV SDK中复制所有带有*.so文件(armeabi,armeabi-v7a,mips,x86)的文件夹放入jniLibs。还要确保Gradle插件版本高于0.7.2+。
如下图所示:enter image description here

非常感谢。除了这个解决方案,其他的都对我无效。谢谢 :) - Muhammad Hashim Shafiq

2
问题在于您在OpenCV4Android库加载完成之前使用了Highgui.imread方法。在加载OpenCV4Android库之前,Android会调用“onCreate”方法。因此,请像这样为您的OpenCV代码创建一个单独的方法:-
public class Start extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_start);
   }

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_start, menu);
    return true;
   }

public void readImage {
    Mat Image = Highgui.imread("/image.jpg");
    if(Image=null) {
    Log.i("Start", "--------Image Cannot be Loaded--------");
    else if(!Image=null) {
    Log.i("Start", "--------Image Loaded Successfully--------");
   }

}


1
答案中的链接无法使用,我不得不花一些时间挖掘适合我的解决方案。
我首先在类中定义了一个BaseLoaderCallback。
private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");
               // any immediate code for using OpenCV
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};

在 onResume 函数中,我有以下内容:
@Override
public void onResume()
{
    super.onResume();
    if (!OpenCVLoader.initDebug()) {
        Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
    } else {
        Log.d(TAG, "OpenCV library found inside package. Using it!");
        mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);

    }
}

请确保以下内容:

1.您将OPENCV_VERSION_3_0_0更改为您的版本

  1. 在加载之前不要运行任何opencv库。即使在onCreate()中,opencv也还没有加载。最好将其放在onManagerConnected()函数中,在成功加载OpenCV的switch case中。

0
在我的情况下,我将opencv类粘贴到了错误的包名中。
错误的包名:
我将opencv类粘贴到了com.opencv中 -> 所有类
正确的包名: org.opencv -> 所有类
更改为正确的包名后,它就可以正常工作了。
原因是他们可能会引用“org.opencv..”

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接