发布于 2026-01-06 6 阅读
0

Flutter 对象检测应用 + YOLOV5 模型。

Flutter 对象检测应用 + YOLOV5 模型。

Flutter 是一款流行的开源移动应用开发框架,它允许开发者创建高性能的跨平台应用,支持 Android 和 iOS 设备。凭借其易用性和灵活性,Flutter 已成为开发者构建移动应用的热门选择。

移动应用最常见的应用场景之一是目标检测,即应用能够识别和分类图像或视频中的物体。YOLOv5 是一种先进的目标检测算法,近年来因其高精度和高速度而广受欢迎。

在本文中,我们将探讨如何将 YOLOv5 与 Flutter 集成,以创建一个目标检测应用程序。

1. 环境搭建:

首先,你需要搭建开发环境。你的电脑上需要安装 Flutter 和 Python。之后,打开 VS Code 并创建一个新的 Flutter 项目。

flutter create object_detection
Enter fullscreen mode Exit fullscreen mode

等待项目创建完成。
现在,打开https://pub.dev/packages/flutter_pytorch并导航至“安装”选项卡,您可以在那里找到最新的软件包版本,目前该软件包版本为 1.0.1。
运行以下命令:

使用 Flutter:
$ flutter pub add flutter_pytorch
这会在你的包的 pubspec.yaml 文件中添加类似这样的行(并隐式运行 flutter pub get):

dependencies:
  flutter_pytorch: ^1.0.1
Enter fullscreen mode Exit fullscreen mode

或者,您的编辑器可能支持 flutter pub get。请查阅编辑器的文档了解更多信息。

导入
后,您可以在 Dart 代码中使用:

import 'package:flutter_pytorch/flutter_pytorch.dart';
Enter fullscreen mode Exit fullscreen mode

2. 准备模型。

在 Flutter 应用中使用 YOLOv5 之前,您需要先在特定的数据集上训练模型。您可以使用现有数据集,也可以创建自己的数据集来训练模型。
本文使用的是https://github.com/ultralytics/yolov5上提供的 YOLOv5 预训练模型。由于我们需要进行目标检测,因此需要将预训练模型的权重转换为 TorchScript 格式。

分类

import torch
from torch.utils.mobile_optimizer import optimize_for_mobile
model = torch.load('model_scripted.pt',map_location="cpu")
model.eval()
example = torch.rand(1, 3, 224, 224)
traced_script_module = torch.jit.trace(model, example)
optimized_traced_model = optimize_for_mobile(traced_script_module)
optimized_traced_model._save_for_lite_interpreter("model.pt")
Enter fullscreen mode Exit fullscreen mode

目标检测(YOLOv5)

!python export.py --weights "the weights of your model" --include torchscript --img 640 --optimize
Enter fullscreen mode Exit fullscreen mode

例子

!python export.py --weights yolov5s.pt --include torchscript --img 640 --optimize
Enter fullscreen mode Exit fullscreen mode

3. 为应用程序创建基本用户界面。

打开应用程序的 lib 文件夹,你会看到 main.dart 文件,这是 Dart 的主编译文件。
在连接的模拟器或手机上以调试模式运行该文件。

emulator -avd "Your emulator name"
Enter fullscreen mode Exit fullscreen mode

现在通过 VS Code 的调试模式运行您的应用程序,因为它提供快速重新加载和热重启功能。

您的初始应用程序应如下所示

创建用户界面设计
为了设计应用程序,我们将遵循工作分解结构 (WBS) 来进行应用程序设计和机器学习模型集成。
请打开 main.dart 文件,并将所有代码替换为以下内容:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'OBJECT DETECTOR',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
    );
  }
}

Enter fullscreen mode Exit fullscreen mode

以上代码只是一个基本的应用程序类结构,其中移除了所有不必要的代码。重新加载后,你会看到类似如下的黑屏:


如果你是新手,别慌,耐心点,我们才刚刚开始😂。

在 lib 文件夹内创建一个名为 HomeScreen.dart 的新 Dart 文件。
现在,如果您输入 stf 并按回车键,它将自动创建相关的代码结构,这里我们使用的是有状态组件。

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
Enter fullscreen mode Exit fullscreen mode

现在在 Scaffold 类中创建一个文本,如下所示:

 return Scaffold(
      backgroundColor: Colors.white,
      body: Text("Home Screen"),
    );
Enter fullscreen mode Exit fullscreen mode

并将此主屏幕状态作为应用程序状态调用,如下所示:

home: HomeScreen(),
Enter fullscreen mode Exit fullscreen mode

现在您可以看到应用程序已更改为:

现在在 HomeScreen.dart 中添加以下代码,以设计应用程序的基本用户界面。

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("OBJECT DETECTOR APP")),
      backgroundColor: Colors.white,
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          //Image with Detections....
          //Button to click pic
          ElevatedButton(
            onPressed: () {},
            child: const Icon(Icons.camera),
          )
        ],
      )),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode


