java OpenCV Android - 无法解析对应的 JNI 函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33455235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:41:42  来源:igfitidea点击:

OpenCV Android - Cannot Resolve Corresponding JNI Function

javaandroidc++opencvandroid-ndk

提问by ConorB

I'm trying to setup Android Studio with Opencv by following this tutorial outlined here: https://www.youtube.com/watch?v=OTw_GIQNbD8

我正在尝试按照此处概述的本教程使用 Opencv 设置 Android Studio:https: //www.youtube.com/watch?v=OTw_GIQNbD8

I can get the result obtained by the person giving the tutorial but upon trying to actually use some of Opencv's functions I run into some trouble.

我可以得到提供教程的人获得的结果,但是在尝试实际使用 Opencv 的某些功能时,我遇到了一些麻烦。

I am able to load the Opencv library but upon trying use some of the native functions such as "Imgcodecs.imread" I get the error: ".lang.UnsatisfiedLinkError: No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_1(java.lang.String)"

我能够加载 Opencv 库,但是在尝试使用一些本机函数(例如“Imgcodecs.imread”)时,我收到错误消息:“.lang.UnsatisfiedLinkError: No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_1( java.lang.String)"

I believe I have tracked down the issue to the following:

我相信我已经将问题追溯到以下几点:

[![enter image description here][1]][1]

[![在此处输入图像描述][1]][1]

It seems that Android Studio is unable to detect the native C++ code which I'm guessing should be picked up from jniLibs folder I now have in app/src/main?

似乎 Android Studio 无法检测到我猜应该从我现在在 app/src/main 中拥有的 jniLibs 文件夹中获取的本机 C++ 代码?

I've tried updating Android Studio to the latest stable build and I have fixed my file paths for my android SDK and NDK as having white-space can apparently affect the running of native code. The issue still persists.

我已经尝试将 Android Studio 更新到最新的稳定版本,并且我已经修复了我的 android SDK 和 NDK 的文件路径,因为空格显然会影响本机代码的运行。问题仍然存在。

I have been trying to fix this for the last 4 hours, any help would be greatly appreciated!

过去 4 个小时我一直在努力解决这个问题,任何帮助将不胜感激!

采纳答案by ConorB

FINAL EDIT: I've made a tutorial explaining how to install Opencv for Android along with SIFT/SURF algorithms - https://www.youtube.com/watch?v=cLK9CjQ-pNI

最终编辑:我制作了一个教程,解释了如何为 Android 安装 Opencv 以及 SIFT/SURF 算法 - https://www.youtube.com/watch?v=cLK9CjQ-pNI

It appears that I have solved my issue with using the following file structure and dependencies. I can't say for sure how I got it to work but I believe if you copy my structure here then yours should work too.

看来我已经使用以下文件结构和依赖项解决了我的问题。我不能肯定地说我是如何让它工作的,但我相信如果你在这里复制我的结构,那么你的也应该工作。

Ensure that there are no spaces present in your file path to your Android SDK or NDK. Android Studio warns that this may cause issue when loading native code.

确保 Android SDK 或 NDK 的文件路径中没有空格。Android Studio 警告说,这可能会导致加载本机代码时出现问题。

