import CameraPermissionWrapper from './components/CameraPermissionWrapper';
import { useRef, useState } from 'react';
import { View, Text } from 'react-native';
import { Worklets } from 'react-native-worklets-core';
import { NitroModules } from 'react-native-nitro-modules';
import {
BoxedInspireFace,
CameraRotation,
DetectMode,
InspireFace,
} from 'react-native-nitro-inspire-face';
import { useResizePlugin } from 'vision-camera-resize-plugin';
import {
Camera,
Templates,
useCameraDevice,
useCameraFormat,
useFrameProcessor,
VisionCameraProxy,
Frame,
runAtTargetFps,
} from 'react-native-vision-camera';
InspireFace.launch('Pikachu');
//let plugin = VisionCameraProxy.initFrameProcessorPlugin('detectFaces');
/*export function detectFaces(frame: Frame): object {
'worklet';
if (plugin == null)
throw new Error('Failed to load Frame Processor Plugin "scanFaces"!');
return plugin.call(frame);
}*/
export default function App() {
let device = useCameraDevice('back');
const camera = useRef<Camera>(null);
const [faceConfidence, setFaceConfidence] = useState<number | null>(null);
const [faceQuality, setFaceQuality] = useState<number | null>(null);
const [faceCount, setFaceCount] = useState<number | null>(null);
const format = useCameraFormat(device, Templates.FrameProcessing);
const { resize } = useResizePlugin();
const featureCache = useRef<ArrayBuffer[]>([]);
// 创建 Worklet 兼容的更新函数
const updateResult = Worklets.createRunOnJS(
(confidence: number, quality: number, count: number) => {
setFaceConfidence(confidence);
setFaceQuality(quality);
setFaceCount(count);
});
// Worklet 专用配置
const frameProcessor = useFrameProcessor((frame) => {
'worklet';
runAtTargetFps(1, () => {
'worklet';
const size = 320;
// Resize frame for processing
const resized = resize(frame, {
scale: {
width: size,
height: size,
},
rotation: '90deg',
pixelFormat: 'bgr',
dataType: 'uint8',
mirror: true,
});
// Unbox InspireFace instance for frame processor
const unboxedInspireFace = BoxedInspireFace.unbox();
// Create image bitmap from frame buffer
const bitmap = unboxedInspireFace.createImageBitmapFromBuffer(
resized.buffer as ArrayBuffer,
size,
size,
3
);
// Create image stream for face detection
const imageStream = unboxedInspireFace.createImageStreamFromBitmap(
bitmap,
CameraRotation.ROTATION_0
);
// Detect faces
let unboxedSession = unboxedInspireFace.createSession(
{
enableRecognition: true,
enableFaceQuality: true,
},
DetectMode.ALWAYS_DETECT,
10,
-1, // Detection resolution level (multiple of 160, e.g., 160, 320, 640; default -1 means 320)
-1 // Frame rate for tracking mode (default -1 means 30fps)
);
unboxedSession.setTrackPreviewSize(320); //Default 192
unboxedSession.setFaceDetectThreshold(0.7);
unboxedSession.setFilterMinimumFacePixelSize(0); //Default 0
const multipleFaceData = unboxedSession.executeFaceTrack(imageStream);
// ✅ 获取质量评分(必须在 executeFaceTrack 后调用)
const qualityScores = unboxedSession.getFaceQualityConfidence();
if (
multipleFaceData.length > 0 &&
multipleFaceData[0] &&
qualityScores.length > 0 &&
qualityScores[0]
) {
// ✅ 获取检测置信度和质量评分
const detectionConfidence = multipleFaceData[0].detConfidence;
const newFaceQuality = qualityScores[0];
// 更新 UI
//updateResult(detectionConfidence, newFaceQuality);
// Extract face feature
// ✅ 仅保留高质量特征值(质量评分 > 0.7)
if (newFaceQuality > 0.7) {
// ✅ 提取特征值并缓存
const feature = unboxedSession.extractFaceFeature(
imageStream,
multipleFaceData[0].token
);
console.log(
'Feature extracted, size:',
new Float32Array(feature).length
);
// ✅ 仅缓存特征值(ArrayBuffer)
featureCache.current.push(feature);
// ✅ 更新采集进度
updateResult(
detectionConfidence,
newFaceQuality,
featureCache.current.length
);
// ✅ 检查是否攒够5个特征值
if (featureCache.current.length >= 5) {
//const batch = featureCache.current;
//featureCache.current = []; // 清空缓存
// ✅ 上传到后端
//batchProcessWorklet(batch);
}
}
}
// Clean up resources
imageStream.dispose();
bitmap.dispose();
unboxedSession.dispose();
});
//const faces = detectFaces(frame);
//updateResult(faces);
}, []);
return (
<View style={{ flex: 1 }}>
<CameraPermissionWrapper>
<Camera
ref={camera}
style={{ flex: 1 }}
device={device!}
isActive={true}
format={format}
frameProcessor={frameProcessor}
//frameProcessorFps={'auto'}
/>
</CameraPermissionWrapper>
{faceConfidence !== null && (
<Text style={{ position: 'absolute', top: 20, left: 20, color: 'red' }}>
检测到人脸置信度: {faceConfidence.toFixed(2)} (0-1)
</Text>
)}
{faceQuality !== null && (
<Text style={{ position: 'absolute', top: 50, left: 20, color: 'blue' }}>
人脸质量评分: {faceQuality.toFixed(2)} (0-1)
</Text>
)}
{faceCount !== null && (
<Text style={{ position: 'absolute', top: 80, left: 20, color: 'green' }}>
人脸数量: {faceCount}
</Text>
)}
</View>
);
}
push导致采集图片数量一直为零
最新发布