기본 콘텐츠로 건너뛰기

[OpenCV/Google Colab] 노트북 웹캠으로 얼굴인식하기

 

[OpenCV/Google Colab] 노트북 웹캠으로 얼굴인식하기



우리 노트북에는 거의 웹캠이 달려있습니다.

안 달린 노트북이 드물 정도죠.


지금 진행중인 프로젝트가 노트북 웹캠을 활용하는 겁니다. 웹캠으로 사용자의 모션을 인식하는 것이죠.

모션인식하는 방법을 찾던 중에 간단하게 예습할 수 있는 것을 찾아보았습니다. 


바로 웹캠으로 '얼굴'을 인식하는 것인데요, 아주 간단한 코드로 진행할 수 있습니다.




  1. Google Colab 실행하기

우선 구글 코랩은 줄여서 'Colab'이라고도 하는 Colaboratory를 사용하면 브라우저에서 Python을 작성하고 실행할 수 있습니다. 
구성이 필요하지 않으며, GPU를 무료 접근 가능하고 간편한 공유가 가능하다는 장점이 있습니다.




간단하게 구글에서 colab만 검색해도 바로 나옵니다.


들어가자마자 이런 창이 뜹니다. 처음 접속하셨다면 'Welcome To Colaboratory'가 뜰겁니다. 간단한 소개와 튜토리얼이 적혀 있습니다. 저는 오른쪽 하단에 'NEW NOTEBOOK'을 누르고 새롭게 만들었습니다.





   2. OpenCV 코드


우선, opencv github주소를 불러옵니다.
그리고 웹캠을 통해 캡쳐한 비디오를 저장할 디렉토리도 하나 만들어줍니다.


그리고 웹캠을 열기 위한 Javascript코드를 넣어줍니다.

!pip install ffmpeg-python
from IPython.display import HTML, Javascript, display
from google.colab.output import eval_js
from base64 import b64decode
import numpy as np
import io
import ffmpeg
video_file_test = '/content/Video/osy_test.mp4'
VIDEO_HTML = """
<script>
var my_div = document.createElement("DIV");
var my_p = document.createElement("P");
var my_btn = document.createElement("BUTTON");
var my_btn_txt = document.createTextNode("Press to start recording");
my_btn.appendChild(my_btn_txt);
my_div.appendChild(my_btn);
document.body.appendChild(my_div);
var base64data = 0;
var reader;
var recorder, videoStream;
var recordButton = my_btn;
var handleSuccess = function(stream) {
videoStream = stream;
var options = {
mimeType : 'video/webm;codecs=vp9'
};
recorder = new MediaRecorder(stream, options);
recorder.ondataavailable = function(e) {
var url = URL.createObjectURL(e.data);
var preview = document.createElement('video');
preview.controls = true;
preview.src = url;
document.body.appendChild(preview);
reader = new FileReader();
reader.readAsDataURL(e.data);
reader.onloadend = function() {
base64data = reader.result;
}
};
recorder.start();
};
recordButton.innerText = "Recording... press to stop";
navigator.mediaDevices.getUserMedia({video: true}).then(handleSuccess);
function toggleRecording() {
if (recorder && recorder.state == "recording") {
recorder.stop();
videoStream.getVideoTracks()[0].stop();
recordButton.innerText = "Saving the recording... Please wait!"
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
var data = new Promise(resolve=>{
recordButton.onclick = ()=>{
toggleRecording()
sleep(2000).then(() => {
// wait 2000ms for the data to be available
resolve(base64data.toString())
});
}
});
</script>
"""
def start_webcam():
js = Javascript('''
async function startWebcam() {
const div = document.createElement('div');
const video = document.createElement('video');
video.style.display = 'block';
const stream = await navigator.mediaDevices.getUserMedia({video: true});
document.body.appendChild(div);
div.appendChild(video);
video.srcObject = stream;
await video.play();
// Resize the output to fit the video element.
google.colab.output.setIframeHeight(document.documentElement.scrollHeight, true);
return;
}
''')
display(js)
data = eval_js('startWebcam()')
start_webcam()
def get_video():
display(HTML(VIDEO_HTML))
data = eval_js("data")
binary = b64decode(data.split(',')[1])
return binary


그리고 캡쳐한 비디오를 get하기위한 코드를 실행합니다.

videofile = get_video()
with open(video_file_test, 'wb'as f:
  f.write(videofile)

크롬을 사용하는 분들은 웹캠 권한을 물어볼 것입니다. 허락해줍니다.






 실행하는 즉시 웹캠에서 기록하고 있습니다. 기록을 중단하려면 눌러줍시다.


이제 OpenCV 코드를 넣어서 얼굴의 눈, 코, 입을 인식하는 알고리즘을 돌립니다.



import cv2
from google.colab.patches import cv2_imshow
face_cascade = cv2.CascadeClassifier('/content/opencv/data/haarcascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('/content/opencv/data/haarcascades/haarcascade_eye.xml')
cap = cv2.VideoCapture(video_file_test)
count = 1
while cap.isOpened() & count<30:
ret, img = cap.read()
# gray = cv2.cvtColor(img, cv2.COLOR_BGR2BGR)
# Detects faces of different sizes in the input image
faces = face_cascade.detectMultiScale(img, 1.3, 5)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2)
# roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_color)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,127,255),2)
cv2_imshow(img)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()


 만약 전체 비디오를 보길 원한다면 while 루프에서 count를 제거하면 됩니다.

이 알고리즘을 실행하면 노트북에 소음이 일어나면서 기록된 비디오에서 이미지를 추출하여 인식된 결과가 주르륵 나오기 시작하는데요, 아마 비디오를 오래 기록했다면 한참 기다려야 할 것 같습니다.

직접 실행해봤더니 아주 잘 나오더군요. 제 얼굴을 올리고 싶지만 혹시나 싶어서 위 링크 블로그의 사진을 참고로 가져왔습니다.






    3. 결과


 인식 정확도는 그리 좋은편이 아니네요. 얼굴과 눈은 100%정도로 읽는데 안경을 눈으로 인식하는 점과, 입은 잘 인식 못하네요.

코드를 더 수정해서 정확도를 높여야할 것 같습니다.



댓글