如何在Flutter的本机C ++中使用OpenCV 4? [英] How to use OpenCV 4 in native C++ of Flutter?

查看:123
本文介绍了如何在Flutter的本机C ++中使用OpenCV 4?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要编写一些使用 OpenCV 的C ++代码,Flutter代码将调用这些C ++代码。 / p>

教程关于用Flutter编写C ++,但是我找不到关于使用OpenCV的任何最新且易于部署的解决方案。

解决方案

这是我的解决方案。


功能



  1. 适用于Android和iOS。

  2. 使用静态链接代替动态链接。 (因此,代码大小要小得多。)

  3. 最新版本为 2020.09.02 (第一个版本为7.28)。 (由于这些API的变化很快,并且许多文章都有些过时。)


入门


注意:如果您已经有一个应用程序,则可以跳过本节:)本节假定您根本没有任何代码。


可以从此处


步骤0 :确保您拥有 Flutter环境,并且遵循了官方使用Flutter编写C ++教程


注意:必须遵循 步骤,在iOS上,您需要告诉Xcode静态链接文件:...。否则,在我们的最后一步,iOS将抱怨找不到该符号。


第1步:使用OpenCV编写所需的任何代码。例如,我将 ios / Classes / native_add.cpp 更改为以下愚蠢的代码,该代码与官方教程

  #include< stdint.h> 
#include< opencv2 / core.hpp>

extern C; __attribute __((visibility( default))))__attribute __((used))
int32_t native_add(int32_t x,int32_t y){
cv :: Mat m = cv :: Mat :: zeros( x,y,CV_8UC3);
返回m.rows + m.cols;
}


Android


步骤0 :下载 Android 来自官方网站的OpenCV sdk。假设我将其放在桌面的 / Users / tom / Others / OpenCVRelease / OpenCV-android-sdk 中。


步骤1.1 :将 android / CMakeLists.txt 更改为此要点注意:首先将 OPENCV_BASE_DIR 更改为您的文件夹。


当然, lib / native_with_opencv.dart 应该将 .so 文件名更改为 libnative_with_opencv.so


备注:如果您需要更多OpenCV功能(例如 imread ),请准备尝试使用此要点


步骤1.2 :更改 android / build.gradle 如下:

  android {
...
defaultConfig {
...
// // [[[CHANGE 1:使minSdkVersion变大]]]
//参见https:/ /github.com/opencv/opencv/issues/14419
minSdkVersion 21

// // [[[CHANGE 2:添加这些标志和过滤器]]]
externalNativeBuild {
cmake {
cppFlags" -frtti -fexceptions -s td = c ++ 11
abiFilters'armeabi-v7a','arm64-v8a'
}
}
...
}
...
}

当然,实际中的 minSdkVersion 项目( native_with_opencv / example / android / app / build.gradle )也应更改为21。


完成! / strong>编译并享受它(并转到iOS的下一部分)!如果看到 1 + 2 == 3 ,那么一切都很好。


奖金:如果您在发布模式下构建查看apk大小,您会看到我们的 .so 文件小于1MB。因此,静态链接和减小文件大小确实有效:)


iOS


步骤0 :在 ios / native_with_opencv.podspec ,添加:

  s.static_framework = true 
s.dependency'OpenCV ','〜> 4.1'

第1步:运行 pod install native_with_opencv / example / ios 下的$ c>。


步骤2 编译并享受!


注释0 :必须遵循在iOS上,您需要告诉Xcode静态链接文件的步骤:...在 tut 中。否则,在我们的最后一步,iOS将抱怨找不到该符号。


注释0b:可能需要检查(验证)XCode中的以下设置(似乎将某些文件拖到XCode中时自动包括在内,但不确定)。否则,您的最终ipa文件(可以由生成)将包含您的 .cpp 源文件除了已编译的代码外,因此源代码也被泄漏。


设置:转到构建阶段 赛跑者的目标。 (1)查看复制捆绑包资源,并验证您的 .cpp 文件或文件夹是否不在其中。 (2)查看编译源,并验证其中的 .cpp 文件 。 (您可能需要先在编译源文件中添加文件,然后再在复制捆绑资源中将其删除。)


备注1 :如果您正在使用其他 .hpp 头文件并且看到奇怪的错误,例如opencv应该使用C ++构建,或者在框架模块中包含非模块化头文件,则可以尝试以下操作:


创建 xxx.modulemap 文件,其中包含以下框架模块the_name_of_your_module {} 。然后更改您的podspec以使用此模块映射。 module_map ='xxx.modulemap'。然后再次运行 pod install 进行刷新。然后编译并运行,应该没问题。


我对这个问题的猜测是,Cocoapod会生成一个伞头。 (例如vision_utils-umbrella.h),标题就会自动包含在其中。因此,在编译该标头时,事情就坏了。因此,我上面的方法尝试删除该伞头。


注释2 :添加或删除某些c ++文件时,可能必须运行<$ c再次执行$ c> pod install (就像在步骤1中一样)。否则,您可能会看到诸如找不到符号之类的错误消息。 (因为xcode不会查看您新添加的C ++文件)。