现在该应用程序已准备好与模型集成。

4. 将模型与 Flutter 集成

模型训练完成后,即可将其集成到 Flutter 应用中。首先,创建一个名为 assets 的文件夹,并在其中创建 model 和 labels 子文件夹,同时在 pubspec.yaml 文件中声明这些子文件夹。如下图所示:

创建额外的模型和标签文件夹后的文件夹结构。

添加 assets 路径后的 pubspec.yaml 文件:


现在将转换后的模型放入 models 文件夹,并创建 labels.txt 文件,将标签放入其中。


或者您可以从以下链接下载模型和标签:
https://github.com/AneeqMalik/flutter_pytorch/tree/main/example/assets
请给这个仓库点个星标😊。
将标签和模型放入各自的文件夹后,就可以等待将模型集成到我们的应用中了。

整合YOLOv5模型

  • 创建以下变量:
File? _imageFile;
  late ModelObjectDetection _objectModel;
  String? _imagePrediction;
  List? _prediction;
  File? _image;
  ImagePicker _picker = ImagePicker();
  bool objectDetection = false;
  List<ResultObjectDetection?> objDetect = [];
Enter fullscreen mode Exit fullscreen mode
  • 创建一个函数,用于将模型加载到应用程序中:
Future loadModel() async {
    String pathObjectDetectionModel = "assets/models/yolov5s.torchscript";
    try {
      _objectModel = await FlutterPytorch.loadObjectDetectionModel(
          //Remeber here 80 value represents number of classes for custom model it will be different don't forget to change this.
          pathObjectDetectionModel, 80, 640, 640,
          labelPath: "assets/labels/labels.txt");
    } catch (e) {
      if (e is PlatformException) {
        print("only supported for android, Error is $e");
      } else {
        print("Error is $e");
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode
  • 在 initState() 函数内部调用 load 函数,以便在应用启动时加载模型:
@override
  void initState() {
    // TODO: implement initState
    super.initState();
    loadModel();
  }
Enter fullscreen mode Exit fullscreen mode
  • 在列中添加以下组件:
 body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          //Image with Detections....
          Expanded(
            child: Container(
              height: 150,
              width: 300,
              child: objDetect.isNotEmpty
                  ? _image == null
                      ? Text('No image selected.')
                      : _objectModel!.renderBoxesOnImage(_image!, objDetect)
                  : _image == null
                      ? Text('No image selected.')
                      : Image.file(_image!),
            ),
          ),
          Center(
            child: Visibility(
              visible: _imagePrediction != null,
              child: Text("$_imagePrediction"),
            ),
          ),
          //Button to click pic
          ElevatedButton(
            onPressed: () {
              runObjectDetection();
            },
            child: const Icon(Icons.camera),
          )
        ],
      )),
Enter fullscreen mode Exit fullscreen mode
  • 最后,创建一个目标检测函数,以获取检测到的图像的推断结果:
Future runObjectDetection() async {
    //pick an image

    final XFile? image = await _picker.pickImage(
        source: ImageSource.gallery, maxWidth: 200, maxHeight: 200);
    objDetect = await _objectModel.getImagePrediction(
        await File(image!.path).readAsBytes(),
        minimumScore: 0.1,
        IOUThershold: 0.3);
    objDetect.forEach((element) {
      print({
        "score": element?.score,
        "className": element?.className,
        "class": element?.classIndex,
        "rect": {
          "left": element?.rect.left,
          "top": element?.rect.top,
          "width": element?.rect.width,
          "height": element?.rect.height,
          "right": element?.rect.right,
          "bottom": element?.rect.bottom,
        },
      });
    });
    setState(() {
      _image = File(image!.path);
    });
  }
Enter fullscreen mode Exit fullscreen mode

更改默认 SDK 版本
后,在进行上述更改后运行应用程序,应用程序将无法编译,并会出现类似于以下的问题:


您需要修改以下文件中的默认 SDK 版本:
ProjectName\object_detection\android\app\build.gradle:


保存更改并重新运行应用构建。
等待构建完成,期间可能会出现一些警告,但暂时忽略它们。

5. 测试应用程序

为了测试您的应用程序,您可以向应用程序提供图像或视频,并查看模型如何检测媒体中的对象。

屏幕截图

🥳🥳🥳🥳应用程序运行正常,并能进行检测。

源代码链接

https://github.com/AneeqMalik/Flutter-Object-Detector-App-YOLOv5-

其他资源/信息

https://pub.dev/packages/flutter_pytorch

文章来源:https://dev.to/aneeqmalik/flutter-object-detection-app-yolov5-model-3h4l