Flutter图像识别插件apple_vision的使用

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

Flutter图像识别插件apple_vision的使用

Apple Vision 是一个 Flutter 插件,使 Flutter 应用能够使用 Apple Vision

重要提示

在继续或发布新问题之前,请务必阅读以下内容:

  • Apple Vision 仅适用于 macOS 和 iOS 应用。
  • 该插件未得到 Apple 的赞助或维护。作者是一些希望为 macOS 开发类似 Google ML Kit 的开发者。

特性

下表列出了当前支持的功能及其对应的插件:

功能 插件 源码 MacOS iOS
面部检测点 apple_vision_face 源码
面部网格 apple_vision_face_mesh 源码
面部检测 apple_vision_face_detection 源码
姿态检测 apple_vision_pose 源码
手部检测 apple_vision_hand 源码
手部检测 3D apple_vision_hand_3d 源码
物体分类 apple_vision_object 源码
物体跟踪 apple_vision_object_tracking 源码
自拍分割 apple_vision_selfie 源码
文本识别 apple_vision_text_recognition 源码
图像分类 apple_vision_image_classification 源码
条形码扫描器 apple_vision_scanner 源码
动物姿态 apple_vision_animal_pose 源码
姿态 3D apple_vision_pose_3d 源码
显著性 apple_vision_saliency 源码
抬升主体 apple_vision_lift_subjects 源码
图像深度 apple_vision_image_depth 源码

要求

MacOS

  • 最低部署目标版本:15.0
  • Xcode 15 或更新版本
  • Swift 5
  • ML Kit 仅支持 64 位架构(x86_64 和 arm64)

iOS

  • 最低部署目标版本:17.0
  • Xcode 15 或更新版本
  • Swift 5
  • ML Kit 仅支持 64 位架构(x86_64 和 arm64)

入门指南

重要提示

在继续或发布新问题之前,请务必阅读以下内容:

  • Apple Vision 仅用于 macOS 应用,未来可能会在 iOS 上可用。
  • 该插件未得到 Apple 的赞助或维护。作者是一些希望为 macOS 开发类似 Google ML Kit 的开发者。
  • Apple Vision API 仅在本地开发中为 macOS 提供支持。此插件使用 Flutter 平台通道,如 这里 所述。
  • 因为该插件使用平台通道,你可能会遇到与原生 API 相关的问题。在提交新问题前,请先确定问题来源。该插件仅适用于 macOS。作者无法访问其原生 API 的源代码,因此你需要向他们报告问题。如果你在使用该插件时遇到问题,请查看我们的 已关闭和开放的问题。如果找不到任何能帮助你的内容,请报告问题并提供足够的细节。耐心等待,社区中的某人最终会帮助你。

示例

首先导入 package:apple_vision/apple_vision.dart

final GlobalKey cameraKey = GlobalKey(debugLabel: "cameraKey");
AppleVisionFaceController visionController = AppleVisionFaceController();
InsertCamera camera = InsertCamera();
String? deviceId;
bool loading = true;
Size imageSize = const Size(640, 640 * 9 / 16);

List<FaceData>? faceData;
late double deviceWidth;
late double deviceHeight;

[@override](/user/override)
void initState() {
  camera.setupCameras().then((value) {
    setState(() {
      loading = false;
    });
    camera.startLiveFeed((InputImage i) {
      if (i.metadata?.size != null) {
        imageSize = i.metadata!.size;
      }
      if (mounted) {
        Uint8List? image = i.bytes;
        visionController.processImage(image!, i.metadata!.size).then((data) {
          faceData = data;
          setState(() {});
        });
      }
    });
  });
  super.initState();
}

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

[@override](/user/override)
Widget build(BuildContext context) {
  deviceWidth = MediaQuery.of(context).size.width;
  deviceHeight = MediaQuery.of(context).size.height;
  return Stack(
    children: [
      SizedBox(
        width: imageSize.width,
        height: imageSize.height,
        child: loading ? Container() : CameraSetup(camera: camera, size: imageSize),
      ),
    ] + showPoints()
  );
}

