如何在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
相关产品推荐
相关产品推荐

