브라우저의 웹캠에서 얼굴 감지
Face-Detection - 자바 스크립트 라이브러리 face-api.js를 사용하여 브라우저의 웹캠에서 얼굴 감지
Signlanguage-Translator Project를 진행 하면서 Client측에서 수화 번역기를 사용하는 사용자가 특정 위치에 존재시키고 인식을 시키는 부분이 필요하여 구현한 부분을 정리하였음.
face-api.js
-
face-api.js는 JavaScript를 통해 얼굴을 쉽게 감지할 수 있는 프로그램 라이브러리
-
소스 코드는 face-api.js 에 공개 됨
-
내가 필요한 파일들은 아래와 같음
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)
})
결과
- 우측 console 창에는 box의 좌표, 너비, 길이가 표시 되고
- 웹캠 화면에는 얼굴을 detection한 box가 보임
고찰
구하고자 하는 box의 좌표를 어떻게 구할 지에 대한 고민을 많이 했는데 face-api의 사용법과 여러 구글링을 통해 javascript의 setInterval 함수와 결합시킬 수 있었다. 이 과정에서 시간을 많이 소요했지만 이후에 최종 목표인 사용자의 위치 지정을 사용자 얼굴이 특정 틀의 범위 안에 맞게 끔 온다면 socket의 이벤트 송신을 통해 번역을 시작하도록 만드는게 목표
댓글남기기