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

问题描述

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

关于使用Flutter编写C ++的教程找不到有关使用OpenCV的任何最新且易于部署的解决方案.该怎么做?

解决方案

这是我的解决方案.

功能

  1. 适用于Android和iOS.
  2. 使用静态链接而不是动态链接.(因此,代码大小要小得多.)
  3. 使用OpenCV 4.5.1(第一个版本为2020.7.28)在 2021.3.7 上进行了最新更新,并在Flutter 1.x和2.0上进行了测试.(由于这些API的变化很快,而且许多文章都有些陈旧.)

入门

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

可以从此处下载示例代码.

第0步:确保您具有 Flutter环境,并遵循官方使用Flutter编写C ++"教程.

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

注意:此外,您还需要更改条形样式"如此处所述.否则,您会在iOS 版本中看到问题构建,而在调试构建中,一切正常.

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

  #include< stdint.h>#include< opencv2/core.hpp>外部"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步:下载官方网站下载"rel =" nofollow noreferrer> 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/14419minSdkVersion 21//[[[CHANGE 2:添加这些标志和过滤器]]]externalNativeBuild {cmake {cppFlags"-frtti -fexceptions -std = c ++ 11"abiFilters'armeabi-v7a','arm64-v8a'}}...}...} 

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

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

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

iOS

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

  s.static_framework = trues.dependency'OpenCV','〜>4.5英尺 

第1步:在 native_with_opencv/example/ios 下运行 pod install .

第2步:编译并享受!

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

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

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

注释1 :如果您使用其他 .hpp 标头,并且发现奇怪的错误,例如OpenCV应该使用C ++构建,或者包含非模块化标头在框架模块内部,则可以尝试以下方法:

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

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

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

注释3 :如果遇到诸如无法查找符号(dlsym(RTLD_DEFAULT,your_function):未找到符号)之类的问题,请查看链接.我似乎可以通过应用该评论中的建议来解决此问题(但不能确定,因为还尝试了其他方法).如果仍然无法解决,请回复我.


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

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 2021.3.7 working with OpenCV 4.5.1 (first version at 2020.7.28) and tested on both Flutter 1.x and 2.0. (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.

The 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.

NOTE: Also, you need to change the "strip style" as mentioned here for iOS. Otherwise, you will see problems in iOS release build while in debug build everything works.

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.5'

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 built with C++, or include of a 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 an "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 does not look at your newly added C++ file).

Remark 3: If you see problems like Failed to lookup symbol (dlsym(RTLD_DEFAULT, your_function): symbol not found), have a look at this link. I seem to solve it by applying what is suggested in that comment (but not sure since also have tried other ways). If still not solved please reply to me.


(Optional) Explanations of how do 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(在2021年)(支持Flutter 2.0)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 15:37