Flutter物体检测插件learning_object_detection的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter物体检测插件 learning_object_detection 的使用

概述

learning_object_detection 是一个用于在Flutter应用中进行物体检测和跟踪的插件。它基于ML Kit,可以轻松实现从图像或实时摄像头流中检测和跟踪物体,并可选择对检测到的物体进行分类。

示例截图

开始使用

添加依赖

首先,在你的Flutter项目的pubspec.yaml文件中添加以下依赖:

dependencies:
  learning_object_detection: ^0.0.1

然后运行以下命令来获取依赖:

flutter pub get

导入包

在你的Dart文件中导入必要的包:

import 'package:learning_object_detection/learning_object_detection.dart';
import 'package:learning_input_image/learning_input_image.dart';

使用方法

输入图像

输入图像需要转换为InputImage格式,这可以通过learning_input_image包中的InputCameraView小部件来实现。该小部件可以从相机或存储中处理图像并将其转换为InputImage格式。

以下是一个使用InputCameraView获取InputImage的例子:

InputCameraView(
  title: 'Object Detection & Tracking',
  onImage: (InputImage image) {
    // 现在我们可以将输入图像送入对象检测器
  },
)

物体检测

一旦有了InputImage,我们就可以通过调用ObjectDetector实例的detect方法开始检测物体。

ObjectDetector detector = ObjectDetector();
List<DetectedObject> result = await detector.detect(image);

你可以根据需要自定义ObjectDetector的参数:

ObjectDetector detector = ObjectDetector(
  isStream: false, // 是否处理图像流
  enableClassification: true, // 是否启用分类
  enableMultipleObjects: true, // 是否检测多个物体
);
参数 可选值 默认值
isStream false / true false
enableClassification false / true true
enableMultipleObjects false / true true

输出结果

检测结果是一个DetectedObject列表,每个对象包含以下信息:

int? trackingId // 跟踪ID(当isStream为false时为null)
Rect boundingBox // 包围检测到的物体的矩形框
List<DetectedLabel> labels // 可能的标签列表

每个DetectedLabel包含以下数据:

int index // 标签索引
String label // 物体的标签
double confidence // 表示标签正确的概率

绘制检测结果

为了方便地将DetectedObject绘制到屏幕上,插件提供了ObjectOverlay类,你可以将其传递给InputCameraView的小部件overlay参数。

ObjectOverlay(
  size: size,
  originalSize: originalSize,
  rotation: rotation,
  objects: objects,
)

清理资源

确保在不需要时释放资源:

detector.dispose();

示例项目

完整的示例代码可以在这里找到。

示例代码

下面是一个完整的示例项目代码:

import 'package:flutter/material.dart';
import 'package:learning_input_image/learning_input_image.dart';
import 'package:learning_object_detection/learning_object_detection.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
        primaryTextTheme: TextTheme(headline6: TextStyle(color: Colors.white)),
      ),
      home: ChangeNotifierProvider(
        create: (_) => ObjectDetectionState(),
        child: ObjectDetectionPage(),
      ),
    );
  }
}

class ObjectDetectionPage extends StatefulWidget {
  [@override](/user/override)
  _ObjectDetectionPageState createState() => _ObjectDetectionPageState();
}

class _ObjectDetectionPageState extends State<ObjectDetectionPage> {
  ObjectDetectionState get state => Provider.of(context, listen: false);

  ObjectDetector _detector = ObjectDetector(
    isStream: false,
    enableClassification: true,
    enableMultipleObjects: true,
  );

  [@override](/user/override)
  void dispose() {
    _detector.dispose();
    super.dispose();
  }

  Future<void> _detectObjects(InputImage image) async {
    if (state.isNotProcessing) {
      state.startProcessing();
      state.image = image;
      state.data = await _detector.detect(image);
      state.stopProcessing();
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return InputCameraView(
      cameraDefault: InputCameraType.rear,
      title: 'Object Detection & Tracking',
      onImage: _detectObjects,
      overlay: Consumer<ObjectDetectionState>(
        builder: (_, state, __) {
          if (state.isEmpty) {
            return Container();
          }

          Size originalSize = state.size!;
          Size size = MediaQuery.of(context).size;

          // 如果图像是从相册获取的
          // 图像显示大小会被缩放到360x360,并保持宽高比
          if (state.notFromLive) {
            if (originalSize.aspectRatio > 1) {
              size = Size(360.0, 360.0 / originalSize.aspectRatio);
            } else {
              size = Size(360.0 * originalSize.aspectRatio, 360.0);
            }
          }

          return ObjectOverlay(
            size: size,
            originalSize: originalSize,
            rotation: state.rotation,
            objects: state.data,
          );
        },
      ),
    );
  }
}

class ObjectDetectionState extends ChangeNotifier {
  InputImage? _image;
  List<DetectedObject> _data = [];
  bool _isProcessing = false;