List<Widget> showPoints() {
  if (faceData == null || faceData!.isEmpty) return [];
  List<Widget> widgets = [];
  Map<LandMark, Color> colors = {
    LandMark.faceContour: Colors.amber,
    LandMark.outerLips: Colors.red,
    LandMark.innerLips: Colors.pink,
    LandMark.leftEye: Colors.green,
    LandMark.rightEye: Colors.green,
    LandMark.leftPupil: Colors.purple,
    LandMark.rightPupil: Colors.purple,
    LandMark.leftEyebrow: Colors.lime,
    LandMark.rightEyebrow: Colors.lime,
  };

  for (int k = 0; k < faceData!.length; k++) {
    if (faceData![k].marks.isNotEmpty) {
      for (int i = 0; i < faceData![k].marks.length; i++) {
        List<FacePoint> points = faceData![k].marks[i].location;
        for (int j = 0; j < points.length; j++) {
          widgets.add(
            Positioned(
              left: points[j].x,
              top: points[j].y,
              child: Container(
                width: 10,
                height: 10,
                decoration: BoxDecoration(
                  color: colors[faceData![k].marks[i].landmark],
                  borderRadius: BorderRadius.circular(5)
                ),
              )
            )
          );
        }
      }
    }
  }
  return widgets;
}

Widget loadingWidget() {
  return Container(
    width: deviceWidth,
    height: deviceHeight,
    color: Theme.of(context).canvasColor,
    alignment: Alignment.center,
    child: const CircularProgressIndicator(color: Colors.blue)
  );
}

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

1 回复

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


当然,以下是一个关于如何在Flutter应用中使用apple_vision插件进行图像识别的代码示例。apple_vision插件主要用于iOS设备,它利用了Apple的Vision框架来实现图像识别功能。

首先,确保你已经在pubspec.yaml文件中添加了apple_vision依赖:

dependencies:
  flutter:
    sdk: flutter
  apple_vision: ^0.1.0  # 请注意版本号可能需要更新为最新版本

然后运行flutter pub get来安装依赖。

接下来,你可以按照以下步骤在Flutter应用中使用apple_vision进行图像识别:

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:apple_vision/apple_vision.dart';
import 'dart:typed_data';
import 'dart:ui' as ui;
  1. 定义图像识别功能
Future<void> recognizeImage(Uint8List imageBytes) async {
  try {
    // 将图像字节转换为CVPixelBuffer
    final pixelBuffer = await VisionUtils.imageToCvPixelBuffer(imageBytes);

    // 创建VNImageRequestHandler
    final requestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:]);

    // 定义要执行的请求,这里以检测矩形为例
    final requests = [
      VNDetectRectanglesRequest(completionHandler: (VNRequest request, NSError error) {
        if (error != null) {
          print('Error: ${error.localizedDescription}');
          return;
        }

        for (var observation in request.results!) {
          final rectObservation = observation as VNDetectedRectangleObservation;
          print('Detected Rectangle: ${rectObservation.boundingBox}');
        }
      })
    ];

    // 执行请求
    do {
      try {
        await requestHandler.perform(requests);
      } catch (e) {
        if (e is! NSError || (e as NSError).code != -1) { // -1 代表取消操作
          throw e;
        }
      }
    } while (requests.any((request) => !request.isCompleted));

  } catch (e) {
    print('Error recognizing image: $e');
  }
}
  1. 在UI中选择并处理图像
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageRecognitionPage(),
    );
  }
}

class ImageRecognitionPage extends StatefulWidget {
  @override
  _ImageRecognitionPageState createState() => _ImageRecognitionPageState();
}

class _ImageRecognitionPageState extends State<ImageRecognitionPage> {
  Uint8List? _imageBytes;

  Future<void> _pickImage() async {
    final pickedFile = await ImagePicker().pickImage(source: ImageSource.gallery);
    if (pickedFile != null) {
      final file = File(pickedFile.path);
      setState(() {
        _imageBytes = file.readAsBytesSync();
      });

      // 识别图像
      recognizeImage(_imageBytes!);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Image Recognition with apple_vision'),
      ),
      body: Center(
        child: _imageBytes == null
            ? Text('No image selected.')
            : Image.memory(_imageBytes!),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _pickImage,
        tooltip: 'Pick Image',
        child: Icon(Icons.add_a_photo),
      ),
    );
  }
}

注意:

  • 上述代码示例使用了image_picker插件来选择图像。你需要添加image_picker依赖到你的pubspec.yaml文件中。
  • 由于apple_vision是一个iOS专用的插件,因此这段代码在Android设备上不会运行。
  • 确保你的iOS项目已经正确配置了所有必要的权限和框架。

这个示例展示了如何使用apple_vision插件来检测图像中的矩形。你可以根据需要修改VNDetectRectanglesRequest为其他类型的请求,例如VNDetectFacesRequestVNDetectBarcodesRequest等,以实现不同的图像识别功能。

回到顶部