Flutter 实现人脸检测 — 使用 google_mlkit_face_detection

📖 一、前言

在很多 App 中,我们会需要检测人脸,例如:

  • 拍照前检测是否有脸;
  • 分析表情、判断是否微笑;
  • 做人脸识别前的预处理;
  • 视频或相机实时检测。

Google 的 ML Kit 提供了强大的人脸检测(Face Detection)能力,而 Flutter 社区封装了一个插件

👉 google_mlkit_face_detection

本文将带你完整了解并使用 google_mlkit_face_detection: ^0.13.1 来实现:

  • 本地图片人脸检测;
  • 实时检测思路;
  • 常见问题与优化建议。

⚙️ 二、环境与依赖配置

  1. 添加依赖

在项目的 pubspec.yaml 文件中添加:

yaml 复制代码
dependencies:
  flutter:
    sdk: flutter
  google_mlkit_face_detection: ^0.13.1
  image_picker: ^1.2.0   # 用于选择图片

执行:

yaml 复制代码
flutter pub get

  1. Android 配置

✅ 修改 Gradle 配置

在 android/app/build.gradle 中:

groovy 复制代码
android {
    compileSdkVersion 35
    defaultConfig {
        minSdkVersion 21
    }
}

✅ 添加权限

在 android/app/src/main/AndroidManifest.xml 中:

xml 复制代码
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

  1. iOS 配置

✅ 修改 Podfile

最低支持版本应为:

platform :ios, '15.5'

✅ 添加相机 / 相册权限说明

在 ios/Runner/Info.plist 中:

xml 复制代码
<key>NSCameraUsageDescription</key>
<string>用于检测人脸</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>用于选择人脸图片</string>

🧠 三、插件原理简介

google_mlkit_face_detection 的底层并不是 Dart 自己检测人脸,而是通过 平台通道 (Platform Channel) 调用 Android / iOS 的原生 ML Kit。

工作流程:

matlab 复制代码
Flutter (Dart)
   ↓  Platform Channel
Native (Android / iOS)
   ↓  调用 Google ML Kit
   ↓  返回检测结果
Flutter 绘制 UI

这种方式的好处是:

  • 检测在设备端执行,速度快;
  • 无需联网;
  • 精度高、稳定性好。

💡 四、FaceDetectorOptions 参数说明

dart 复制代码
final options = FaceDetectorOptions(
  enableContours: true,      // 是否检测人脸轮廓(眼睛、嘴唇等)
  enableLandmarks: true,     // 是否检测关键点(眼睛、鼻尖、耳朵等)
  enableClassification: true,// 是否识别表情(如微笑、闭眼)
  performanceMode: FaceDetectorMode.accurate, // 准确模式(相对较慢)
  minFaceSize: 0.1,          // 最小人脸占图片比例
);

这些参数的取舍决定性能与检测精度的平衡。


🧩 五、完整示例:检测图片中的人脸

以下是一个完整的 Flutter 示例页面:

dart 复制代码
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:google_mlkit_face_detection/google_mlkit_face_detection.dart';
import 'package:image_picker/image_picker.dart';

class FaceDetectionPage extends StatefulWidget {
  @override
  _FaceDetectionPageState createState() => _FaceDetectionPageState();
}

class _FaceDetectionPageState extends State<FaceDetectionPage> {
  File? _image;
  List<Face>? _faces;
  late FaceDetector _faceDetector;
  bool _busy = false;

  @override
  void initState() {
    super.initState();
    final options = FaceDetectorOptions(
      enableContours: true,
      enableLandmarks: true,
      enableClassification: true,
      performanceMode: FaceDetectorMode.accurate,
    );
    _faceDetector = FaceDetector(options: options);
  }

  @override
  void dispose() {
    _faceDetector.close();
    super.dispose();
  }

  Future<void> _pickAndDetect() async {
    final picker = ImagePicker();
    final XFile? file = await picker.pickImage(source: ImageSource.gallery);
    if (file == null) return;

    setState(() {
      _busy = true;
      _image = File(file.path);
      _faces = null;
    });

    final inputImage = InputImage.fromFile(_image!);
    try {
      final faces = await _faceDetector.processImage(inputImage);
      setState(() => _faces = faces);
    } catch (e) {
      print('检测失败: $e');
    } finally {
      setState(() => _busy = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('人脸检测 Demo')),
      body: Center(
        child: _busy
            ? CircularProgressIndicator()
            : Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  if (_image != null)
                    SizedBox(
                      width: 300,
                      height: 300,
                      child: Stack(
                        fit: StackFit.expand,
                        children: [
                          Image.file(_image!, fit: BoxFit.cover),
                          if (_faces != null)
                            CustomPaint(painter: FacePainter(_faces!)),
                        ],
                      ),
                    ),
                  const SizedBox(height: 20),
                  ElevatedButton(
                    onPressed: _pickAndDetect,
                    child: Text('选择图片并检测'),
                  ),
                  const SizedBox(height: 10),
                  Text(_faces == null
                      ? '未检测'
                      : '检测到 ${_faces!.length} 张人脸'),
                ],
              ),
      ),
    );
  }
}

