Flutter媒体处理与AI集成插件mediapipe_genai的使用

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

Flutter媒体处理与AI集成插件mediapipe_genai的使用

pub package

一个用于在Flutter中使用MediaPipe GenAI API的插件,包含多个基于生成式AI的MediaPipe任务。

要了解更多关于MediaPipe的信息,请访问 MediaPipe网站

开始使用

要开始使用MediaPipe,请参阅 文档

支持的任务

任务 Android iOS Web Windows macOS Linux
推理

选择设备

离线推理是一项资源密集型任务,建议在Pixel 7或更新的设备(或其他类似的Android设备)上运行。对于iOS设备,建议使用iPhone 13或更新的设备。

移动仿真器不被支持。

对于桌面端,macOS被支持,Windows和Linux将在不久的将来支持。

使用方法

要开始使用此插件,您必须处于 master 通道。

其次,您需要启用 native-assets 实验,使用 --enable-experiment=native-assets 标志运行任何使用 $ dart 命令行工具的命令。

要在Flutter中全局启用此功能,请运行:

$ flutter config --enable-native-assets

要在Flutter中全局禁用此功能,请运行:

$ flutter config --no-enable-native-assets

添加依赖

在您的 pubspec.yaml 文件中添加 mediapipe_coremediapipe_genai 依赖:

dependencies:
  flutter:
    sdk: flutter
  mediapipe_core: latest
  mediapipe_genai: latest

添加tflite模型

与MediaPipe的其他任务风味(文本、视觉和音频)不同,生成式AI模型必须在运行时从开发者托管的URL下载。为了获取这些模型,您需要创建一个 Kaggle 账户,接受服务条款,下载您想在应用中使用的模型,并自行托管这些模型在您选择的位置,然后配置您的应用以在运行时下载它们。

查看示例目录以获得一个实现示例和指导,了解如何使MediaPipe的推理任务工作。

CPU与GPU模型

推理任务可以在CPU或GPU上运行,每个模型都为每种策略编译一次。当您从Kaggle选择要使用的模型时,请注意其CPU和GPU变体,并确保调用适当的选项构造函数。

初始化引擎

推理示例:

import 'package:mediapipe_genai/mediapipe_genai.dart';

// 您在运行时下载文件的位置,或者提前将模型放置在自己的位置(使用`adb push`等)
final String modelPath = getModelPath();

// 根据您的模型选择CPU或GPU运行时
// 查看示例以获取传递给`LlmInferenceOptions`类其余参数的合适值。
bool isGpu = yourValueHere;
final options = switch (isGpu) {
  true => LlmInferenceOptions.gpu(
    modelPath: modelPath,
    // 其他参数...
  ),
  false => LlmInferenceOptions.cpu(
    modelPath: modelPath,
    // 其他参数...
  ),
};

// 创建推理引擎
final engine = LlmInferenceEngine(options);

// 流式处理引擎结果
final Stream<String> responseStream = engine.generateResponse('Hello, world!');
await for (final String responseChunk in responseStream) {
  print('The LLM said: $responseChunk');
}

问题和反馈

请在我们的 问题跟踪器 中提交与Flutter-MediaPipe相关的错误、问题或功能请求。

与Flutter相关的问题可以提交到 Flutter问题跟踪器

要为该插件贡献更改,请参阅我们的 贡献指南,并打开一个 拉取请求


示例代码

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:logging/logging.dart';
import 'llm_inference_demo.dart';
import 'logging.dart';

/// {[@template](/user/template) AppBlocObserver}
/// 记录所有与`pkg:flutter_bloc`相关的事项。
/// {[@endtemplate](/user/endtemplate)}
class AppBlocObserver extends BlocObserver {
  /// {[@macro](/user/macro) AppBlocObserver}
  const AppBlocObserver();

  static final _log = Logger('AppBlocObserver');

  [@override](/user/override)
  void onChange(BlocBase<dynamic> bloc, Change<dynamic> change) {
    _log.finest('onChange(${bloc.runtimeType}, $change)');
    super.onChange(bloc, change);
  }

  [@override](/user/override)
  void onEvent(Bloc<dynamic, dynamic> bloc, Object? event) {
    _log.finest('onEvent($event)');
    super.onEvent(bloc, event);
  }

  [@override](/user/override)
  void onError(BlocBase<dynamic> bloc, Object error, StackTrace stackTrace) {
    _log.shout('onError(${bloc.runtimeType}, $error, $stackTrace)');
    super.onError(bloc, error, stackTrace);
  }
}

