簡體   English   中英

擁有多個支持 OpenCV 的 JNI 庫

[英]Having multiple JNI libraries with OpenCV support

我有一個在 JNI 中使用 OpenCV 的項目,當它只有一個.cpp/ .h 文件時,它可以按預期編譯和工作,沒有任何問題。 然后我添加另一個.cpp/ .h 以在另一個活動中使用,並將其鏈接到 CMakeLists.txt 中。 如果這個新的 cpp 文件內部沒有任何 OpenCV 調用,那么一切仍然正常。 第一個活動可以按預期調用其 OpenCV 函數,第二個活動可以調用其相應 cpp 文件中定義的標准 JNI 函數。 但是,如果我嘗試使用任何 OpenCV,即使只是第二個 cpp 文件中的一個簡單Mat ,該項目甚至都無法編譯,並出現以下錯誤:

D:/programming/tree-project/treedetect/app/src/main/cpp/processing.cpp:21: error: undefined reference to 'cv::Mat::Mat(int, int, int)'
D:/programming/tree-project/treedetect/app/src/main/cpp/processing.cpp:24: error: undefined reference to 'cv::Mat::~Mat()'

到目前為止,我發現的每個問題和答案都處理單個 cpp 文件並使其工作。 我不想把不同活動的所有代碼都放在一個 cpp 中,讓它長 3k 行,但我不能讓多個庫一起工作。 如何在多個 JNI 庫中使用 OpenCV? 由於單個庫有效,我的猜測是鏈接和 cmake 配置有問題。

對於代碼詳細信息, detection庫始終按預期編譯和工作。 如果processing庫包含任何 OpenCV 代碼,則不會編譯。 一些重要文件如下所示:

CMakeLists.txt

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)




# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

include_directories(${OpenCV_DIR}/jni/include)
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${OpenCV_DIR}/libs/${ANDROID_ABI}/libopencv_java4.so)

# Declares and names the project.

project("detection")
project("processing")

add_library( # Sets the name of the library.
             detection

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             detection.cpp )

add_library( # Sets the name of the library.
        processing

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        processing.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.


                       detection

                       processing


        lib_opencv
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

設置.gradle

rootProject.name = 'TFLite Object Detection Demo App'
include ':app', ':lib_interpreter', ':lib_task_api'
include ':opencv'
project(':opencv').projectDir = new File(openCVSDK+'/sdk')

gradle.properties

org.gradle.jvmargs=-Xmx1536m
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true
# OpenCV
openCVSDK=D\:\\libraries\\OpenCV-android-sdk\\4.5.2

構建.gradle(應用程序)

apply plugin: 'com.android.application'
apply plugin: 'de.undercouch.download'

android {
    compileSdkVersion 30
    buildToolsVersion '30.0.3'
    defaultConfig {
        applicationId "org.tensorflow.lite.examples.detection"
        minSdkVersion 24
        targetSdkVersion 30
        versionCode 5
        versionName "1.0.1111"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
                abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
                arguments "-DOpenCV_DIR=" + openCVSDK + "/sdk/native"
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    buildFeatures {
        dataBinding = true
    }
    aaptOptions {
        noCompress "tflite"
    }
    compileOptions {
        sourceCompatibility = '1.8'
        targetCompatibility = '1.8'
    }
    lintOptions {
        abortOnError false
    }
    flavorDimensions "tfliteInference"
    productFlavors {
       // The TFLite inference is built using the TFLite Java interpreter.
       interpreter {
           dimension "tfliteInference"
       }
       // Default: The TFLite inference is built using the TFLite Task library (high-level API).
       taskApi {
           getIsDefault().set(true)
           dimension "tfliteInference"
       }
    }
    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.10.2'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
    implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
    interpreterImplementation project(":lib_interpreter")
    taskApiImplementation project(":lib_task_api")
    // OpenCV
    implementation project(path: ':opencv')
    implementation 'androidx.appcompat:appcompat:1.3.1'
    implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0'
    implementation 'com.google.android.material:material:1.4.0'
    // view model
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
    implementation 'com.github.felHR85:UsbSerial:6.1.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'com.google.truth:truth:1.0.1'
    androidTestImplementation 'androidx.test:runner:1.4.0'
    androidTestImplementation 'androidx.test:rules:1.4.0'
}

processing.cpp(一個不起作用的)

#include <jni.h>
#include <android/log.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <numeric>



using cv::Mat;


extern "C"
JNIEXPORT jint JNICALL
Java_org_tensorflow_lite_examples_detection_ImageProcessingViewModel_valueFromJNI(JNIEnv *env,
                                                                                  jobject thiz) {
    // This does not work
    Mat dummy(400, 800, CV_8UC1);
    return dummy.rows;
    // this does work
    return 42;
}

構建變體

變體

錯誤

Build command failed.
Error while executing process C:\Users\tpalh\AppData\Local\Android\Sdk\cmake\3.10.2.4988404\bin\ninja.exe with arguments {-C D:\programming\tree-project\treedetect\app\.cxx\Debug\54133v1z\armeabi-v7a detection processing}
ninja: Entering directory `D:\programming\tree-project\treedetect\app\.cxx\Debug\54133v1z\armeabi-v7a'
[1/2] Linking CXX shared library D:\programming\tree-project\treedetect\app\build\intermediates\cxx\Debug\54133v1z\obj\armeabi-v7a\libprocessing.so
FAILED: D:/programming/tree-project/treedetect/app/build/intermediates/cxx/Debug/54133v1z/obj/armeabi-v7a/libprocessing.so 
cmd.exe /C "cd . && C:\Users\tpalh\AppData\Local\Android\Sdk\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi24 --gcc-toolchain=C:/Users/tpalh/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/tpalh/AppData/Local/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security  -frtti -fexceptions -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libprocessing.so -o D:\programming\tree-project\treedetect\app\build\intermediates\cxx\Debug\54133v1z\obj\armeabi-v7a\libprocessing.so CMakeFiles/processing.dir/processing.cpp.o  -latomic -lm && cd ."
D:/programming/tree-project/treedetect/app/src/main/cpp/processing.cpp:21: error: undefined reference to 'cv::Mat::Mat(int, int, int)'
D:/programming/tree-project/treedetect/app/src/main/cpp/processing.cpp:24: error: undefined reference to 'cv::Mat::~Mat()'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

有趣的是,這個 cpp 文件實際上在 IDE 中識別了 OpenCV 庫: 樂趣

可能為時已晚,但如果其他人卡在這里,它看起來像一個cmake問題,op 只包括一個文件->

add_library( # Sets the name of the library.
             detection

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             detection.cpp <--- *ONLY ONE FILE INCLUDED*
 )

add_library( # Sets the name of the library.
        processing

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        processing.cpp <--- *ONLY ONE FILE INCLUDED*
 )

這可以通過使用GLOB_RECURSE或查找所有需要的文件來解決。

例如

# Automatically all files in a directory to a target
file (GLOB_RECURSE CHOPPER_SRCS CONFIGURE_DEPENDS
    "src/*.cpp"
    "src/*.h"
)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        chopper

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ${CHOPPER_SRCS}
)

資源

這是一個使用 OpenCV native for android 並且有多個 C++ 文件的項目的鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM