You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于faceapi的Web端人脸识别:仅显示摄像头前人员姓名

解决方案

关键修改点

  • 移除加载标签图片时的批量控制台输出
  • 在页面添加用于显示问候语的元素
  • 仅在识别到当前摄像头前的人脸时,输出对应问候语并更新页面显示

修改后的代码

HTML代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Face Detection on the browser</title>

    <script defer src="face-api.min.js"></script>
    <script defer src="script.js"></script>
    <link rel="stylesheet" href="style.css">

</head>
<body>
    <video id="video" width="600" height="450" autoplay></video>
    <!-- 添加用于显示问候语的元素 -->
    <div id="greeting" style="margin-top: 10px; font-size: 24px; font-weight: bold;"></div>
</body>
</html>

JS代码

const video = document.getElementById("video");
// 获取问候语显示元素
const greetingElement = document.getElementById("greeting");

Promise.all([
  faceapi.nets.ssdMobilenetv1.loadFromUri("./models"),
  faceapi.nets.faceRecognitionNet.loadFromUri("./models"),
  faceapi.nets.faceLandmark68Net.loadFromUri("./models"),
]).then(startWebcam);

function startWebcam() {
  navigator.mediaDevices
    .getUserMedia({
      video: true,
      audio: false,
    })
    .then((stream) => {
      video.srcObject = stream;
    })
    .catch((error) => {
      console.error(error);
    });
}

function getLabeledFaceDescriptions() {
  const labels = ["Bibinur", "Emunrich", "Mukthar", "NursultanAhmetsha"];
  return Promise.all(
    labels.map(async (label) => {
      const descriptions = [];
      for (let i = 1; i <= 2; i++) {
        const img = await faceapi.fetchImage(`./labels/${label}/${i}.png`);
        const detections = await faceapi
          .detectSingleFace(img)
          .withFaceLandmarks()
          .withFaceDescriptor();
        descriptions.push(detections.descriptor);
        // 移除加载标签时的批量输出
      }
     
      return new faceapi.LabeledFaceDescriptors(label, descriptions);
      
    })
  );
}

video.addEventListener("play", async()=>{
  const labeledFaceDescriptors = await getLabeledFaceDescriptions();
  const faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors);

  const canvas = faceapi.createCanvasFromMedia(video);
  document.body.append(canvas);

  const displaySize = {width: video.width, height: video.height};
  faceapi.matchDimensions(canvas, displaySize);

  // 记录上一次识别的姓名,避免重复输出
  let lastRecognizedName = "";

  setInterval(async ()=>{
    const detections = await faceapi
    .detectAllFaces(video)
    .withFaceLandmarks()
    .withFaceDescriptors();

    const resizedDetections = faceapi.resizeResults(detections, displaySize)
    canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);

    const results = resizedDetections.map((d) => {
      return faceMatcher.findBestMatch(d.descriptor);
    });

    // 清空之前的问候语
    greetingElement.textContent = "";
    if(results.length > 0){
      const result = results[0];
      const name = result.label;
      // 仅当识别结果变化时输出并更新页面
      if(name !== lastRecognizedName){
        lastRecognizedName = name;
        const greeting = `Hello ${name}`;
        console.log(greeting);
        greetingElement.textContent = greeting;
      }
    } else {
      // 未检测到人脸时重置记录
      lastRecognizedName = "";
    }

    results.forEach((result, i) => {
      const box = resizedDetections[i].detection.box;
      const drawBox = new faceapi.draw.DrawBox(box, {
        label: result,
      });
      drawBox.draw(canvas);
    });
  }, 100);
});

修改说明

  1. 移除冗余输出:删除getLabeledFaceDescriptions内的批量控制台输出,避免加载标签图片时重复打印所有人名。
  2. 添加页面显示区域:在HTML中新增问候语容器,用于在视频下方展示识别结果。
  3. 精准输出逻辑:在人脸识别循环中,仅当检测到的人脸姓名发生变化时,才输出Hello 姓名到控制台并更新页面内容,避免重复刷屏。

内容的提问来源于stack exchange,提问作者user11130151

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:43:09