dli 라이브러리는 C++로 작성된 툴킷으로 HOG(histogram of Oriented Gradients) 특성을 사용하여 얼굴 검출하는 기능에 많이 사용되고 있다.
dlib.get_frontal_face_detector( ) 를 사용하여 기본 얼굴 검출기로 사용할 수 있다.
1. 라이브러리 임포트
import cv2,dlib,sys
import numpy as np
cv2,dlib,numpy 모듈을 활용한다.
2. 웹캠에서 이미지 파일 읽기
cap = cv2.VideoCapture(0) #0 웹캠, 동영상 파일을 적용 할 수도 있다.
while True:
ret,img = cap.read() #프레임 단위로 읽는다.
if not ret:
break #프레임이 없다면 종료하자.
VideoCapture(동영상파일명) - 동영상파일명을 넣으면 동영상 을 플레이 하면서 동영상의 프레임을 가지고 처리 할 수 있다.
3. 원본 이미지 화면에 출력하기
img = cv2.resize(img,(int(img.shape[1] * 0.7),int(img.shape[0] * 0.7))) #이미지 크기를 축소하자.
ori = img.copy() #원본 이미지를 ori 에 카피 해 놓자.
cv2.imshow('img',img) #이미지를 화면에 띄운다.
cv2.waitKey(1) #1미리세컨드만큼 대기
cv2를 이용하여 이미지 사이즈를 축소하여 원본 이미지를 프레임 단위로 출력한 다음 1미리 세컨드 단위로 다음 프레임을 읽어서 출력하는 형식으로 무한 반복 처리 한다.
4. 얼굴 검출
detector = dlib.get_frontal_face_detector() #얼굴 검출 라이브러리
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat') #얼굴 특징점 모듈
dlib.get_frontal_face_detector( ) 를 사용하여 detector 를 생성하고
얼굴의 특징점 68개를 찾을 수 있는 모델을 이용하여 predictor 을 생성하자.
shape_predictor_68_face_landmarks.dat 파일은 머신러닝으로 학습된 데이터 이므로 해당 사이트에서 다운로드 받자.
Downloading File /dlib/v18.10/shape_predictor_68_face_landmarks.dat.bz2 - dlib C++ Library - OSDN
Free download page for Project dlib C++ Library's shape_predictor_68_face_landmarks.dat.bz2.Dlib is a C++ toolkit containing machine learning algorithms and tools that facilitate creating compl...
osdn.net
5. 얼굴 검출 부분에 사각형 그리기
faces = detector(img) #얼굴인식
if len(faces) == 0 : continue
face = faces[0] #찾은 모든 얼굴에서 첫번째 얼굴만 가져 오기
#얼굴 부분에 사각형을 그려 보자.
img = cv2.rectangle(img,pt1=(face.left(),face.top()),pt2=(face.right(),face.bottom()), color=(255,255,255),thickness=2,lineType=cv2.LINE_AA)
detector 을 이용하여 얼굴 인식하여 첫번째 인식한 얼굴을 가져와서 인식 부분의 크기에 흰색으로 사각형을 그려 본다.
6. 특징점 68개를 찾아 특징점을 마킹
# 특징점 추출
dlib_shape = predictor(img, face)
shape_2d = np.array([[p.x, p.y] for p in dlib_shape.parts()]) # 특징점을 넘파이로 바꾼다.
for s in shape_2d: # shape_2d 의 갯수는 68개이다.
cv2.circle(img, center=tuple(s), radius=1, color=(255, 255, 255), thickness=2,
lineType=cv2.LINE_AA) # 68개의 특징점에 원모양을 그리자
shape_predictor_68_face_landmarks.dat 모델을 사용한 특징점 추출 모델인 predictor 을 이용하여 이미지에서 얼굴 인식 위치에서 특징점을 추출하여 dlib_shape를 만든다.
dlib_shape의 정보를 x,y 의 넘파이 배열로 만든 다음 cv2를 이용하여 해당 위치에 반지름 1인 원을 그린다.
안경씌우는 실습을 진행하기 위해 눈의 좌측 위치와 우측 위치의 인덱스 번호를 출력하였다.
활용하기] 얼굴에 선글라스를 씌워보자.
- 특징점의 위치
- 왼쪽 끝의 눈의 위치 37번째 지점과 오른쪽 끝의 46번째 지점 위치를 활용하여 선글라스를 끼우는 프로그램을 만들어 보자.
1. 각도를 계산하기 위해 라이브러리 임포트 및 안경 이미지를 로딩해 놓는다.
from math import atan2, degrees
# 안경 로딩
glass = cv2.imread('glasses.png', cv2.IMREAD_UNCHANGED)
glass_h, glass_w = glass.shape[:2]
안경이미지 파일 - https://github.com/kairess/cat_hipsterizer/blob/master/images/glasses.png
GitHub - kairess/cat_hipsterizer: Hipsterize your cat with deep learning. Put glasses on!
Hipsterize your cat with deep learning. Put glasses on! - GitHub - kairess/cat_hipsterizer: Hipsterize your cat with deep learning. Put glasses on!
github.com
2. 원본 파일에 안경이미지 오버레이 하는 함수
def overlay_transparent(background_img, img_to_overlay_t, x, y, overlay_size=None):
bg_img = background_img.copy() #백그라운드이미지 카피
# 3채널의 이미지라면 4채널의 이미지로 변환하자.
if bg_img.shape[2] == 3:
bg_img = cv2.cvtColor(bg_img, cv2.COLOR_BGR2BGRA) #알파채널 추가하여 변환
if overlay_size is not None:
img_to_overlay_t = cv2.resize(img_to_overlay_t.copy(), overlay_size)
b, g, r, a = cv2.split(img_to_overlay_t)
mask = cv2.medianBlur(a, 5) #주변 픽셀들의 값을 정렬하여 중앙값으로 대체하여 잡음 제거
h, w, _ = img_to_overlay_t.shape #오버레이 할 높이와 넓이
roi = bg_img[int(y - h / 2):int(y + h / 2), int(x - w / 2):int(x + w / 2)] #x,y 위치로 부터 오버레이 할 위치의 이미지 선택
img1_bg = cv2.bitwise_and(roi.copy(), roi.copy(), mask=cv2.bitwise_not(mask))
img2_fg = cv2.bitwise_and(img_to_overlay_t, img_to_overlay_t, mask=mask)
bg_img[int(y - h / 2):int(y + h / 2), int(x - w / 2):int(x + w / 2)] = cv2.add(img1_bg, img2_fg)
# 4채널의 이미지를 3채널의 이미지로 변환
bg_img = cv2.cvtColor(bg_img, cv2.COLOR_BGRA2BGR)
return bg_img
백그라운드 이미지가 3채널이라면 알파채널을 추가하여 4채널로 변환한 뒤
안경이미지를 copy 하여 얼굴 사이즈(overlay_size에 얼굴크기가 전달 되어져 온다.) 만큼 사이즈를 조절한다.
medianBlur을 이용하여 안경의 잡음을 제거한 다음 안경을 중심점을 기준으로 오버레이 한 후 3채널로 변환하여 리턴한다.
3. 각도 계산 함수
def angle_between(p1, p2):
xDiff = p2[0] - p1[0]
yDiff = p2[1] - p1[1]
return degrees(atan2(yDiff, xDiff))
왼쪽 눈과 오른쪽 눈의 지점을 받아서 각도를 계산하여 리턴 하는 함수
4. 두 눈의 중심점 찾기
eye_center = np.mean([shape_2d[36], shape_2d[45]], axis=0) # 두 눈의 중심점을 찾는다.
위에서 특징점의 위치가 shape_2d에 있으며 37번째는 36번 인덱스값, 46번째는 45번 인덱스 값이므로 두 값의 평균이 중심점이 된다.
5. 안경의 크기 및 각도 설정
glass_size = np.linalg.norm(shape_2d[36]- shape_2d[45]) * 2 # 두 눈의 길이 * 2를 안경크기로 잡는다.
angle = -angle_between(shape_2d[36], shape_2d[45]) # 두 눈의 각도를 계산한다.
M = cv2.getRotationMatrix2D((glass_w / 2, glass_h / 2), angle, 1) # 안경의 중심 위치를 기준으로 각도를 설정하자.
rotated_glasses = cv2.warpAffine(glass, M, (glass_w, glass_h))
6. 안경을 원본 이미지에 오버레이하자.
try:
img = overlay_transparent(img, rotated_glasses, eye_center[0], eye_center[1],
overlay_size=(int(glass_size), int(glass_h * glass_size / glass_w)))
except:
print('failed overlay image')
cv2.imshow('img',img) #이미지를 화면에 띄운다.
cv2.waitKey(10) #1미리세컨드만큼 대기
if cv2.waitKey(0) == ord('q'):
break
안경의 이미지만 바꿔 본다면 여러가지 안경을 직접 써 볼 수 있는 프로그램을 만들어 볼 수가 있다.
참고 소스)
https://github.com/kairess/cat_hipsterizer
GitHub - kairess/cat_hipsterizer: Hipsterize your cat with deep learning. Put glasses on!
Hipsterize your cat with deep learning. Put glasses on! - GitHub - kairess/cat_hipsterizer: Hipsterize your cat with deep learning. Put glasses on!
github.com
'강의자료 > 머신러닝' 카테고리의 다른 글
[머신러닝활용] 컴퓨터 비전 (9) | 2023.03.20 |
---|---|
[머신러닝활용] CCTV속 범인얼굴 특정하기 (15) | 2023.03.07 |
[머신러닝활용]성별과 나이를 맞추는 인공지능 (8) | 2023.01.31 |
[머신러닝활용] dlib 라이브러리를 이용한 얼굴 인식 (7) | 2023.01.17 |
[머신러닝활용] OpenCV 사용법 알아보기 (11) | 2023.01.10 |