class FacePainter extends CustomPainter {
  final List<Face> faces;
  FacePainter(this.faces);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3
      ..color = Colors.red;

    for (var face in faces) {
      canvas.drawRect(face.boundingBox, paint);
    }
  }

  @override
  bool shouldRepaint(covariant FacePainter oldDelegate) =>
      oldDelegate.faces != faces;
}

🖼️ 运行效果

  • 选择一张图片后,插件会检测其中的人脸;
  • 检测到的人脸区域会用红框标出;
  • 下方会显示检测到的人脸数量。

🎥 六、实时检测思路(Camera)

想实现类似抖音那样的实时检测,需要结合 camera 插件:

  1. 启动摄像头;
  2. 调用 controller.startImageStream();
  3. 每隔几帧或每 200ms 调用一次人脸检测;
  4. 使用 InputImage.fromBytes() 转换图像流;
  5. 在界面上叠加绘制检测框。

⚠️ 注意:

  • 每帧检测会非常耗时;
  • 建议降低帧率或检测频率;
  • 处理时要注意图像旋转、镜像、比例。

🧱 七、常见问题与解决方案

问题 可能原因 解决办法
iOS检测不到前置人脸 图像镜像 / 旋转角度错误 预处理图像方向或使用后置摄像头测试
Android 报错 removeFirst 底层依赖冲突 升级 Gradle 与 Kotlin,清理缓存
实时检测卡顿 每帧都处理 设定检测间隔、关闭部分检测功能
检测不准确 模型限制 调整 minFaceSize 或开启 accurate 模式
资源未释放 未调用 close() 页面销毁时调用 _faceDetector.close()

⚡ 八、性能优化建议

目标 建议
提高帧率 每隔 N 帧检测一次
提高精度 使用 FaceDetectorMode.accurate
降低功耗 关闭不必要的检测项
减少误检 对 boundingBox 做过滤
稳定输出 对检测结果做平滑处理

🧭 九、总结

通过 google_mlkit_face_detection: ^0.13.1,我们可以:

✅ 快速实现本地人脸检测

✅ 离线检测、响应迅速

✅ 支持检测人脸框、关键点、表情等信息

但要注意:

  • 插件依赖底层 ML Kit,不支持 Web;
  • Android/iOS 环境需正确配置;
  • 实时检测需做好性能优化。

🚀 十、后续方向

后续可以结合以下方向拓展:

  • 使用 camera 实现实时检测;
  • 将检测结果与 TensorFlow Lite 人脸识别模型结合;
  • 在检测到人脸时自动拍照或触发动画效果;
  • 实现人脸表情识别与情绪分析。

🧩 参考资料

  • google_mlkit_face_detection 官方文档
  • Google ML Kit 官方文档
  • Flutter camera 插件
相关推荐
西西学代码4 小时前
Flutter---默认程序(计数器)
flutter
君逸臣劳4 小时前
玩Android Flutter版本,通过项目了解Flutter项目快速搭建开发
android·flutter
叫我龙翔5 小时前
【MySQL】从零开始了解数据库开发 --- 基本查询
android·mysql·数据库开发
2501_916008895 小时前
iOS 26 性能分析深度指南 包含帧率、渲染、资源瓶颈与 KeyMob 协助策略
android·macos·ios·小程序·uni-app·cocoa·iphone
撩得Android一次心动7 小时前
Android adb 基础使用指南
android·adb
为java加瓦7 小时前
PHP MQTT 订阅服务:实时消息接收与数据库存储解决方案
android
怿星科技7 小时前
Android MVVM架构解析:现代开发的首选模式
android·架构
安卓机器7 小时前
安卓13_ROM修改定制化-----ROM解打包 修改 讲解 导读篇
android·安卓13固件修改·安卓13rom修改
钱塘天梭7 小时前
记录一次排查Android App启动时偶现卡顿问题的过程
android