FaceDetector 人臉檢測追蹤demo

_clai發表於2024-05-08
  • 捕獲攝像頭,檢測人臉識別
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      video,
      canvas {
        width: 640px;
      }
    </style>
  </head>
  <body>
    <button id="start" onclick="start()" class="btn btn-lg btn-primary">Start capture</button>
    <button id="detect" onclick="detect()" class="btn btn-lg btn-primary">Detect the face</button>
    <br />
    <video id="video" autoplay="true" muted="true"></video>
    <canvas id="canvas"></canvas>

    <script>
      const detectBtn = document.getElementById('detect')
      detectBtn.disabled = true;

      function start() {
        navigator.mediaDevices
          .enumerateDevices()
          .then((devices) => {
            console.log('devices => ', devices);
            var videoSource = null;
            devices.forEach((device) => {
              if (device.kind == 'videoinput') {
                videoSource = device.deviceId;
              }
            });
            const constraints = {
              video: { deviceId: { exact: videoSource }, width: { max: 320 } },
            };
            console.log('constraints => ', constraints);
            return navigator.mediaDevices.getUserMedia(constraints);
          })
          .then((stream) => {
            document.getElementById('video').srcObject = stream;
            document.getElementById('start').disabled = true;
            document.getElementById('detect').disabled = false;
          })
          .catch((e) => {
            console.error('getUserMedia() failed: ', e);
          });
      }
      function detect() {
        if (!Reflect.has(globalThis, 'FaceDetector')) {
          document.body.innerHTML = `<h1>不支援人臉檢測</h1>`;
          return;
        }

        /** @type {HTMLCanvasElement} */
        var canvas = document.getElementById('canvas');
        /** @type {HTMLVideoElement} */
        var video = document.getElementById('video');

        if (video.videoWidth < video.offsetWidth) {
          canvas.width = video.offsetWidth * devicePixelRatio;
          canvas.height = video.offsetHeight * devicePixelRatio;
        } else {
          canvas.width = video.videoWidth * devicePixelRatio;
          canvas.height = video.videoHeight * devicePixelRatio;
        }

        var ctx = canvas.getContext('2d');

        var faceDetector = new FaceDetector();

        video.requestVideoFrameCallback(_detect);

        function _detect() {
          ctx.clearRect(0, 0, canvas.width, canvas.height);
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

          faceDetector 
            .detect(canvas)
            .then((faces) => {
              ctx.lineWidth = 3;
              ctx.strokeStyle = 'red';

              for (var i = 0; i < faces.length; i++) {
                const { x, y, width, height } = faces[i].boundingBox;
                ctx.beginPath();
                ctx.rect(
                  Math.floor(x),
                  Math.floor(y),
                  Math.floor(width),
                  Math.floor(height)
                );
                ctx.stroke();
              }
              ctx.closePath();
            })
            .catch((err) => {
              console.log('error: => ' + err);
            })
            .finally(() => {
              video.requestVideoFrameCallback(_detect);
            });
        }
      }
    </script>
  </body>
</html>

相關文章