Flutter图像标签识别插件ml_kit_image_labeler的使用

Flutter图像标签识别插件ml_kit_image_labeler的使用

该插件提供了原生的ML Kit ImageLabeler API。

需求

Android

  • 设置 minSdkVersion 21android/app/build.gradle
  • 添加 <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="ica" />android/src/main/AndroidManifest.xml
  • 注意:如果使用多个模型,用逗号分隔它们 <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="ica,ocr" />
  • 设置 ext.kotlin_version = '1.6.10'android/build.gradle
  • 应用大小影响:700KB(使用未捆绑模型,在首次启动应用时通过Google Play服务下载模型),详情见此处

iOS

  • 最低iOS部署目标:10.0
  • Xcode 12.5.1或更高版本。
  • ML Kit仅支持64位架构(x86_64和arm64)。查看此列表以确认设备是否具备所需架构。
  • 由于ML Kit不支持32位架构(i386和armv7),了解更多,你需要在Xcode中排除armv7架构来构建iOS应用,详情见此处

使用方法

// 创建一个[MlKitImageLabeler]实例
final imageLabeler = MlKitImageLabeler();

//...
// 使用图像选择器选择图像
//...

// 调用`processImage()`并传递参数为`InputImage`(详见示例)
final labels = await imageLabeler.processImage(InputImage.fromFilePath(image.path));

String predictedLabels = '';

// 遍历标签
for (var label in labels) {
  predictedLabels += '\n${label.label} ${(label.confidence * 100).toStringAsPrecision(2)}%';
}

该插件基本上是google_ml_kit的一个简化版。由于google_ml_kit包含了所有NLP和Vision API,应用程序的大小会大幅增加。因此,我创建了这个插件,现在示例应用的完整APK大小为17MB,分割后的APK大小为6MB。

完整示例

以下是一个完整的示例代码,展示了如何使用ml_kit_image_labeler插件进行图像标签识别:

import 'dart:io';

import 'package:flutter/material.dart';

import 'package:image_picker/image_picker.dart';

import 'package:ml_kit_image_labeler/ml_kit_image_labeler.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  XFile? image;
  String predictedLabels = '';
  String timeElapsed = '';
  bool isProcessing = false;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('MLKit图像标签识别示例'),
        ),
        body: ListView(
          physics: const ClampingScrollPhysics(),
          children: [
            const SizedBox(height: 20),
            if (image != null)
              SizedBox(
                height: 200,
                width: 200,
                child: InteractiveViewer(
                  child: Image.file(
                    File(image!.path),
                    fit: BoxFit.contain,
                  ),
                ),
              ),
            const SizedBox(height: 20),
            if (predictedLabels.isNotEmpty)
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: SelectableText('预测标签: $predictedLabels'),
              ),
            if (timeElapsed.isNotEmpty)
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Text('处理时间: $timeElapsed ms'),
              ),
            const SizedBox(height: 20),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              children: [
                ElevatedButton(
                  onPressed: () async {
                    image = await ImagePicker().pickImage(source: ImageSource.gallery);
                    predictedLabels = '';
                    timeElapsed = '';
                    setState(() {});
                  },
                  child: const Text('选择图像'),
                ),
                if (image != null)
                  isProcessing
                      ? const Center(
                          child: CircularProgressIndicator.adaptive(),
                        )
                      : ElevatedButton(
                          onPressed: () async {
                            final imageLabeler = MlKitImageLabeler();
                            final stopwatch = Stopwatch()..start();
                            predictedLabels = '';
                            isProcessing = true;
                            setState(() {});

                            final labels = await imageLabeler.processImage(
                                InputImage.fromFilePath(image!.path));

                            timeElapsed = stopwatch.elapsedMilliseconds.toString();

                            isProcessing = false;

                            for (var label in labels) {
                              predictedLabels += '\n${label.label} ${(label.confidence * 100).toStringAsPrecision(4)}%';
                            }
                            stopwatch.reset();
                            stopwatch.stop();

                            setState(() {});
                          },
                          child: const Text('从图像中预测'),
                        ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter图像标签识别插件ml_kit_image_labeler的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图像标签识别插件ml_kit_image_labeler的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中使用ml_kit_image_labeler插件进行图像标签识别是一个非常直接的过程。ml_kit_image_labeler是基于Google的ML Kit的Flutter插件,用于从图像中提取标签信息。以下是如何使用该插件的详细步骤:

1. 添加依赖项

首先,你需要在pubspec.yaml文件中添加ml_kit_image_labeler插件的依赖项。

dependencies:
  flutter:
    sdk: flutter
  ml_kit_image_labeler: ^0.0.1  # 请检查最新版本

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

2. 导入插件

在你的Dart文件中导入ml_kit_image_labeler插件。

import 'package:ml_kit_image_labeler/ml_kit_image_labeler.dart';

3. 初始化图像标签识别器

在使用图像标签识别器之前,你需要先初始化它。

final ImageLabeler imageLabeler = ImageLabeler();

4. 从图像中提取标签

你可以从本地文件或网络加载图像,然后使用imageLabeler.processImage方法来提取标签。

import 'dart:io';
import 'package:image_picker/image_picker.dart';

Future<void> processImage() async {
  // 使用image_picker插件从相册中选择图像
  final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);

  if (pickedFile != null) {
    final File imageFile = File(pickedFile.path);

    // 提取标签
    final List<ImageLabel> labels = await imageLabeler.processImage(imageFile);

    // 打印标签
    labels.forEach((label) {
      print('Label: ${label.label}, Confidence: ${label.confidence}');
    });
  }
}

5. 释放资源

在使用完图像标签识别器后,记得释放资源。

await imageLabeler.close();

6. 处理标签

ImageLabel对象包含两个属性:

  • label: 标签的名称。
  • confidence: 标签的置信度,范围是0到1。

你可以根据这些信息来处理图像标签。

7. 处理权限

如果你的应用需要从设备上选择图像,确保你已经处理了必要的权限。你可以使用permission_handler插件来请求权限。

dependencies:
  permission_handler: ^10.0.0  # 请检查最新版本

然后请求权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestPermissions() async {
  if (await Permission.storage.request().isGranted) {
    // 权限已授予
  }
}

8. 完整示例

以下是一个完整的示例,展示了如何使用ml_kit_image_labeler插件从图像中提取标签:

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:ml_kit_image_labeler/ml_kit_image_labeler.dart';
import 'dart:io';

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageLabelerScreen(),
    );
  }
}

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

class _ImageLabelerScreenState extends State<ImageLabelerScreen> {
  final ImageLabeler imageLabeler = ImageLabeler();
  List<ImageLabel> labels = [];

  Future<void> processImage() async {
    final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);

    if (pickedFile != null) {
      final File imageFile = File(pickedFile.path);

      final List<ImageLabel> result = await imageLabeler.processImage(imageFile);

      setState(() {
        labels = result;
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Image Labeler'),
      ),
      body: Column(
        children: [
          ElevatedButton(
            onPressed: processImage,
            child: Text('Pick Image'),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: labels.length,
              itemBuilder: (context, index) {
                final label = labels[index];
                return ListTile(
                  title: Text(label.label),
                  subtitle: Text('Confidence: ${label.confidence.toStringAsFixed(2)}'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  [@override](/user/override)
  void dispose() {
    imageLabeler.close();
    super.dispose();
  }
}
回到顶部