You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何实现人脸检测时自动触发拍照功能?

实现人脸检测自动触发拍照

核心思路

在相机预览的每一帧图像中执行人脸检测,当检测到人脸时自动调用takePicture方法,同时添加防重复触发逻辑避免连续拍照。

具体实现步骤

  • 初始化相机并开启预览帧监听,对每一帧图像进行人脸检测
  • 将camera插件返回的CameraImage转换为google_ml_kit兼容的InputImage格式
  • 检测到人脸后标记拍摄状态,调用拍照方法,可选停止图像流或设置间隔时间重新允许拍照

完整代码示例

import 'dart:async';
import 'package:camera/camera.dart';
import 'package:google_ml_kit/google_ml_kit.dart';
import 'package:flutter/material.dart';

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

  @override
  State<FaceAutoCapturePage> createState() => _FaceAutoCapturePageState();
}

class _FaceAutoCapturePageState extends State<FaceAutoCapturePage> {
  late CameraController _cameraController;
  bool _isPictureTaken = false;
  bool _isAlreadyCaptured = false; // 防重复拍照标记
  final FaceDetectorService _faceDetectorService = FaceDetectorService();

  @override
  void initState() {
    super.initState();
    _initCamera();
  }

  Future<void> _initCamera() async {
    // 获取前置相机
    final cameras = await availableCameras();
    final frontCamera = cameras.firstWhere(
      (camera) => camera.lensDirection == CameraLensDirection.front,
    );

    // 初始化相机控制器
    _cameraController = CameraController(
      frontCamera,
      ResolutionPreset.medium,
      enableAudio: false,
    );

    await _cameraController.initialize();

    // 监听预览帧,处理人脸检测
    _cameraController.startImageStream((CameraImage image) async {
      if (_isAlreadyCaptured || _isPictureTaken) return;

      // 转换图像格式为人脸检测器可处理的类型
      final inputImage = _convertCameraImageToInputImage(image);

      // 执行人脸检测
      final faces = await _faceDetectorService.faceDetector.processImage(inputImage);

      if (faces.isNotEmpty) {
        _faceDetectorService.faceDetected = true;
        await takePicture();
        _isAlreadyCaptured = true;

        // 如需间隔一段时间后允许再次拍照,取消下方注释
        // Timer(const Duration(seconds: 5), () {
        //   setState(() {
        //     _isAlreadyCaptured = false;
        //     _isPictureTaken = false;
        //   });
        // });
      } else {
        _faceDetectorService.faceDetected = false;
      }
    });
  }

  // 转换CameraImage为InputImage格式
  InputImage _convertCameraImageToInputImage(CameraImage image) {
    final inputImageFormat = InputImageFormatValue.fromRawValue(image.format.raw);
    final planeData = image.planes.map(
      (Plane plane) => InputImagePlaneMetadata(
        bytesPerRow: plane.bytesPerRow,
        height: plane.height,
        width: plane.width,
      ),
    ).toList();

    return InputImage.fromBytes(
      bytes: image.planes.first.bytes,
      metadata: InputImageMetadata(
        size: Size(image.width.toDouble(), image.height.toDouble()),
        // 根据相机方向调整旋转角度,前置相机通常设为90度
        rotation: InputImageRotationValue.fromRawValue(90)!,
        format: inputImageFormat!,
        planeData: planeData,
      ),
    );
  }

  Future<void> takePicture() async {
    if (_faceDetectorService.faceDetected) {
      try {
        await _cameraController.takePicture(); // 若使用自定义_cameraService,替换为对应方法
        setState(() => _isPictureTaken = true);
        // 拍照完成后停止图像流,避免持续检测
        await _cameraController.stopImageStream();
      } catch (e) {
        print('拍照失败: $e');
      }
    }
  }

  @override
  void dispose() {
    _cameraController.dispose();
    _faceDetectorService.faceDetector.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _isPictureTaken
          ? const Center(child: Text('照片已拍摄'))
          : CameraPreview(_cameraController),
    );
  }
}

// 人脸检测服务类示例
class FaceDetectorService {
  final FaceDetector faceDetector = FaceDetector(
    options: FaceDetectorOptions(
      enableContours: false,
      enableClassification: false,
    ),
  );
  bool faceDetected = false;
}

注意事项

  • 图像旋转角度:根据使用的相机(前置/后置)调整InputImageRotation的值,否则可能导致人脸检测失效
  • 资源释放:页面销毁时必须关闭人脸检测器和相机控制器,防止内存泄漏
  • 防重复触发:通过_isAlreadyCaptured变量避免短时间内连续拍照,可根据需求调整间隔时长

内容的提问来源于stack exchange,提问作者hafeezrana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 19:33:37