1 분 소요

Face-Detection - 자바 스크립트 라이브러리 face-api.js를 사용하여 브라우저의 웹캠에서 얼굴 감지


Signlanguage-Translator Project를 진행 하면서 Client측에서 수화 번역기를 사용하는 사용자가 특정 위치에 존재시키고 인식을 시키는 부분이 필요하여 구현한 부분을 정리하였음.


face-api.js

  • face-api.js는 JavaScript를 통해 얼굴을 쉽게 감지할 수 있는 프로그램 라이브러리

  • 소스 코드는 face-api.js 에 공개 됨

  • 내가 필요한 파일들은 아래와 같음

image

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script defer src="face-api.min.js"></script>
  <script defer src="script.js"></script>
  <style>
    body {
      margin: 0;
      padding: 0;
      width: 100vw;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    canvas {
      position: absolute;
    }
  </style>
</head>
<body>
  <video id="video" width="720" height="560" autoplay muted></video>
</body>
</html>
  • body 태그의 video에서 얼굴 식별에 사용할 비디오와 detection 상자를 그릴 예정 + console 창에는 detection box의 좌표 값을 얻을 예정

script.js

const video = document.getElementById('video')

// 모델 로드를 끝 마치면 startVideo 함수 실행 
Promise.all([
  faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
  faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
  faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
  faceapi.nets.faceExpressionNet.loadFromUri('/models'),
  faceapi.nets.ssdMobilenetv1.loadFromUri('./models')
]).then(startVideo)

// 유저의 카메라 권한을 얻기 위한 코드
function startVideo() {
  navigator.mediaDevices
    .getUserMedia({ video: true })
    .then(function (stream) {
      video.srcObject = stream;
    })
    .catch(function (err) {
      console.log(err);
    });
}


video.addEventListener('play', () => {
  // canvas를 초기화 함
  const canvas = faceapi.createCanvasFromMedia(video)
  document.body.append(canvas) 
  const displaySize = { width: video.width, height: video.height }
  faceapi.matchDimensions(canvas, displaySize)
  // 100ms 마다 화면에 video frame이 표시 됨
  setInterval(async () => {
    // video에서 얼굴을 식별
    const detections = await faceapi.detectAllFaces(video).withFaceLandmarks().withFaceDescriptors()
    const resizedDetections = faceapi.resizeResults(detections, displaySize)
    canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height)
    // video에서 얼굴 좌표에 box를 그림
    resizedDetections.forEach(detection => {
      const box = detection.detection.box
      const drawBox = new faceapi.draw.DrawBox(box, {label: 'Face'})
      drawBox.draw(canvas)
      // box의 좌표 값과 너비, 길이를 콘솔창에 출력
      console.log(box.x, box.y, box.width, box.height)
  })
  }, 100)
})

결과

image

  • 우측 console 창에는 box의 좌표, 너비, 길이가 표시 되고
  • 웹캠 화면에는 얼굴을 detection한 box가 보임

고찰

구하고자 하는 box의 좌표를 어떻게 구할 지에 대한 고민을 많이 했는데 face-api의 사용법과 여러 구글링을 통해 javascript의 setInterval 함수와 결합시킬 수 있었다. 이 과정에서 시간을 많이 소요했지만 이후에 최종 목표인 사용자의 위치 지정을 사용자 얼굴이 특정 틀의 범위 안에 맞게 끔 온다면 socket의 이벤트 송신을 통해 번역을 시작하도록 만드는게 목표

댓글남기기