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

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_core 和 mediapipe_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任务。

回到顶部