前言
最近在做一个考勤签到的系统,项目中需要人脸识别来做身份认证。这里来记录一下在react native中人脸检测模块的集成。
首先简单介绍一下项目中使用的到的库:
react-native-vision-camera:React Native Vision Camera 是一个用于构建 React Native 应用程序中与相机相关的功能的库。它提供了一种以高性能和可定制化的方式访问设备相机并捕获图像或视频的方法。该库是基于 iOS 和 Android 的本地相机 API 构建的,并为两个平台提供了统一的 API。它提供了各种功能,如实时图像处理、手动相机控制和自定义取景器叠加层。更多用例访问官网
Frame Processors:Frame Processors(帧处理器)是指对相机捕获的帧进行实时处理的功能模块。在 React Native Vision Camera中,可以使用 Frame Processors 来对相机捕获的帧进行自定义的处理。如:使用帧处理器将视频的每一帧中的人脸来进行检测。
vision-camera-face-detector:vision-camera-face-detector 是 React Native Vision Camera 库提供的一个人脸检测功能模块。它使用了 iOS 和 Android 平台的本地人脸检测算法,并提供了一个简单的 API,使开发人员可以轻松地在他们的应用程序中添加人脸检测功能。
集成步骤
1.安装react-native-vision-camera库
首先在项目中使用npm 或者yarn 安装react-native-vision-camera
1 2 3 4 5 6 7 8 9
| npm i react-native-vision-camera cd ios pod install
yarn add react-native-vision-camera cd ios pod install
|
若要使用相机或麦克风,必须首先指定应用需要相机和麦克风权限。
苹果需要Info.plist
文件<dict>
标签中添加以下代码打开相机和麦克风权限,Info.plist
在~/ios/ios项目名称/Info.plist
目录
1 2 3 4 5 6 7
| <key>NSCameraUsageDescription</key> <string>$(PRODUCT_NAME) needs access to your Camera.</string>
<key>NSMicrophoneUsageDescription</key> <string>$(PRODUCT_NAME) needs access to your Microphone.</string>
|
安卓需要在AndroidManifest.xml
文件<manifest>
标签中添加以下代码
1 2
| <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
|
下面是一个react-native-vision-camera库的简单示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import { useCameraDevices, Camera} from 'react-native-vision-camera'; import * as React from 'react'; import {useRef} from 'react'; export function FaceRecognitionPunch(props) { const camara=useRef(null) const devices = useCameraDevices(); const device = devices.front; return device != null && ( <Camera ref={camara} //绑定ref device={device} //绑定设备 isActive={true} photo={true} //打开相机功能 frameProcessorFps={'auto'} /> ) ;
}
|
2.使用Frame Processors帧处理器需要安装react-native-reanimated库
1 2 3 4
| yarn add react-native-reanimated cd ios pod install
|
3.安装vision-camera-face-detector人脸检测模块
1 2 3 4
| yarn add vision-camera-face-detector cd ios pod install
|
vision-camera-face-detector 提供了一个名为 useFaceDetector
的钩子,可以用于启用人脸检测功能。当使用 useFaceDetector
钩子启用人脸检测时,每次相机捕获到一帧画面时,该功能模块会自动检测画面中的人脸,并返回一个包含人脸信息的数组。具体使用示例看下面的完整代码
完整示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| import * as React from 'react'; import {runOnJS} from 'react-native-reanimated'; import { Platform} from 'react-native'; import { useCameraDevices, useFrameProcessor, Camera} from 'react-native-vision-camera'; import {scanFaces, Face} from 'vision-camera-face-detector'; import {useRef} from 'react';
export function FaceRecognitionPunch(props) { const [hasPermission, setHasPermission] = React.useState(false); const [faces, setFaces] = React.useState([]); const [msg, setMsg] = React.useState(null); const [isActiveVal, setIsActiveVal] = React.useState(true); const camara=useRef(null) const devices = useCameraDevices(); const device = devices.front;
React.useEffect( () => { let facesArr = []; facesArr = faces; if (facesArr.length > 0) { let face = facesArr[0]; if (JSON.stringify(face.contours) == '{}') { setMsg('人脸信息不全'); } else { if (face.leftEyeOpenProbability == 1 && face.rightEyeOpenProbability == 1 && face.pitchAngle == 0 && face.rollAngle == 0) { setMsg('面部遮挡'); } else { if (face.leftEyeOpenProbability < 0.8 && face.rightEyeOpenProbability < 0.8) { setMsg('请睁眼'); } else { if (!(Math.abs(face.pitchAngle) < 6 && Math.abs(face.rollAngle) < 6 && Math.abs(face.yawAngle) <= 6)) { setMsg('请正面朝向屏幕'); } else { setIsActiveVal(false); takePicture().then(res=>{ console.log('成功',res) }).catch()
} } } } } }, [faces]);
React.useEffect(() => { (async () => { const status = await Camera.requestCameraPermission(); setHasPermission(status === 'authorized'); })(); }, []);
const frameProcessor = useFrameProcessor((frame) => { 'worklet'; const scannedFaces = scanFaces(frame); runOnJS(setFaces)(scannedFaces); }, []);
const takePicture=async ()=>{ if (camara.current) { let photo = null; if (Platform.OS === 'ios') { photo = await camara.current.takePhoto({ qualityPrioritization: 'speed', flash: 'off', enableAutoRedEyeReduction: true, }); } else { photo = await camara.current.takeSnapshot({ quality: 80, skipMetadata: true, }); } let path = photo.path; } } return device != null && hasPermission ? ( <Camera ref={camara} device={device} isActive={isActiveVal} photo={true} frameProcessor={frameProcessor} frameProcessorFps={'auto'} /> ) : null; }
|
效果图展示
1.人脸信息不全显示效果
2.非正面朝向屏幕显示效果
3.闭眼显示效果
4.上传成功显示效果
5.面部遮挡显示效果