Flutter目标检测插件ultralytics_yolo的使用

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

Flutter目标检测插件ultralytics_yolo的使用

简介

ultralytics_yolo 是一个Flutter插件,用于将Ultralytics YOLO计算机视觉模型集成到移动应用中。该插件支持Android和iOS平台,并提供对象检测和图像分类的API。

特性

功能 Android iOS
检测
分类
姿态估计
分割
OBB检测

在进一步操作或报告新问题之前,请确保您已彻底阅读本文档。

使用方法

先决条件

导出Ultralytics YOLO模型

在使用Ultralytics YOLO之前,必须导出所需的模型。导出的模型文件格式为.tflite.mlmodel,然后将其包含在您的应用中。使用Ultralytics YOLO CLI导出模型。

Android
yolo export format=tflite model=yolov8n imgsz=320 int8
iOS
yolo export format=mlmodel model=yolov8n imgsz=[320, 192] half nms

安装

导出模型后,您会得到.tflite.mlmodel文件。将这些文件包含在您的应用的assets文件夹中。

权限

确保您有访问相机和存储的必要权限。

Android

AndroidManifest.xml中添加以下权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
iOS

Info.plist中添加以下权限:

<key>NSCameraUsageDescription</key>
<string>Camera permission is required for object detection.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Storage permission is required for object detection.</string>

Podfile中添加以下配置:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)

    # Start of the permission_handler configuration
    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        '$(inherited)',
        
        ## dart: PermissionGroup.camera
        'PERMISSION_CAMERA=1',

        ## dart: PermissionGroup.photos
        'PERMISSION_PHOTOS=1',
      ]
    end 
    # End of the permission_handler configuration
  end
end

使用示例

创建预测器对象

使用LocalYoloModel类创建预测器对象。此类需要以下参数:

final model = LocalYoloModel(
  id: id,
  task: Task.detect /* 或 Task.classify */,
  format: Format.tflite /* 或 Format.coreml*/,
  modelPath: modelPath,
  metadataPath: metadataPath,
);
对象检测器
final objectDetector = ObjectDetector(model: model);
await objectDetector.loadModel();
图像分类器
final imageClassifier = ImageClassifier(model: model);
await imageClassifier.loadModel();

相机预览

使用UltralyticsYoloCameraPreview小部件显示相机预览和预测结果。

final _controller = UltralyticsYoloCameraController();

UltralyticsYoloCameraPreview(
  predictor: predictor, // 您的预测模型数据
  controller: _controller, // Ultralytics相机控制器
  loadingPlaceholder: Center(
    child: Wrap(
      direction: Axis.vertical,
      crossAxisAlignment: WrapCrossAlignment.center,
      children: [
        const CircularProgressIndicator(
          color: Colors.white,
          strokeWidth: 2,
        ),
        const SizedBox(height: 20),
        Text(
          'Loading model...',
          style: theme.typography.base.copyWith(
            color: Colors.white,
            fontSize: 14,
          ),
        ),
      ],
    ),
  ),
)

图像检测与分类

使用detectclassify方法获取图像预测结果。

objectDetector.detect(imagePath: imagePath);
// 或
imageClassifier.classify(imagePath: imagePath);

示例代码

以下是完整的示例代码,展示了如何在Flutter应用中使用ultralytics_yolo插件进行对象检测。

import 'dart:io' as io;
import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:ultralytics_yolo/ultralytics_yolo.dart';
import 'package:ultralytics_yolo/yolo_model.dart';

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final controller = UltralyticsYoloCameraController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: FutureBuilder<bool>(
          future: _checkPermissions(),
          builder: (context, snapshot) {
            final allPermissionsGranted = snapshot.data ?? false;

            return !allPermissionsGranted
                ? Container()
                : FutureBuilder<ObjectDetector>(
                    future: _initObjectDetectorWithLocalModel(),
                    builder: (context, snapshot) {
                      final predictor = snapshot.data;

                      return predictor == null
                          ? Container()
                          : Stack(
                              children: [
                                UltralyticsYoloCameraPreview(
                                  controller: controller,
                                  predictor: predictor,
                                  onCameraCreated: () {
                                    predictor.loadModel(useGpu: true);
                                  },
                                ),
                                StreamBuilder<double?>(
                                  stream: predictor.inferenceTime,
                                  builder: (context, snapshot) {
                                    final inferenceTime = snapshot.data;

                                    return StreamBuilder<double?>(
                                      stream: predictor.fpsRate,
                                      builder: (context, snapshot) {
                                        final fpsRate = snapshot.data;

                                        return Times(
                                          inferenceTime: inferenceTime,
                                          fpsRate: fpsRate,
                                        );
                                      },
                                    );
                                  },
                                ),
                              ],
                            );
                    },
                  );
          },
        ),
        floatingActionButton: FloatingActionButton(
          child: const Icon(Icons.abc),
          onPressed: () {
            controller.toggleLensDirection();
          },
        ),
      ),
    );
  }

  Future<ObjectDetector> _initObjectDetectorWithLocalModel() async {
    final modelPath = await _copy('assets/yolov8n_int8.tflite');
    final metadataPath = await _copy('assets/metadata.yaml');
    final model = LocalYoloModel(
      id: '',
      task: Task.detect,
      format: Format.tflite,
      modelPath: modelPath,
      metadataPath: metadataPath,
    );

    return ObjectDetector(model: model);
  }

  Future<ImageClassifier> _initImageClassifierWithLocalModel() async {
    final modelPath = await _copy('assets/yolov8n-cls.mlmodel');
    final model = LocalYoloModel(
      id: '',
      task: Task.classify,
      format: Format.coreml,
      modelPath: modelPath,
    );

    return ImageClassifier(model: model);
  }

  Future<String> _copy(String assetPath) async {
    final path = '${(await getApplicationSupportDirectory()).path}/$assetPath';
    await io.Directory(dirname(path)).create(recursive: true);
    final file = io.File(path);
    if (!await file.exists()) {
      final byteData = await rootBundle.load(assetPath);
      await file.writeAsBytes(byteData.buffer
          .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
    }
    return file.path;
  }

  Future<bool> _checkPermissions() async {
    List<Permission> permissions = [];

    var cameraStatus = await Permission.camera.status;
    if (!cameraStatus.isGranted) permissions.add(Permission.camera);

    var storageStatus = await Permission.storage.status;
    if (!storageStatus.isGranted) permissions.add(Permission.storage);

    if (permissions.isEmpty) {
      return true;
    } else {
      try {
        Map<Permission, PermissionStatus> statuses =
            await permissions.request();
        return statuses[Permission.camera] == PermissionStatus.granted &&
            statuses[Permission.storage] == PermissionStatus.granted;
      } on Exception catch (_) {
        return false;
      }
    }
  }
}