(可选)Android配置如何工作的说明:(1)最初,我只是链接核心,但是有数百个链接错误。然后,我搜索并修复其中的每组。例如, error:对'carotene_o4t :: ...'的未定义引用表示我需要 libtegra_hal ,因此我添加了几行。 (2)奇怪的是,应该将 tbb 放在之后 core ,否则它仍然会没有链接。 (3)由于 tegra_hal 不支持 x86 abiFilters $ c>(因此不存在 .a 文件)。 (4)需要提高 minSdkVersion ,否则将找不到 fegettenv


I need to write some C++ code which uses OpenCV, and the Flutter code will call those C++ code.

There are tutorials about writing C++ with Flutter, but I cannot find any up-to-date and easy-to-deploy solution about working with OpenCV. How to do that?

解决方案

Here is my solution.

Features

  1. Works for both Android and iOS.
  2. Use static linking instead of dynamic linking. (Thus code size is much smaller.)
  3. Up-to-date at 2020.09.02 (first version at 7.28). (Since those APIs change rapidly and many articles are a little bit old.)

Getting Started

NOTE: If you already have an app, you can skip this section :) This section assumes that you have no code at all.

Sample code can be downloaded from here.

step 0: Ensure you have Flutter environment, and have followed the official "writing C++ with Flutter" tutorial.

NOTE: It is a must to follow the step of "On iOS, you need to tell Xcode to statically link the file: ...". Otherwise, at our last step iOS will complain the symbol cannot be found.

step 1: Write whatever code you like using OpenCV. For instance, I change ios/Classes/native_add.cpp to the following silly code, which is almost identical as in the official tutorial:

#include <stdint.h>
#include <opencv2/core.hpp>

extern "C" __attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t x, int32_t y) {
    cv::Mat m = cv::Mat::zeros(x, y, CV_8UC3);
    return m.rows + m.cols;
}

Android

Step 0: Download the Android OpenCV sdk from the official website. Say I put it in /Users/tom/Others/OpenCVRelease/OpenCV-android-sdk in my desktop.

Step 1.1: Change the android/CMakeLists.txt to the content of this gist. NOTE: First change the OPENCV_BASE_DIR to your folder.

Of course, the lib/native_with_opencv.dart should change the .so file name to "libnative_with_opencv.so".

Remark: If you need more OpenCV features (such as imread), have a try using this gist.

Step 1.2: Change the android/build.gradle as following:

android {
    ...
    defaultConfig {
        ...
        // [[[CHANGE 1: Make minSdkVersion bigger]]]
        // see https://github.com/opencv/opencv/issues/14419
        minSdkVersion 21

        // [[[CHANGE 2: Add these flags and filters]]]
        externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions -std=c++11"
                abiFilters 'armeabi-v7a', 'arm64-v8a'
            }
        }
        ...
    }
    ...
}

Of course, the minSdkVersion in your actual project (native_with_opencv/example/android/app/build.gradle) should also change to 21.

Done! Compile and enjoy it (and go to the next section for iOS)! If you see 1 + 2 == 3, then everything is fine.

Bonus: If you build in release mode and look at the apk size, you will see our .so file is less than 1MB. Thus static linking and file size reduction does work :)

iOS

Step 0: In ios/native_with_opencv.podspec, add:

  s.static_framework = true
  s.dependency 'OpenCV', '~> 4.1'

Step 1: Run pod install under native_with_opencv/example/ios.

Step 2: Compile and enjoy!

Remark 0: It is a must to follow the step of "On iOS, you need to tell Xcode to statically link the file: ..." in the tut. Otherwise, at our last step iOS will complain the symbol cannot be found.

Remark 0b: May need to check (verify) the following settings in XCode (which seems to be automatically included when dragging some files into XCode but not sure). Otherwise, your final ipa file (can be generated by this) will contain your .cpp source file besides compiled code, thus the source code is leaked.

The setting: Go to "Build Phase" of the "Runner" Target. (1) Look at "Copy Bundle Resources", and verify that your .cpp file or folders are not there. (2) Look at "Compile Sources", and verify your .cpp files are there. (You may need to first add your file in "Compile Sources" before removing it in "Copy Bundle Resources".)

Remark 1: If you are using other .hpp headers and see strange errors, such as opencv should be build with C++, or include of non-modular header inside framework module, then may try this:

Create xxx.modulemap file containing the following framework module the_name_of_your_module {}. Then change your podspec to use this modulemap s.module_map = 'xxx.modulemap'. Then run pod install again to refresh. Then compile and run and it should be OK.

My guess about this problem is that, Cocoapod generates a "umbrella header" (say vision_utils-umbrella.h), and your header is automatically included there. Thus, when compiling that header, things get broken. Thus, my method above tries to remove this umbrella header.

Remark 2: When you add or remove some c++ files, you may have to run pod install again (just like in step 1). Otherwise, you may see errors like "cannot find the symbol" (because xcode do not look at your newly added C++ file).


(Optional) Explanations of how does the Android configuration work: (1) Originally, I just link the core, but there are hundreds of linking errors. Then I search and fix for each group of them. For instance, error: undefined reference to 'carotene_o4t::...' means I need to link with libtegra_hal, thus I add several lines. (2) Strangely, the tbb should be put after core, otherwise it still does not link. (3) The abiFilters is needed, since tegra_hal does not support x86 (thus no .a file exists). (4) minSdkVersion needs to be raised up, otherwise fegetenv will not be found.

这篇关于如何在Flutter的本机C ++中使用OpenCV 4?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