yanjinhui
10 天以前 c5de0d98241f8c8349fa38851b77efcfc61e4d26
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
 
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;
}