class Times extends StatelessWidget {
  const Times({
    super.key,
    required this.inferenceTime,
    required this.fpsRate,
  });

  final double? inferenceTime;
  final double? fpsRate;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Align(
        alignment: Alignment.bottomCenter,
        child: Container(
            margin: const EdgeInsets.all(20),
            padding: const EdgeInsets.all(20),
            decoration: const BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(10)),
              color: Colors.black54,
            ),
            child: Text(
              '${(inferenceTime ?? 0).toStringAsFixed(1)} ms  -  ${(fpsRate ?? 0).toStringAsFixed(1)} FPS',
              style: const TextStyle(color: Colors.white70),
            )),
      ),
    );
  }
}

通过上述步骤,您可以成功地在Flutter应用中集成Ultralytics YOLO模型进行对象检测和图像分类。希望这个指南对您有所帮助!


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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用ultralytics_yolo插件进行目标检测的示例代码。这个插件允许你使用YOLO(You Only Look Once)模型进行实时目标检测。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加ultralytics_yolo依赖:

dependencies:
  flutter:
    sdk: flutter
  ultralytics_yolo: ^最新版本号  # 请替换为实际发布的最新版本号

然后运行flutter pub get来获取依赖。

2. 配置Android和iOS权限

由于目标检测需要访问设备的摄像头,你需要在AndroidManifest.xmlInfo.plist中添加相应的权限。

Android

android/app/src/main/AndroidManifest.xml中添加:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

iOS

ios/Runner/Info.plist中添加:

<key>NSCameraUsageDescription</key>
<string>需要访问相机以进行目标检测</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>需要访问照片库以保存检测结果</string>

3. 使用ultralytics_yolo插件

以下是一个简单的Flutter应用示例,展示如何使用ultralytics_yolo插件进行目标检测:

import 'package:flutter/material.dart';
import 'package:ultralytics_yolo/ultralytics_yolo.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter YOLO 目标检测',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: CameraScreen(),
    );
  }
}

class CameraScreen extends StatefulWidget {
  @override
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  late UltralyticsYolo _yolo;
  late CameraController _cameraController;

  @override
  void initState() {
    super.initState();
    // 初始化YOLO模型
    _yolo = UltralyticsYolo(
      weights: 'yolov5s.pt',  // 你可以指定其他权重文件
      source: '0',  // 使用设备的后置摄像头
      conf: 0.25,  // 置信度阈值
    );

    // 初始化相机控制器
    _cameraController = CameraController(
      _yolo.camera!,
      ResolutionPreset.high,
      enableAudio: false,
    );
    _cameraController.initialize().then((_) {
      if (!mounted) return;
      setState(() {});
    });
  }

  @override
  void dispose() {
    _cameraController.dispose();
    _yolo.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    if (!_cameraController.value.isInitialized) {
      return Container();
    }

    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter YOLO 目标检测'),
      ),
      body: Stack(
        children: [
          CameraPreview(_cameraController),
          _buildOverlay(),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          // 捕获图像并进行目标检测
          final image = await _cameraController.capture();
          final detections = await _yolo.detect(image: image.path);
          print(detections);  // 打印检测结果
        },
        tooltip: '检测',
        child: Icon(Icons.photo_camera),
      ),
    );
  }

  Widget _buildOverlay() {
    if (!_cameraController.value.isRecordingImage) {
      return Container();
    }
    // 这里你可以添加代码来绘制检测结果,例如使用CustomPaint
    return Container();
  }
}

注意事项

  1. 模型权重:你需要下载YOLOv5的权重文件(如yolov5s.pt),并将其放置在合适的位置,或者直接使用在线权重(如果插件支持)。
  2. 性能:目标检测是一个计算密集型的任务,确保在适当的设备上运行,以获得流畅的体验。
  3. 权限处理:在实际应用中,你需要处理用户权限的请求和拒绝情况。

这个示例代码展示了如何在Flutter应用中使用ultralytics_yolo插件进行基本的目标检测。根据具体需求,你可能需要进一步优化和扩展代码。

回到顶部