void main() {
  initLogging();
  Bloc.observer = const AppBlocObserver();
  runApp(
    const MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate, // 这是必需的
      ],
      home: MainApp(),
    ),
  );
}

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

  [@override](/user/override)
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  final PageController controller = PageController();

  final titles = <String>['推理'];
  int titleIndex = 0;

  [@override](/user/override)
  void initState() {
    controller.addListener(() {
      final newIndex = controller.page?.toInt();
      if (newIndex != null && newIndex != titleIndex) {
        setState(() {
          titleIndex = newIndex;
        });
      }
    });
    super.initState();
  }

  void switchToPage(int index) {
    controller.animateToPage(
      index,
      duration: const Duration(milliseconds: 200),
      curve: Curves.easeOut,
    );
    setState(() {
      titleIndex = index;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        controller: controller,
        children: const <Widget>[
          LlmInferenceDemo(),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: titleIndex,
        onTap: switchToPage,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.chat_bubble),
            activeIcon: Icon(Icons.chat_bubble, color: Colors.blue),
            label: '推理',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.cancel),
            activeIcon: Icon(Icons.cancel, color: Colors.blue),
            label: '即将推出',
          ),
        ],
      ),
    );
  }
}

更多关于Flutter媒体处理与AI集成插件mediapipe_genai的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter媒体处理与AI集成插件mediapipe_genai的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用mediapipe_genai插件进行媒体处理与AI集成的代码示例。这个插件可以帮助你利用MediaPipe和Google的AI模型进行实时媒体处理。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加mediapipe_genai依赖:

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

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

2. 配置权限

AndroidManifest.xml中配置相机和麦克风权限(如果需要使用这些功能):

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

3. 初始化插件

在你的Flutter项目的Dart代码中,初始化mediapipe_genai插件。这里是一个简单的例子,展示如何使用插件进行实时面部检测:

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

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

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

class FaceDetectionScreen extends StatefulWidget {
  @override
  _FaceDetectionScreenState createState() => _FaceDetectionScreenState();
}

class _FaceDetectionScreenState extends State<FaceDetectionScreen> {
  late MediaPipeGenaiPlugin mediapipeGenai;

  @override
  void initState() {
    super.initState();
    mediapipeGenai = MediaPipeGenaiPlugin();
    // 初始化MediaPipe模型,这里以面部检测为例
    mediapipeGenai.initialize(model: 'face_detection');
    mediapipeGenai.startCamera();
    mediapipeGenai.addListener(() {
      setState(() {});  // 更新UI以显示检测结果
    });
  }

  @override
  void dispose() {
    mediapipeGenai.stopCamera();
    mediapipeGenai.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Face Detection with MediaPipe and AI'),
      ),
      body: Center(
        child: mediapipeGenai.frame != null
            ? CustomPaint(
                size: Size(mediapipeGenai.frame!.width.toDouble(), mediapipeGenai.frame!.height.toDouble()),
                painter: FacePainter(mediapipeGenai.results!))
            : CircularProgressIndicator(),
      ),
    );
  }
}

class FacePainter extends CustomPainter {
  final List<dynamic> results;
  final Uint8List? frame;

  FacePainter(this.results, {this.frame}) {
    // 你可以在这里处理frame和results,进行绘制
  }

  @override
  void paint(Canvas canvas, Size size) {
    // 绘制逻辑,比如根据results中的面部检测数据在frame上绘制矩形框
    final Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 4.0;

    results.forEach((result) {
      final Rect rect = Rect.fromLTWH(
        result['x']! - result['width']! / 2,
        result['y']! - result['height']! / 2,
        result['width']!,
        result['height']!,
      );
      canvas.drawRect(rect, paint);
    });
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;  // 每当状态改变时重绘
  }
}

注意事项

  1. 权限处理:在实际应用中,你需要处理权限请求,确保用户在使用前已授予必要的权限。
  2. 错误处理:添加错误处理逻辑,以应对初始化失败、相机不可用等情况。
  3. 性能优化:在实际项目中,你可能需要优化绘制逻辑,以提高性能和用户体验。

这个示例展示了如何在Flutter中使用mediapipe_genai插件进行基本的面部检测。你可以根据需求扩展此代码,以处理其他类型的媒体和AI任务。

回到顶部