如何使用react-native-camera实现实时姿态检测?
摄像头帧提取优化及姿态检测实现方案
你现有通过takePictureAsync拍照获取图像的方式只适合单帧静态检测,如需实现低延迟的实时姿态处理,最优方案是直接获取摄像头实时预览帧,无需触发拍照逻辑,具体实现如下:
1 基于现有react-native-camera的实时帧获取方案
react-native-camera本身提供预览帧回调能力,无需调用拍照接口即可逐帧获取摄像头数据,延迟比拍照方案低80%以上,适配实时模型推理需求:
- 在
RNCamera组件上开启onFrameReceived回调,同时设置captureMode="video"、captureAudio={false}关闭音频采集减少性能消耗 - 可通过
frameRate属性设置回调帧率,建议匹配posenet的推理速度,一般15~30fps即可满足姿态检测需求 - 可通过
ratio属性控制帧分辨率,建议最高设置为1280*720,过高的分辨率会大幅增加推理耗时
2 完整实现逻辑梳理
步骤1:配置RNCamera组件
修改原有RNCamera配置,新增帧回调相关属性:
<RNCamera ref={cameraRef} style={cameraStyle as ViewStyle} type={RNCamera.Constants.Type.back} flashMode={RNCamera.Constants.FlashMode.auto} // 新增帧回调配置 captureMode="video" captureAudio={false} frameRate={20} ratio="4:3" onFrameReceived={handleFrame} />
步骤2:帧数据预处理适配posenet输入
回调拿到的帧数据为YUV格式的原始二进制数据,需预处理后喂给posenet:
const handleFrame = async (frame) => { // frame参数包含width、height、data属性,data为YUV格式Uint8Array // 1. 转换为posenet要求的RGB格式Tensor const inputTensor = tf.tensor3d(frame.data, [frame.height, frame.width, 3], 'uint8') // 2. resize到posenet默认输入尺寸257*257,可根据模型版本调整 const resizedTensor = tf.image.resizeBilinear(inputTensor, [257, 257]) // 3. 传入posenet推理 const poseResult = await posenet.estimateSinglePose(resizedTensor, { flipHorizontal: false }) // 4. 执行Canvas绘制逻辑 renderPoseToCanvas(poseResult, frame.width, frame.height) // 释放Tensor内存,避免内存泄漏 inputTensor.dispose() resizedTensor.dispose() }
步骤3:姿态结果映射绘制到Canvas
由于摄像头帧分辨率和Canvas组件的实际尺寸不一致,需要先做坐标映射再绘制:
- 计算帧宽高和Canvas宽高的缩放比,将poseResult中每个关键点的x、y坐标乘以对应缩放比
- 先在Canvas上绘制当前摄像头帧作为背景,再绘制关键点和骨骼连线即可
3 性能优化建议
- 推理逻辑不要放在UI线程执行,避免阻塞Canvas绘制导致掉帧
- 若react-native-camera的帧回调性能无法满足需求,可替换为react-native-vision-camera,其原生帧处理能力更强,延迟更低
- 不需要实时检测的场景可设置帧回调间隔,比如每3帧处理一次,降低设备性能消耗
内容的提问来源于stack exchange,提问作者Vishesh Tayal
相关产品推荐
相关产品推荐

