Flutter图像处理插件opencv_dart的使用
Flutter图像处理插件opencv_dart的使用
opencv_dart简介
opencv_dart是用于Flutter的OpenCV库,它包含了所有的OpenCV模块。如果你不需要videoio和highgui模块,可以考虑使用opencv_core。
注意事项
从版本v1.3.0开始,动态库将在本地构建,并在构建期间由Flutter调用。请注意:OpenCV SDK(约100M)将通过CMake的FetchContent下载,你可以设置DARTCV_CACHE_DIR环境变量来缓存它以避免重复下载。例如:export DARTCV_CACHE_DIR=$HOME/.cache/dartcv
- Q&A: #212 或者打开新问题。
- 如果你正在使用支持原生资源的Flutter特性,请考虑使用v2.x版本,详见native-assets分支,但此分支不会更新直到Native Assets稳定。
支持的平台
| 平台 | 是否支持 | 测试状态 | 架构 | 
|---|---|---|---|
| Android | ✅ | ✅ | x86_64, arm64-v8a, armeabi-v7a | 
| iOS | ✅ | ✅ | arm64, x64(Simulator) | 
| Linux | ✅ | ✅ | x64, arm64 | 
| Windows | ✅ | ✅ | x64, arm64 | 
| macOS | ✅ | ✅ | x64, arm64 | 
支持的模块
具体支持的模块列表请参阅这里
包大小
示例代码
下面是一个完整的示例demo,展示了如何使用opencv_dart进行图像处理:
// ignore_for_file: avoid_print
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:opencv_dart/opencv.dart' as cv;
void main() {
  runApp(const MyApp());
}
class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
  List<Uint8List> images = [];
  Future<(cv.Mat, cv.Mat)> heavyTaskAsync(cv.Mat im, {int count = 1000}) async {
    late cv.Mat gray, blur;
    for (var i = 0; i < count; i++) {
      gray = await cv.cvtColorAsync(im, cv.COLOR_BGR2GRAY);
      blur = await cv.gaussianBlurAsync(im, (7, 7), 2, sigmaY: 2);
      if (i != count - 1) {
        gray.dispose(); // 手动释放
        blur.dispose(); // 手动释放
      }
    }
    return (gray, blur);
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('OpenCV Dart Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton(
                onPressed: () async {
                  final picker = ImagePicker();
                  final img = await picker.pickImage(source: ImageSource.gallery);
                  if (img != null) {
                    final path = img.path;
                    final mat = cv.imread(path);
                    print("cv.imread: width: ${mat.cols}, height: ${mat.rows}, path: $path");
                    debugPrint("mat.data.length: ${mat.data.length}");
                    // 重计算任务
                    final (gray, blur) = await heavyTaskAsync(mat, count: 1);
                    setState(() {
                      images = [
                        cv.imencode(".png", mat).$2,
                        cv.imencode(".png", gray).$2,
                        cv.imencode(".png", blur).$2,
                      ];
                    });
                  }
                },
                child: const Text("Pick Image"),
              ),
              ElevatedButton(
                onPressed: () async {
                  final data = await DefaultAssetBundle.of(context).load("images/lenna.png");
                  final bytes = data.buffer.asUint8List();
                  // 重计算任务
                  final (gray, blur) = await heavyTaskAsync(cv.imdecode(bytes, cv.IMREAD_COLOR));
                  setState(() {
                    images = [bytes, cv.imencode(".png", gray).$2, cv.imencode(".png", blur).$2];
                  });
                },
                child: const Text("Process"),
              ),
              Expanded(
                flex: 2,
                child: Row(
                  children: [
                    Expanded(
                      child: ListView.builder(
                        itemCount: images.length,
                        itemBuilder: (ctx, idx) => Card(
                          child: Image.memory(images[idx]),
                        ),
                      ),
                    ),
                    Expanded(
                      child: SingleChildScrollView(
                        child: Text(cv.getBuildInformation()),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
说明
- heavyTaskAsync:该函数执行了颜色转换和高斯模糊操作,并返回灰度图和模糊后的图像。
- Pick Image按钮:允许用户从图库中选择图片,并对其进行颜色转换和高斯模糊处理,最后显示原始图像、灰度图像和模糊图像。
- Process按钮:加载内置的lenna.png图像并对其进行相同的处理。
更多示例可以参考官方示例或awesome-opencv_dart。
许可证
opencv_dart遵循Apache-2.0 License。
希望这些信息对你有帮助!如果你有任何问题或需要进一步的帮助,请随时提问。
更多关于Flutter图像处理插件opencv_dart的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图像处理插件opencv_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,使用opencv_dart插件进行图像处理是一个强大的方法,因为OpenCV是一个广泛使用的计算机视觉库。虽然opencv_dart主要是为Dart环境设计的,但你可以通过一些桥接技术在Flutter项目中使用它。下面是一个基本的示例,展示如何在Flutter中使用opencv_dart进行图像处理。
首先,你需要在你的pubspec.yaml文件中添加对opencv_dart的依赖。然而,需要注意的是,opencv_dart可能不是直接在Flutter插件库中可用的,因此你可能需要手动集成OpenCV的Dart绑定或者使用其他Flutter兼容的OpenCV封装。这里假设你已经有了相应的绑定或封装。
dependencies:
  flutter:
    sdk: flutter
  opencv_dart: ^版本号  # 请注意,这里的版本号需要替换为实际可用的版本号
由于opencv_dart可能不是官方支持的Flutter插件,接下来的步骤可能涉及一些原生代码集成或者使用现有的Flutter兼容库(如flutter_opencv,如果存在的话)。以下是一个假设性的示例,展示如何在Flutter中调用OpenCV的功能。
假设性示例:在Flutter中使用OpenCV进行灰度转换
- 
确保OpenCV Dart绑定已正确集成: 这一步可能涉及下载OpenCV的Dart绑定库,并将其包含在你的Flutter项目中。由于这不是一个标准的Flutter插件,你可能需要手动处理一些原生代码和构建配置。 
- 
创建一个Dart文件来处理OpenCV操作: import 'package:opencv_dart/opencv_dart.dart'; class ImageProcessor { Mat convertToGrayscale(Uint8List imageBytes, int width, int height) { // 创建一个Mat对象从图像字节数据 Mat src = Mat.fromBytes(width, height, Mat.CV_8UC4, imageBytes); // 转换到灰度图像 Mat dst = Mat(); cv.cvtColor(src, dst, cv.COLOR_BGR2GRAY); return dst; } }
- 
在Flutter Widget中使用这个处理器: import 'package:flutter/material.dart'; import 'dart:typed_data'; import 'image_processor.dart'; // 假设你的ImageProcessor类在这里 void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('OpenCV in Flutter'), ), body: Center( child: ImageFromOpenCV(), ), ), ); } } class ImageFromOpenCV extends StatefulWidget { @override _ImageFromOpenCVState createState() => _ImageFromOpenCVState(); } class _ImageFromOpenCVState extends State<ImageFromOpenCV> { Uint8List? grayscaleImageBytes; @override void initState() { super.initState(); loadAndProcessImage(); } void loadAndProcessImage() async { // 这里你应该加载你的图像数据,例如从资产文件夹或网络 // 这里为了简化,我们假设已经有了一个图像字节数组 Uint8List imageBytes = ...; // 你的图像字节数据 int width = ...; // 图像宽度 int height = ...; // 图像高度 ImageProcessor processor = ImageProcessor(); Mat grayscaleMat = processor.convertToGrayscale(imageBytes, width, height); // 将Mat对象转换回字节数据(这里需要一些额外的处理,因为Mat对象不是直接可序列化的) // 注意:这里的转换代码可能需要根据你使用的OpenCV Dart绑定的具体实现来调整 Uint8ListBuffer buffer = Uint8ListBuffer(); grayscaleMat.writeTo(buffer); grayscaleImageBytes = buffer.asUint8List(); // 更新UI setState(() {}); } @override Widget build(BuildContext context) { return grayscaleImageBytes != null ? Image.memory(grayscaleImageBytes!) : CircularProgressIndicator(); } }
注意:上面的代码示例包含了一些假设和简化的部分,特别是关于如何加载图像数据和如何将Mat对象转换回字节数据的部分。在实际应用中,你可能需要使用更复杂的逻辑来处理这些任务,特别是如果你正在处理从相机或网络加载的图像。
此外,由于opencv_dart可能不是直接在Flutter生态系统中广泛使用的库,因此你可能需要查找或创建与Flutter兼容的OpenCV绑定。如果这样的绑定不存在,你可能需要考虑使用平台通道(Platform Channels)来在Flutter和原生代码之间通信,从而在原生侧使用OpenCV。
 
        
       
             
             
            

