Flutter图像处理插件opencv_4的使用
Flutter图像处理插件opencv_4的使用
opencv_4
是一个用于Flutter应用的插件,它集成了OpenCV 4.3.0版本的功能,支持Android和iOS平台。本文将介绍如何安装和使用该插件,并提供一些示例代码。
目录
关于此版本
兼容性
- 集成OpenCV 4.3.0版本
- 支持Android和iOS平台
- 可与流行的Flutter包如
image_picker
配合使用,以从图库或相机中获取图像进行处理
图像处理
- 所有处理都通过图像字符串路径进行
- 图像可以来自Flutter项目的assets文件夹、URL或者使用
image_picker
获取的相机和图库中的图片
安装
1. 依赖它
在你的 pubspec.yaml
文件中添加以下内容:
dependencies:
opencv_4: ^1.0.0
2. 安装它
你可以通过命令行安装包:
$ flutter pub get
3. 导入它
现在你可以在Dart代码中导入并使用:
import 'package:opencv_4/opencv_4.dart';
如何使用
前提条件
-
Android: 需要在项目中的
android/app/build.gradle
文件中设置最低版本为21:defaultConfig { ... minSdkVersion 21 ... }
-
如果要处理来自assets文件夹的图像,不需要额外配置。
-
如果要处理来自URL的图像,也不需要额外配置。
-
如果要使用
image_picker
处理来自相机和图库的图像,请按照其文档进行权限配置。 -
Nullsafety: 如果你要测试示例代码,请确保在
pubspec.yaml
中设置了以下环境变量:environment: sdk: ">=2.12.0 <3.0.0"
类
Cv2
: 包含OpenCV模块实现的类CVPathFrom
: 允许配置要处理的图像路径URL
: 配置OpenCV用于Web图像GALLERY_CAMERA
: 配置OpenCV用于从image_picker
包获取的图像ASSETS
: 配置OpenCV用于flutter项目中配置的assets图像
模块:图像过滤
Bilateral Filter (双边滤波)
必须在异步函数中调用:
Uint8List _byte = await Cv2.bilateralFilter(
pathFrom: CVPathFrom.ASSETS,
pathString: 'assets/Test.JPG',
diameter: 20,
sigmaColor: 75,
sigmaSpace: 75,
borderType: Cv2.BORDER_DEFAULT,
);
setState(() {
_byte;
});
显示结果在一个Image widget中:
Image.memory(
_byte!,
width: 300,
height: 300,
fit: BoxFit.fill,
)
如果你要处理网络上的图像,只需将 pathFrom
设置为 CVPathFrom.URL
并替换 pathString
为URL即可。
Dilate (膨胀)
Uint8List _byte = await Cv2.dilate(
pathFrom: CVPathFrom.ASSETS,
pathString: 'assets/Test.JPG',
kernelSize: [3, 3],
);
setState(() {
_byte;
});
Filter2D (二维卷积)
Uint8List _byte = await Cv2.filter2D(
pathFrom: CVPathFrom.URL,
pathString: 'https://example.com/image.jpg',
outputDepth: -1,
kernelSize: [2, 2],
);
setState(() {
_byte;
});
Median Blur (中值模糊)
Uint8List _byte = await Cv2.medianBlur(
pathFrom: CVPathFrom.URL,
pathString: 'https://example.com/image.jpg',
kernelSize: 19,
);
setState(() {
_byte;
});
MorphologyEx (形态学操作)
Uint8List _byte = await Cv2.morphologyEx(
pathFrom: CVPathFrom.URL,
pathString: 'https://example.com/image.jpg',
operation: Cv2.MORPH_TOPHAT,
kernelSize: [5, 5],
);
setState(() {
_byte;
});
PyrMeanShiftFiltering (金字塔均值偏移滤波)
Uint8List _byte = await Cv2.pyrMeanShiftFiltering(
pathFrom: CVPathFrom.ASSETS,
pathString: 'assets/Test.JPG',
spatialWindowRadius: 20,
colorWindowRadius: 20,
);
setState(() {
_byte;
});
Scharr (Scharr算子)
Uint8List _byte = await Cv2.scharr(
pathFrom: CVPathFrom.ASSETS,
pathString: 'assets/Test.JPG',
depth: Cv2.CV_SCHARR,
dx: 0,
dy: 1,
);
setState(() {
_byte;
});
示例Demo
下面是一个完整的Flutter应用程序示例,展示了如何使用 opencv_4
插件来处理图像:
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:opencv_4/factory/pathfrom.dart';
import 'package:opencv_4/opencv_4.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'OpenCV Example'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, this.title}) : super(key: key);
final String? title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Uint8List? _byte;
bool _visible = false;
final picker = ImagePicker();
Future<void> _getOpenCVVersion() async {
String? versionOpenCV = await Cv2.version();
setState(() {
print('OpenCV Version: $versionOpenCV');
});
}
void testThreshold({
required String pathString,
required CVPathFrom pathFrom,
required double thresholdValue,
required double maxThresholdValue,
required int thresholdType,
}) async {
try {
_byte = await Cv2.threshold(
pathFrom: pathFrom,
pathString: pathString,
maxThresholdValue: maxThresholdValue,
thresholdType: thresholdType,
thresholdValue: thresholdValue,
);
setState(() {
_byte;
_visible = false;
});
} on PlatformException catch (e) {
print(e.message);
}
}
void _testFromAssets() async {
testThreshold(
pathFrom: CVPathFrom.ASSETS,
pathString: 'assets/Test.JPG',
thresholdValue: 150,
maxThresholdValue: 200,
thresholdType: Cv2.THRESH_BINARY,
);
setState(() {
_visible = true;
});
}
void _testFromUrl() async {
testThreshold(
pathFrom: CVPathFrom.URL,
pathString: 'https://example.com/image.jpg',
thresholdValue: 150,
maxThresholdValue: 200,
thresholdType: Cv2.THRESH_BINARY,
);
setState(() {
_visible = true;
});
}
void _testFromCamera() async {
final pickedFile = await picker.getImage(source: ImageSource.camera);
if (pickedFile != null) {
testThreshold(
pathFrom: CVPathFrom.GALLERY_CAMERA,
pathString: pickedFile.path,
thresholdValue: 150,
maxThresholdValue: 200,
thresholdType: Cv2.THRESH_BINARY,
);
setState(() {
_visible = true;
});
}
}
void _testFromGallery() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
if (pickedFile != null) {
testThreshold(
pathFrom: CVPathFrom.GALLERY_CAMERA,
pathString: pickedFile.path,
thresholdValue: 150,
maxThresholdValue: 200,
thresholdType: Cv2.THRESH_BINARY,
);
setState(() {
_visible = true;
});
}
}
@override
void initState() {
super.initState();
_getOpenCVVersion();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title!),
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: [
Container(
margin: EdgeInsets.only(top: 20),
child: Center(
child: Column(
children: <Widget>[
Text(
'OpenCV Example',
style: TextStyle(fontSize: 23),
),
Container(
margin: EdgeInsets.only(top: 5),
child: _byte != null
? Image.memory(
_byte!,
width: 300,
height: 300,
fit: BoxFit.fill,
)
: Container(
width: 300,
height: 300,
child: Icon(
Icons.camera_alt,
color: Colors.grey[800],
),
),
),
Visibility(
maintainAnimation: true,
maintainState: true,
visible: _visible,
child: Container(child: CircularProgressIndicator()),
),
SizedBox(
width: MediaQuery.of(context).size.width - 40,
child: TextButton(
child: Text('Test Assets'),
onPressed: _testFromAssets,
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.teal,
onSurface: Colors.grey,
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width - 40,
child: TextButton(
child: Text('Test URL'),
onPressed: _testFromUrl,
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.teal,
onSurface: Colors.grey,
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width - 40,
child: TextButton(
child: Text('Test Gallery'),
onPressed: _testFromGallery,
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.teal,
onSurface: Colors.grey,
),
),
),
SizedBox(
width: MediaQuery.of(context).size.width - 40,
child: TextButton(
child: Text('Test Camera'),
onPressed: _testFromCamera,
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.teal,
onSurface: Colors.grey,
),
),
),
],
),
),
),
],
),
),
),
);
}
}
以上就是使用 opencv_4
插件的基本步骤和示例代码。希望对你有所帮助!
更多关于Flutter图像处理插件opencv_4的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图像处理插件opencv_4的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用opencv_4
插件进行基本图像处理的示例代码。请注意,opencv_4
插件可能并不是官方或广泛认可的插件名称,因此这里假设你指的是一个允许Flutter使用OpenCV 4.x功能的插件。在Flutter社区中,通常通过调用原生代码(如C++或Java/Kotlin)来实现OpenCV的功能。
由于Flutter本身不直接支持C++库,我们通常需要通过平台通道(Platform Channels)与原生代码进行交互。以下示例将展示如何在Flutter中设置一个基本的平台通道,并在原生代码中调用OpenCV的功能。
1. 设置Flutter项目
首先,创建一个新的Flutter项目(如果还没有的话):
flutter create flutter_opencv_example
cd flutter_opencv_example
2. 添加平台通道
在lib
目录下创建或修改main.dart
文件,添加一个平台通道来与原生代码通信:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
static const platform = const MethodChannel('com.example.flutter_opencv_example/opencv');
Future<void> _processImage(File imageFile) async {
try {
final result = await platform.invokeMethod('processImage', imageFile.path);
print('Processed image result: $result');
} on PlatformException catch (e) {
print("Failed to process image: '${e.message}'.");
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter OpenCV Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () async {
// Here you would typically pick an image from the gallery or take a photo with the camera
// For simplicity, we assume you already have a File object called `imageFile`
// File imageFile = ...;
// _processImage(imageFile);
},
child: Text('Process Image'),
),
),
),
);
}
}
3. 在Android端实现OpenCV功能
在android/app/src/main/java/com/example/flutter_opencv_example/
目录下创建或修改MainActivity.kt
(如果是Kotlin项目)或MainActivity.java
(如果是Java项目),并添加平台通道的实现。这里以Kotlin为例:
package com.example.flutter_opencv_example
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import org.opencv.android.OpenCVLoader
import org.opencv.android.Utils
import org.opencv.core.Mat
import org.opencv.imgproc.Imgproc
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.flutter_opencv_example/opencv"
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "processImage") {
val imagePath = call.argument<String>("imagePath") ?: return@setMethodCallHandler result.error("INVALID_ARGUMENT", "imagePath is missing", null)
processImage(imagePath, result)
} else {
result.notImplemented()
}
}
}
private fun processImage(imagePath: String, result: MethodChannel.Result) {
if (!OpenCVLoader.initDebug()) {
result.error("OPENCV_LOAD_FAILED", "OpenCV library loading failed", null)
return
}
val bitmap = // Load bitmap from imagePath (you can use standard Android code for this)
val mat = Mat()
Utils.bitmapToMat(bitmap, mat)
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY) // Example: convert to grayscale
val processedBitmap = Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888)
Utils.matToBitmap(mat, processedBitmap)
// Save or return the processed bitmap as needed
// For simplicity, we'll just return a success message here
result.success("Image processed successfully")
}
}
注意:上面的代码中省略了从文件路径加载Bitmap
的部分,因为这部分代码依赖于Android的标准图像处理库,并且相对简单。你可以使用BitmapFactory.decodeFile(imagePath)
来加载图像。
4. 在iOS端实现OpenCV功能(可选)
由于iOS平台的复杂性,这里不详细展开。但基本思路是类似的:你需要创建一个Swift
或Objective-C
的桥接文件,使用OpenCV的iOS库来处理图像,并通过Flutter的MethodChannel
与Dart代码通信。
5. 添加OpenCV依赖
确保在Android和iOS项目中正确配置了OpenCV库。对于Android,你可能需要将OpenCV的SDK添加到项目中,并在build.gradle
文件中进行配置。对于iOS,你需要将OpenCV的framework添加到Xcode项目中。
6. 运行应用
现在,你应该能够在Flutter应用中调用OpenCV的功能来处理图像了。请注意,这只是一个基本示例,实际应用中可能需要进行更多的错误处理和优化。
由于篇幅限制和平台差异,这里提供的代码可能需要根据实际情况进行调整和完善。希望这个示例能帮助你入门在Flutter中使用OpenCV进行图像处理。