Place the folders containing the '*.so' files into /YOUR_PROJECT_ROOT/libs (You'll probably have to manually create this libs folder). All the other solutions online stating to put them into app/src/main/jniLibs did not work for me.

将包含 '*.so' 文件的文件夹放入 /YOUR_PROJECT_ROOT/libs(您可能必须手动创建此 libs 文件夹)。在线说明将它们放入 app/src/main/jniLibs 的所有其他解决方案对我不起作用。

To include the openCVLibrary300, I imported it as a module using File->New->Import Module, the set the Source Directory to something like ..\OpenCV-android-sdk\sdk\java

为了包含 openCVLibrary300,我使用 File->New->Import Module 将其作为模块导入,将 Source Directory 设置为类似 ..\OpenCV-android-sdk\sdk\java

Ensure build.gradle files in both the app and the imported library share the same min and max sdk version etc.

确保应用程序和导入的库中的 build.gradle 文件共享相同的最小和最大 sdk 版本等。

Sample code used to test - http://pastebin.com/2zzU5B9G

用于测试的示例代码 - http://pastebin.com/2zzU5B9G

The sample code I've posted above ensures the libraries are loaded before using Opencv methods. It uses the Imgcodecs.imread() function that uses native code in C++ that was previously giving me the ".lang.UnsatisfiedLinkError: No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_1(java.lang.String)" error.

我在上面发布的示例代码可确保在使用 Opencv 方法之前加载库。它使用 Imgcodecs.imread() 函数,该函数使用 C++ 中的本机代码,该函数以前给我“.lang.UnsatisfiedLinkError: No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_1(java.lang.String)”错误.

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

回答by Vitt Volt

I think I am the right person to give you a practical answer on this problem after solving the ndk issue with Android Studio before struggling for a week. It means that you have solved the issue but I can give more information on how to setup your own native files in case you need it.

我认为在用 Android Studio 解决了 ndk 问题之后,在挣扎了一周之前,我是为您提供有关此问题的实际答案的合适人选。这意味着您已经解决了问题,但我可以提供有关如何设置您自己的本机文件的更多信息,以备不时之需。

The first thing you have to know is that currently Android Studio still has some internal flaws and the native function declarations in the Java source files might still trigger a "Cannot resolve..." message. It is ok actually, as long as all your sources codes are correct and you have done the compilation correctly, nothing will be wrong.

您首先要知道的是,目前 Android Studio 仍然存在一些内部缺陷,Java 源文件中的本机函数声明可能仍会触发“无法解析...”消息。其实没问题,只要你所有的源代码都是正确的,并且编译正确,就不会出错。

If you don't have your own native files (C++,C) in your project, just put the .a or .so native libraries in the src/main/jniLibs folders and you don't have to modify anything in the gradle file. The system will do everything for you automatically.

如果您的项目中没有自己的本机文件(C++、C),只需将 .a 或 .so 本机库放在 src/main/jniLibs 文件夹中,您无需修改​​ gradle 文件中的任何内容. 系统会自动为您做所有事情。

If you have own native files and have put them in the src/main/jni folder, then you have to create your own makefiles and put them in the jni folder as well. You also have to modify the gradle file in your app module.

如果您有自己的本机文件并将它们放在 src/main/jni 文件夹中,那么您必须创建自己的 makefile 并将它们也放在 jni 文件夹中。您还必须修改应用模块中的 gradle 文件。

Here is what I did for a face detection sample of opencv, and I got the original code from this wonderful post(Here), which was actually modified from another one's method for simpler execution:

这是我对opencv的人脸检测样本所做的,我从这篇精彩的帖子(这里)中得到了原始代码,实际上是从另一个人的方法中修改的,以简化执行:

My project structure: Project Structure

我的项目结构: 项目结构

My makefiles (make sure you have the original sdk of the library for reference in the makefile):

我的 makefiles(确保你有库的原始 sdk 以供在 makefile 中参考):

Android.mk:

安卓.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include /home/ng/Desktop/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk

LOCAL_SRC_FILES  := DetectionBasedTracker_jni.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS     += -llog -ldl

LOCAL_MODULE     := detection_based_tracker

include $(BUILD_SHARED_LIBRARY)

Application.mk:

应用程序.mk:

    APP_STL := gnustl_static
    APP_CPPFLAGS := -frtti -fexceptions
    APP_ABI := armeabi-v7a armeabi
    APP_PLATFORM := android-19

My gradle.build file in the app module:

我在 app 模块中的 gradle.build 文件:

apply plugin: 'com.android.application'
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "org.opencv.samples.facedetect"
        minSdkVersion 14
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    sourceSets.main.jni.srcDirs = []

    task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
       // ndkDir = project.plugins.findPlugin('com.android.application').getNdkFolder()
        commandLine "$ndkDir/ndk-build",
                'NDK_PROJECT_PATH=build/intermediates/ndk',
                'NDK_LIBS_OUT=src/main/jniLibs',
                'APP_BUILD_SCRIPT=src/main/jni/Android.mk',
                'NDK_APPLICATION_MK=src/main/jni/Application.mk'
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }

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

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.0'
    compile project(':openCVLibrary300')
}

You don't actually have to change other gradle files for compiling the native part of the project. You could also compile the native sources codes by command line and put the .so files back to the jniLibs folder. This also works. I hope this could help in your problem.

您实际上不必更改其他 gradle 文件来编译项目的本机部分。您还可以通过命令行编译本机源代码并将 .so 文件放回 jniLibs 文件夹。这也有效。我希望这可以帮助您解决问题。