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

如何在Expo Camera React Native中集成人脸检测,实现仅人脸可拍照?

实现Expo Camera人脸检测控制拍照功能

步骤1:安装依赖

首先安装Expo人脸检测包:

npx expo install expo-face-detector

步骤2:配置权限

在项目的app.json中添加相机和人脸检测权限:

{
  "expo": {
    "permissions": [
      "CAMERA",
      "FACE_DETECTION"
    ],
    "ios": {
      "infoPlist": {
        "NSCameraUsageDescription": "需要访问相机进行拍照和人脸检测",
        "NSFaceIDUsageDescription": "需要使用人脸检测功能"
      }
    },
    "android": {
      "permissions": [
        "android.permission.CAMERA",
        "com.google.android.gms.permission.FACE_DETECTION"
      ]
    }
  }
}

步骤3:修改组件代码

下面是集成人脸检测后的完整代码,关键修改点已标注:

import { Camera } from 'expo-camera';
import { TouchableOpacity, Text, View, Alert } from 'react-native';
import { useState, useEffect, useRef } from "react";
import { firebase } from '../../Storage/Firebase/config';
// 导入FaceDetector模块
import * as FaceDetector from 'expo-face-detector';

export default function CameraPage({ navigation }) {

  const [hasPermission, setHasPermission] = useState(null);
  const [type, setType] = useState(Camera.Constants.Type.front);
  const cameraRef = useRef(null);
  // 新增状态:标记是否检测到人脸
  const [isFaceDetected, setIsFaceDetected] = useState(false);

  useEffect(() => {
    (async () => {
      // 请求相机权限(人脸检测依赖相机权限)
      const { status } = await Camera.requestCameraPermissionsAsync();
      setHasPermission(status === 'granted');
    })();
  }, []);

  if (hasPermission === null) {
    return <View />;
  }

  if (hasPermission === false) {
    return <Text>No access to camera</Text>;
  }

  // 人脸检测结果回调
  const handleFacesDetected = ({ faces }) => {
    // 检测到至少一张人脸则更新状态
    setIsFaceDetected(faces.length > 0);
  };

  // 人脸检测错误处理
  const handleFaceDetectionError = (error) => {
    console.error('人脸检测出错:', error);
  };

  const handleTakePicture = async () => {
    // 拍照前校验是否检测到人脸
    if (!isFaceDetected) {
      Alert.alert('提示', '未检测到人脸,请对准后再拍照');
      return;
    }

    if (cameraRef.current) {
      const photo = await cameraRef.current.takePictureAsync();

      if (!photo.cancelled) {
        const response = await fetch(photo.uri);
        const blob = await response.blob();
        const filename = photo.uri.substring(photo.uri.lastIndexOf('/') + 1);
        const ref = firebase.storage().ref().child(filename);
        const snapshot = await ref.put(blob);
        const url = await snapshot.ref.getDownloadURL();
        console.log(url)
        navigation.navigate('addpost', { post: url });
      }
    }
  }

  return (
    <View style={{ flex: 1 }}>
      {/* 给Camera组件绑定人脸检测相关属性 */}
      <Camera
        style={{ flex: 1 }}
        type={type}
        ref={cameraRef}
        onFacesDetected={handleFacesDetected}
        onFacesDetectionError={handleFaceDetectionError}
        faceDetectorSettings={{
          // 配置检测参数:快速模式、不检测特征点、不做分类
          mode: FaceDetector.FaceDetectorMode.fast,
          detectLandmarks: FaceDetector.FaceDetectorLandmarks.none,
          runClassifications: FaceDetector.FaceDetectorClassifications.none,
          minDetectionInterval: 100,
          tracking: true,
        }}
      >
        <View style={{ flex: 1, backgroundColor: 'transparent', flexDirection: 'row' }}>
          {/* 根据人脸检测状态调整按钮样式 */}
          <TouchableOpacity
            style={{
              alignSelf: 'center',
              alignItems: 'center',
              width: 90,
              height: 90,
              borderRadius: 500,
              backgroundColor: isFaceDetected ? 'rgba(255,255,255,0.3)' : 'rgba(255,255,255,0.1)',
              marginTop: '150%',
              marginLeft: '35%',
              borderColor: isFaceDetected ? '#4CAF50' : '#fff',
              borderWidth: 4,
            }}
            onPress={handleTakePicture}
            // 可选:未检测到人脸时禁用按钮
            disabled={!isFaceDetected}
          >
            <View style={{ opacity: 0.5, }} />
          </TouchableOpacity>
        </View>
        {/* 可选:添加顶部状态提示文本 */}
        <View style={{ position: 'absolute', top: 50, alignSelf: 'center' }}>
          <Text style={{ color: isFaceDetected ? 'green' : 'red', fontSize: 18, fontWeight: 'bold' }}>
            {isFaceDetected ? '已检测到人脸' : '未检测到人脸'}
          </Text>
        </View>
      </Camera>
    </View>
  );
}

关键说明

  • 检测参数配置:faceDetectorSettings里的fast模式适合实时检测,兼顾性能和准确性;如果需要更高精度可以换成accurate模式。
  • 状态联动:isFaceDetected状态实时同步检测结果,用来控制拍照按钮的可用性、样式,同时作为拍照的前置校验条件。
  • 用户反馈:通过Alert弹窗、按钮样式变化、顶部文本三种方式,给用户清晰的检测状态反馈。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:15:31