|
import * as faceapi from "face-api.js";
|
let isFaceModuleLoaded = false;
|
|
export const loadModels = async() => {
|
if(isFaceModuleLoaded){
|
return;
|
}
|
const MODEL_URL = '/models'
|
await faceapi.nets.tinyFaceDetector.loadFromUri(MODEL_URL)
|
await faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL)
|
await faceapi.nets.faceLandmark68TinyNet.loadFromUri(MODEL_URL)
|
isFaceModuleLoaded = true;
|
console.info("model loaded");
|
}
|
|
export const detectWithTimeout = async (video,timeout) => {
|
if(!timeout) timeout = 5000; // 默认超时时间为5秒
|
|
const detectionPromise = faceapi.detectAllFaces(
|
video,
|
new faceapi.TinyFaceDetectorOptions({
|
inputSize: 320,
|
scoreThreshold: 0.5,
|
})
|
).withFaceLandmarks();
|
const timeoutPromise = new Promise((_, reject) =>
|
setTimeout(() => reject(new Error("检测超时")), timeout)
|
);
|
return await Promise.race([detectionPromise, timeoutPromise]);
|
}
|
|
export const detectSingleWithTimeout = async (video,canvas, timeout) => {
|
if(!timeout) timeout = 5000; // 默认超时时间为5秒
|
|
const detectionPromise = faceapi.detectSingleFace(
|
video,
|
new faceapi.TinyFaceDetectorOptions({
|
inputSize: 320,
|
scoreThreshold: 0.5,
|
})
|
).withFaceLandmarks(true);
|
const timeoutPromise = new Promise((_, reject) =>
|
setTimeout(() => reject(new Error("检测超时")), timeout)
|
);
|
return await Promise.race([detectionPromise, timeoutPromise]);
|
}
|
|
// 正脸判断逻辑
|
export const isFaceFrontal = (landmarks) =>{
|
const leftEye = landmarks.getLeftEye()
|
const rightEye = landmarks.getRightEye()
|
const nose = landmarks.getNose()
|
|
const eyeYDiff = Math.abs(leftEye[0].y - rightEye[3].y)
|
const noseCenterX = nose[3].x
|
const eyeCenterX = (leftEye[0].x + rightEye[3].x) / 2
|
const noseXDiff = Math.abs(noseCenterX - eyeCenterX)
|
|
return eyeYDiff < 10 && noseXDiff < 20
|
}
|
|
export const isFaceCentered = (video, box) => {
|
const faceCenterX = box.x + box.width / 2
|
const faceCenterY = box.y + box.height / 2
|
const screenCenterX = video.videoWidth / 2
|
const screenCenterY = video.videoHeight / 2
|
const offsetX = Math.abs(faceCenterX - screenCenterX)
|
const offsetY = Math.abs(faceCenterY - screenCenterY)
|
|
const isCentered = offsetX < 50 && offsetY < 50
|
return isCentered;
|
}
|