Flutter图像标注插件bounding_box_annotation的使用
Flutter图像标注插件bounding_box_annotation的使用
标题
Flutter图像标注插件bounding_box_annotation的使用
内容
一个用于在图像上创建边界框标注的Widget。
预览
功能
- 在图像上绘制矩形(边界框)。
- 添加/编辑自定义文本以标记标注。
- 获取标注详细信息(例如Offset)。
- 基于边界框裁剪图像为多个部分。
- 删除标注。
使用方法
- 创建
BoundingBoxAnnotation
widget,并传递所需的参数。
final AnnotationController annotationController = AnnotationController();
BoundingBoxAnnotation(
controller: annotationController,
imageBytes: imageBytes
)
- 自定义图像大小。
BoundingBoxAnnotation(
controller: annotationController,
imageBytes: imageBytes,
imageWidth: 400.0,
imageHeight: 400.0,
)
- 自定义标注样式。
BoundingBoxAnnotation(
controller: annotationController,
imageBytes: imageBytes,
color: Colors.blue,
strokeWidth: 5.0,
)
- 创建一个
List
变量来存储标注。
List<AnnottaionDetails> annotationList = [];
- 获取标注详细信息:
final AnnotationController annotationController = AnnotationController();
List<AnnottaionDetails> annotationList = await annotationController.getData();
- 手动添加标注:
final AnnotationController annotationController = AnnotationController();
double x = 10.0;
double y = 20.0;
double width = 150.0;
double height = 150.0;
String label = "Test"
annotationController.addAnnotation(x, y, width, height, label);
- 清除所有标注:
final AnnotationController annotationController = AnnotationController();
annotationController.clear();
示例代码
import 'package:bounding_box_annotation/bounding_box_annotation.dart';
import 'package:bounding_box_annotation_example/result.dart';
import 'package:bounding_box_annotation_example/widgets/add_annotation_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return const MaterialApp(
home: Loading(),
);
}
}
class Loading extends StatefulWidget {
const Loading({super.key});
[@override](/user/override)
State<Loading> createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
Uint8List? imageBytes;
void getImageBytes() async {
final byteData = await rootBundle.load("assets/flutter-logo.png");
imageBytes = byteData.buffer.asUint8List();
if (context.mounted) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Annotation(imageBytes: imageBytes!),
),
);
}
}
[@override](/user/override)
void initState() {
getImageBytes();
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
}
class Annotation extends StatefulWidget {
final Uint8List imageBytes;
const Annotation({super.key, required this.imageBytes});
[@override](/user/override)
State<Annotation> createState() => _AnnotationState();
}
class _AnnotationState extends State<Annotation> {
final AnnotationController annotationController = AnnotationController();
double? x;
double? y;
double? width;
double? height;
String? label;
void setValue(double x, double y, double width, double height, String label) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.label = label;
}
[@override](/user/override)
void initState() {
super.initState();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
backgroundColor: Colors.blue,
title: const Text(
"Annotation Demo",
style: TextStyle(color: Colors.white, fontWeight: FontWeight.w600),
),
centerTitle: true,
iconTheme: const IconThemeData(color: Colors.white),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.blue,
width: 10.0,
),
),
child: BoundingBoxAnnotation(
controller: annotationController,
imageBytes: widget.imageBytes,
imageWidth: 400.0,
imageHeight: 400.0,
),
),
const SizedBox(height: 22.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(120.0, 45.0),
foregroundColor: Colors.white,
backgroundColor: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
onPressed: () async {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return Center(
child: Container(
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
padding: const EdgeInsets.all(30.0),
child: const SizedBox(
width: 40.0,
height: 40.0,
child: CircularProgressIndicator(
color: Colors.blue,
strokeWidth: 66.0,
),
),
),
);
},
);
List<AnnotationDetails> annotationList =
await annotationController.getData();
if (context.mounted) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Result(annotationList: annotationList),
),
);
}
},
child: const Text(
"Save",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(width: 10.0),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(120.0, 45.0),
foregroundColor: Colors.white,
backgroundColor: Colors.amber,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AddAnnotationDialog(
setValue: setValue,
);
},
).then((value) async {
if (value == true) {
annotationController.addAnnotation(
x!, y!, width!, height!, label!
);
}
});
},
child: const Text(
"Add",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(width: 10.0),
ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: const Size(120.0, 45.0),
foregroundColor: Colors.white,
backgroundColor: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
onPressed: () {
annotationController.clear();
},
child: const Text(
"Clear",
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w600,
),
),
),
],
),
],
),
),
);
}
}
更多关于Flutter图像标注插件bounding_box_annotation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图像标注插件bounding_box_annotation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用bounding_box_annotation
插件来进行图像标注的示例代码。bounding_box_annotation
插件允许用户在图像上绘制矩形框来标注感兴趣的区域。
首先,确保你的Flutter项目已经添加了这个插件。在pubspec.yaml
文件中添加以下依赖项:
dependencies:
flutter:
sdk: flutter
bounding_box_annotation: ^最新版本号 # 替换为实际的最新版本号
然后运行flutter pub get
来安装依赖。
接下来,让我们创建一个简单的示例,展示如何使用bounding_box_annotation
插件。
1. 导入必要的包
在你的Flutter组件文件中(例如main.dart
),导入必要的包:
import 'package:flutter/material.dart';
import 'package:bounding_box_annotation/bounding_box_annotation.dart';
2. 创建标注界面
创建一个包含图像和标注功能的界面:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Bounding Box Annotation Example'),
),
body: AnnotationScreen(),
),
);
}
}
class AnnotationScreen extends StatefulWidget {
@override
_AnnotationScreenState createState() => _AnnotationScreenState();
}
class _AnnotationScreenState extends State<AnnotationScreen> {
final GlobalKey<BoundingBoxAnnotationState> annotationKey = GlobalKey();
List<Rect> boundingBoxes = [];
@override
Widget build(BuildContext context) {
return Stack(
children: [
Image.network(
'https://example.com/your-image-url.jpg', // 替换为你的图像URL
fit: BoxFit.cover,
),
BoundingBoxAnnotation(
key: annotationKey,
onAnnotationChanged: (rectangles) {
setState(() {
boundingBoxes = rectangles;
});
},
),
// 绘制标注框
if (boundingBoxes.isNotEmpty)
Positioned.fill(
child: CustomPaint(
painter: BoundingBoxPainter(boundingBoxes),
),
),
],
);
}
}
class BoundingBoxPainter extends CustomPainter {
final List<Rect> boundingBoxes;
BoundingBoxPainter(this.boundingBoxes);
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = 4.0;
boundingBoxes.forEach((rect) {
final Offset topLeft = Offset(rect.left, rect.top);
final Offset topRight = Offset(rect.right, rect.top);
final Offset bottomLeft = Offset(rect.left, rect.bottom);
final Offset bottomRight = Offset(rect.right, rect.bottom);
canvas.drawLine(topLeft, topRight, paint);
canvas.drawLine(topRight, bottomRight, paint);
canvas.drawLine(bottomRight, bottomLeft, paint);
canvas.drawLine(bottomLeft, topLeft, paint);
});
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return oldDelegate != this;
}
}
3. 运行应用
现在,你可以运行你的Flutter应用,并在图像上标注感兴趣的区域。BoundingBoxAnnotation
组件允许用户绘制矩形框,并通过onAnnotationChanged
回调返回所有标注框的坐标。然后,我们使用CustomPaint
和BoundingBoxPainter
将这些标注框绘制在图像上。
注意事项
- 图像URL:确保你使用的是有效的图像URL。
- 权限:如果你的应用需要访问本地存储的图像,请确保在
AndroidManifest.xml
和Info.plist
中声明了相应的权限。 - 插件版本:确保你使用的是最新版本的
bounding_box_annotation
插件,以获取最新的功能和修复。
希望这个示例能帮助你在Flutter项目中成功使用bounding_box_annotation
插件进行图像标注。