android - 如何在 Flutter 插件中添加 OpenCV

标签 android opencv gradle flutter flutter-dependencies

我正在做一个 flutter 项目,我必须检测物体的边缘。我已经搜索了现有的插件,但找不到任何插件。我打算使用 OpenCV 进行边缘检测。

我从 Android Studio 创建了一个 flutter 插件。这是插件结构。

enter image description here

我已经从这里下载了适用于 Android 的 OpenCV - opencv-3.4.3-android-sdk并提取出来。

enter image description here

我已将 OpenCV SDK 中的 java 文件夹作为模块导入到 Flutter 插件的 Android 项目中。

这就是我的 android 项目(flutter 插件)build.gradle 的样子

group 'com.xxxx.xxxxx'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.2.30'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.2'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

rootProject.allprojects {
    repositories {
        google()
        jcenter()
    }
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 27

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
    defaultConfig {
        minSdkVersion 16
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    lintOptions {
        disable 'InvalidPackage'
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'

    implementation project(':openCVLibrary343')
    compileOnly files('templibs/flutter.jar')
}

这就是我的 opencv build.gradle 的样子

apply plugin: 'com.android.library'

android {
    compileSdkVersion 27
    buildToolsVersion "28.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 21
    }

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

这就是 Android 项目(flutter 插件)的 settings.gradle 的样子

rootProject.name = 'flutter_plugin'
include ':openCVLibrary343'

当我尝试运行由 flutter 插件模板创建的示例应用程序时,我遇到了以下错误。

在 Debug模式下在 Nexus 6P 上启动 lib\main.dart... 正在初始化梯度... 解决依赖关系... * 运行 Gradle 时出错: 退出代码 1 来自:C:\Users\xxxxx\Documents\flutter_plugin\example\android\gradlew.bat app:properties:

FAILURE:构建失败并出现异常。

  • 在哪里: 构建文件 'C:\Users\xxxx\Documents\flutter_plugin\android\build.gradle' 行:48

  • 出了什么问题: 评估项目 ':flutter_plugin' 时出现问题。

    Project with path ':openCVLibrary343' could not be found in project ':flutter_plugin'.

  • 试试: 使用 --stacktrace 选项运行以获取堆栈跟踪。使用 --info 或 --debug 选项运行以获得更多日志输出。运行 --scan 以获得完整的见解。

  • https://help.gradle.org 获得更多帮助

1 秒内构建失败

以错误结束:请检查 android/文件夹中的 Gradle 项目设置。

最佳答案

对于我正在进行的一个项目,我设法创建了一个 flutter 插件,它依赖于 OpenCV 来处理来自相机的图像。请注意,当我说“来自相机”时,我指的不是来自视频捕获的实时帧,而是之前保存在设备内存中的图片。

首先,我遵循了有关创建 plugins here 的 Flutter 文档。

当flutter创建插件文件夹和文件时,我最终得到了一个类似这样的结构(第一级的“opencv”文件夹是插件的根目录): Folder structure

注意我添加的 opencv-341.jar 文件,其中包含控制 native 库的 Java 方法,OpenCVPlugin.javaopencv.dart 是从 Flutter 访问 Java 方法的入口点,是从 Flutter 创建的。

.java 和 .dart 文件的文件名可能不同,这反射(reflect)了您在上述插件创建阶段作为参数传递的名称。

.jar 文件可以在 OpenCV 包中作为预编译库找到。在同一个包中,您会在这个小伪装的末尾找到所需的 native 库。

[plugin_root]/android 中的 build.gradle 文件应该像这样引用 jar 文件

dependencies {
    implementation files('opencv/opencv-341.jar')
}

OpencvPlugin.java 应该承载从 dart 调用的方法。就我而言,为了更好地管理不同的方法,我创建了这样的代码:

if (call.method.equals("processReceiptImage")) {
    if (!call.hasArgument("input")) {
        result.error("NOTFOUND", "File not found", null);
        return;
    }
    try {
        String input = call.argument("input");
        int maxWidth = (int) call.argument("maxWidth");
        int quality = (int) call.argument("quality");
        String output = call.argument("output");
        result.success(ProcessReceiptImage.run(input, maxWidth, quality, output));
        return;
    } catch (Exception e) {
        e.printStackTrace();
        result.error("UNKNOWN", e.getMessage(), null);
        return;
    }
}

静态方法ProcessReceiptImage包含在相关文件ProcessReceiptImage.java中:

package com.yourplugin.opencv;

import org.opencv.core.Mat;
import org.opencv.core.MatOfInt;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;


public class ProcessReceiptImage {
    static String run(String input, int maxWidth, int quality, String output) throws Exception {
        Mat src = Imgcodecs.imread(input, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
        Size size = src.size();

        int height = (int) (maxWidth * size.height / size.width);
        Imgproc.resize(src, src, new Size(maxWidth, height));

        ArrayList<Integer> parameters;
        parameters = new ArrayList();

        parameters.add(Imgcodecs.CV_IMWRITE_JPEG_QUALITY);
        parameters.add(quality);

        MatOfInt par = new MatOfInt();
        par.fromList(parameters);
        Imgcodecs.imwrite(output, src, par);
        return output;
    }
}

从现在开始,如果您运行您的应用程序,它可能会由于缺少库 opencv_java3 而失败。 为了解决这部分,我现在创建的唯一方法是将原生库复制到您的最终项目中(这是您的应用程序的根目录,而不是插件):

enter image description here

我已经为每个我想要定位的平台包含了最终的 .so native 库,因此无论用户使用什么平台,代码始终可以获取正确的 .so 并正确加载 OpenCV。

提示:由于包含所有 .so 文件会导致 APK 很大,我建议您配置 build.gradle 以便将包拆分为 abis,这样您将拥有一个较小的 apk,它将自动通过Play 商店。

关于android - 如何在 Flutter 插件中添加 OpenCV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53099700/

相关文章:

安卓gradle : Error No resource found that matches the given name: attr when refer to an android lib

java - 找不到 gradlew 命令?

java - 如何将json对象日期解析为Android

python - opencv warpPerspective参数计数

python - opencv中createBackgroundSubtractorMOG2函数的行为

c++ - OpenCV 树莓派 printf() 不显示

java - 从 Google 日历中提取事件

Android 在应用程序中加载和播放声音的最快方式

java - JNI "jobject thiz"与jboolean参数关系

gradle - 无法将String变量添加到 list 中