  InputImage? get image => _image;
  List<DetectedObject> get data => _data;

  String? get type => _image?.type;
  InputImageRotation? get rotation => _image?.metadata?.rotation;
  Size? get size => _image?.metadata?.size;

  bool get isNotProcessing => !_isProcessing;
  bool get isEmpty => _data.isEmpty;
  bool get isFromLive => type == 'bytes';
  bool get notFromLive => !isFromLive;

  void startProcessing() {
    _isProcessing = true;
    notifyListeners();
  }

  void stopProcessing() {
    _isProcessing = false;
    notifyListeners();
  }

  set image(InputImage? image) {
    _image = image;

    if (notFromLive) {
      _data = [];
    }
    notifyListeners();
  }

  set data(List<DetectedObject> data) {
    _data = data;
    notifyListeners();
  }
}

更多关于Flutter物体检测插件learning_object_detection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter物体检测插件learning_object_detection的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用learning_object_detection插件进行物体检测的示例代码。这个插件允许你使用TensorFlow Lite模型在移动设备上执行实时物体检测。

前提条件

  1. 确保你已经安装了Flutter SDK。
  2. 确保你的Android或iOS设备已经连接并可以被Flutter识别。
  3. 在你的pubspec.yaml文件中添加learning_object_detection依赖。
dependencies:
  flutter:
    sdk: flutter
  learning_object_detection: ^0.6.0  # 请检查最新版本号

步骤

  1. 创建Flutter项目(如果还没有项目的话):
flutter create object_detection_app
cd object_detection_app
  1. 添加依赖并获取TensorFlow Lite模型

    确保在pubspec.yaml中添加了learning_object_detection依赖,然后运行flutter pub get

    你需要一个TensorFlow Lite模型文件(通常是.tflite格式)和一个与之对应的标签文件(通常是.txt格式)。这些文件可以从TensorFlow Model Zoo或你自己训练的模型中获取。

  2. 配置Android和iOS项目

    将你的.tflite模型和.txt标签文件添加到项目的assets文件夹中,并在pubspec.yaml中声明它们:

flutter:
  assets:
    - assets/model.tflite
    - assets/labels.txt
  1. 编写Flutter代码

    下面是一个简单的示例,展示如何使用learning_object_detection插件进行物体检测:

import 'package:flutter/material.dart';
import 'package:learning_object_detection/learning_object_detection.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Object Detection App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ObjectDetectionScreen(),
    );
  }
}

class ObjectDetectionScreen extends StatefulWidget {
  @override
  _ObjectDetectionScreenState createState() => _ObjectDetectionScreenState();
}

class _ObjectDetectionScreenState extends State<ObjectDetectionScreen> {
  late ObjectDetector _objectDetector;
  late CameraController _cameraController;

  @override
  void initState() {
    super.initState();
    _initCamera();
    _initObjectDetector();
  }

  Future<void> _initCamera() async {
    // 初始化相机控制器(这里省略具体实现,可以使用camera插件)
    // _cameraController = ...
  }

  Future<void> _initObjectDetector() async {
    _objectDetector = await ObjectDetector.loadModel(
      model: 'assets/model.tflite',
      labels: 'assets/labels.txt',
      numThreads: 1,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Object Detection'),
      ),
      body: Center(
        child: _cameraController.value.isInitialized
            ? AspectRatio(
                aspectRatio: _cameraController.value.aspectRatio,
                child: CameraPreview(_cameraController),
              )
            : Container(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          if (_cameraController.value.isRecordingImage) return;
          final Uint8List imageBytes = await _cameraController.capture();
          final ui.Image image = await loadImage(imageBytes);
          final List<Detection> detections = await _objectDetector.detectObjectsOnImage(image);
          // 处理检测结果(这里可以绘制检测框等)
        },
        tooltip: 'Capture Image and Detect Objects',
        child: Icon(Icons.camera_alt),
      ),
    );
  }

  Future<ui.Image> loadImage(Uint8List imageBytes) async {
    final Completer<ui.Image> completer = Completer<ui.Image>();
    ui.decodeImageFromList(imageBytes, (ui.Image img) {
      completer.complete(img);
    });
    return completer.future;
  }

  @override
  void dispose() {
    _cameraController?.dispose();
    _objectDetector?.close();
    super.dispose();
  }
}

注意

  • 上面的代码示例中省略了相机初始化的具体实现,你可以使用camera插件来管理相机预览和捕获图像。
  • loadImage函数用于将图像字节数据解码为ui.Image对象,这是learning_object_detection插件所需要的格式。
  • 检测结果detections是一个Detection对象的列表,每个对象包含检测到的物体的边界框、标签和置信度等信息。

运行项目

确保所有依赖都已正确安装,并且你的设备和开发环境已经配置好,然后运行:

flutter run

这将启动你的Flutter应用,并允许你捕获图像并检测其中的物体。

回到顶部