앞에서 공부했던 얼굴 검출 밑 눈 검출 방법으로 카메라를 통해 사용자가 눈을 오래 감고 있거나 자고있는지 확인하고 이를 판별해서 경고음을 내는 프로그램을 만들어 보았다.
먼저 필요한 라이브러리를 import 한다
import numpy as np
import dlib
import cv2
import time
import pygame
다음 코드는 경고 소리를 내기 위해 사용하는 코드이다.
# 경고 소리를 내기 위해서 사용
pygame.mixer.init()
pygame.mixer.music.load('./audio/fire-truck.wav')
앞에서 보았듯이 얼굴 부위별로 할당되는 range값이다. 이번에는 오른쪽눈, 왼쪽눈, 그리고 전체 눈 range만 필요하다.
RIHGT_EYE=list(range(36,42))
LEFT_EYE=list(range(42,48))
EYES=list(range(36,48))
# 영상의 사이즈를 미리 조정해준다.
frame_width=640
frame_height=480
title_name='Face Drowsiness Detection'
elapsed_time=0 #측정시간
이번에는 얼굴을 haarcascades 방식으로 검출하겠다. 이 방법은 가장 쉽고 빠른 얼굴 식별 방법이다. 그러나 정확하지 않다는 단점이 있다.
# 가장 쉽고 빠른 얼굴 식별 방법 정확하지 않다는 단점이 있다.
face_cascade_name='./haarcascades/haarcascade_frontalface_alt.xml'
face_cascade=cv2.CascadeClassifier()
if not face_cascade.load(cv2.samples.findFile(face_cascade_name)):
print('ERROR loading face cascade')
exit(0)
이제 얼굴의 68개의 점들을 찾아주는 코드를 작성하겠다.
# 얼굴의 68개의 점들을 찾아줌
predictor_file='./model/shape_predictor_68_face_landmarks.dat'
predictor=dlib.shape_predictor(predictor_file)
다음은 이 프로그램의 상태 변수들이다. 이 프로그램에서는 카메라가 지속적으로 눈을 몇번이나 감고 있는지 카운팅을 할 것인데 여기서는 7번 이상 지속되면 즉 number_closed=7이 넘어가면 경고음을 들려주게끔 설계했다. 또한 min_EAR라는 중요한 변수가 있는데 이 개념은 다음과 같다.
눈을 감고있는지 뜨고있는지 계싼할수 있는 방법이다. 여기서는 임계값을 0.25로 주었다.
status='Awake'
number_closed=0
min_EAR=0.15
#최대 허용 눈감고 있는 횟수
closed_limit=7
show_frame=None
sign=None
color=None
위의 EAR를 계산하는 함수는 다음과 같다.
def getEAR(points):
A=np.linalg.norm(points[1]-points[5])
B=np.linalg.norm(points[2]-points[4])
C=np.linalg.norm(points[0]-points[3])
return (A+B) / (2.0 * C)
다음은 제일 중요한 함수인 detectAndDisplay이다. 이 코드는 주석으로 설명하겠다.
def detectAndDisplay(image):
global number_closed
global color
global show_frame
global sign
global elapsed_time
start_time=time.time()
# height,width=image.shape[:2]
image=cv2.resize(image,(frame_width,frame_height))
show_frame=image # 졸고있을때 회색으로 frame을 변하게 해주려고
frame_gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
frame_gray=cv2.equalizeHist(frame_gray) # 분석을 편하게 하기 위해
faces=face_cascade.detectMultiScale(frame_gray) # 얼굴을 찾아줌
for (x,y,w,h) in faces: #얼굴의 개수만큼 반복
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
rect=dlib.rectangle(int(x),int(y),int(x+w),int(y+h)) # dlib에서 사용하는 좌표체계를 만들어줌
points=np.matrix([[p.x,p.y] for p in predictor(frame_gray,rect).parts()])
show_parts=points[EYES]
right_eye_EAR=getEAR(points[RIHGT_EYE])
left_eye_EAR=getEAR(points[LEFT_EYE])
mean_eye_EAR=(right_eye_EAR + left_eye_EAR) /2
right_eye_center=np.mean(points[RIHGT_EYE],axis=0).astype('int') #오른쪽 눈의 좌표값들의 평균값
left_eye_center=np.mean(points[LEFT_EYE],axis=0).astype('int') #왼쪽 눈의 좌표들값의 평균값
cv2.putText(image,'{:2f}'.format(right_eye_EAR),
(right_eye_center[0,0],right_eye_center[0,1]+20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,0),1)
cv2.putText(image,'{:.2f}'.format(left_eye_EAR),
(left_eye_center[0,0],left_eye_center[0,1]+20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,0),1)
for (i,point) in enumerate(show_parts):
x=point[0,0]
y=point[0,1]
cv2.circle(image,(x,y),1,(0,255,255),-1)
if mean_eye_EAR > min_EAR:
color = (0,255,0)
status='Awake'
number_closed=number_closed -1
if(number_closed<0):
number_closed=0
else:
color=(0,0,255)
status='Sleep'
number_closed=number_closed + 1
sign=status + 'Sleep count:' + str(number_closed) + '/' + str(closed_limit)
if (number_closed > closed_limit):
shhow_frame=frame_gray
# play SOUND
if(pygame.mixer.music.get_busy()==False): # 노래가 플레이 되고 있지 않냐
pygame.mixer.music.play()
cv2.putText(show_frame,sign,(10,frame_height-20),cv2.FONT_HERSHEY_SIMPLEX,0.6,(255,0,0),2)
cv2.imshow(title_name,show_frame)
frame_time=time.time() - start_time
elapsed_time += frame_time
print('frame time {:.3f} seconds'.format(frame_time))
마지막 main 함수이다.
vs=cv2.VideoCapture(0)
time.sleep(2.0)
if not vs.isOpened:
print('ERROR opening video')
exit(0)
while True:
ret,frame=vs.read()
if frame is None:
print('no more frame')
vs.releas()
break
detectAndDisplay(frame)
if cv2.waitKey(1) & 0xFF==ord('q'):
break
vs.release()
cv2.destroyAllWindows()
'Object Detection' 카테고리의 다른 글
Custom YOLO project - YOLO 이미지 데이터 만들기 (0) | 2021.08.21 |
---|---|
yolov3를 이용한 객체 탐지 (0) | 2021.08.17 |
face_aligned_photo_generator (0) | 2021.08.16 |
face alignment (0) | 2021.08.15 |
face_landmark 방법으로 얼굴 검출하기 (0) | 2021.08.15 |