스파르타 코딩클럽의 딥러닝 이미지 처리 수업을 기반으로 공부한 내용을 정리하고 있습니다.
이미 학습된 모델을 기반으로 주어진 데이터들을 추론하는 연습을 하는 거라, 모델 자체를 학습하고 만드는 과정에 대한 내용은 없습니다.
얼굴 인식 코드 출처 : dlib.net/face_landmark_detection.py.html
랜드마크 모델이란?
얼굴의 눈,코,입 좌표를 알려주는 모델이다. 따라서 얼굴 사진을 입력하면 각각 눈,코,입의 좌표가 출력된다.
기본적인 코드 작성
1. 관련 패키지 import 하고 모델 로드하기
-> dlib 모듈 사용 : 자체적으로 얼굴을 탐지하는 모델을 제공한다. 따라서 빠른 속도로 얼굴을 탐지할 수 있다.
1
2
3
4
5
6
7
8
9
10
|
#패키지 불러오기
import cv2
import dlib
#모델 불러오기
detector = dlib.get_frontal_face_detector()
#영상과 이미지 로드하기
cap = cv2.VideoCapture('videos/01.mp4')
sticher_img = cv2.imread('imgs/sticker01.png' , cv2.IMREAD_UNCHANGED)
|
cs |
사용할 영상 및 스티커를 불러올 때, cv.IMREAD_UNCHANGED를 통해, png 파일을 합성할 수 있는 상태로 변형해준다.
불러온 동영상을 플레이 하는 코드는 블로그 내의 다른 게시글에 정리해두었으니 참고!
2. 얼굴영역 탐지하기
-> 기존에 사용한 얼굴영역 탐지코드와는 조금 다르다. dlib을 통해 로드한 모델을 사용할 건데, dlib 모듈 덕에
이미지 전처리 과정이 필요가 없어진다.
1
2
3
4
5
|
dets = detector(img)
print("number of faces detected:", len(dets))
for det in dets:
print(det)
|
cs |
-> 아래와 같이 인지된 얼굴의 수와 얼굴이 위치한 좌표수가 출력된다.
따라서 좀더 정확하게 x,y 좌표를 출력해야 하므로 코드를 살짝 수정해준다,
**
x,y 좌표를 지정하고, 얼굴 영역부분에 사각형 좌표 찍어주기
1
2
3
4
5
6
7
8
9
10
|
dets = detector(img)
print("number of faces detected:", len(dets))
for det in dets:
x1 = det.left()
y1 = det.top()
x2 = det.right()
y2 = det.bottom()
cv2.rectangle(img, pt1=(x1,y1), pt2=(x2,y2), color=(0,255,0), thickness=2)
|
cs |
3. 탐지한 얼굴 영역에 스티커 붙이기
->기존에 이미지에 합성처리한 코드를 활용해보는 것
1
2
3
4
5
6
7
8
9
10
|
overlay_img = sticker_img.copy()
#스티커를 얼굴 사이즈에 맞춰서 크기 조정을 해준다.
overlay_img = cv2.resize(overlay_img, dsize=(x2 - x1, y2 - y1))
#스티커 합성하는 코드
overlay_alpha = overlay_img[:, :, 3:4] / 255.0
background_alpha = 1.0 - overlay_alpha
img[y1:y2, x1:x2] = overlay_alpha * overlay_img[:, :, :3] + background_alpha * img[y1:y2, x1:x2]
|
cs |
하지만 위의 코드로 동영상을 출력해보면, 스티커가 얼굴영역 안에 붙어서 출력된다.
이 이유는 리사이즈 및 위치 선정을 얼굴영역을 기준으로 햇기 때문에 얼굴 영역 내에 합성 된것이다.
하지만 얼굴영역의 외부에 스티커가 붙어야 하므로, 이를 위해 위치와 크기를 조정할 필요가 있다.
** 수정코드
-> 우선 try/ except 구문을 통해, 스티커가 얼굴 영역 밖에 위치하게 되더라도 잘리거나 에러가 나지 않도록 해준다.
-> 이제는 얼굴영역에 대한 x,y 좌표룰 수정해야 한다.
이 때, x1,y1의 경우는 빼야 범위가 더커지고, 반대로 x2,y2의 경우는 더해야 범위가 더 커진다. 따라서 더 작은 범위를 출력하려면 반대를 생각하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
for det in dets:
x1 = det.left() - 40
y1 = det.top() - 50
x2 = det.right() + 40
y2 = det.bottom() + 30
#cv2.rectangle(img, pt1=(x1,y1), pt2=(x2,y2), color=(0,255,0), thickness=2)
#얼굴 영역 밖에 스티커가 있는 경우 잘리거나 에러가 나는 경우를 방지
try:
overlay_img = sticker_img.copy()
#스티커를 얼굴 사이즈에 맞춰서 크기 조정을 해준다.
overlay_img = cv2.resize(overlay_img, dsize=(x2 - x1, y2 - y1))
#스티커 합성하는 코드
overlay_alpha = overlay_img[:, :, 3:4] / 255.0
background_alpha = 1.0 - overlay_alpha
img[y1:y2, x1:x2] = overlay_alpha * overlay_img[:, :, :3] + background_alpha * img[y1:y2, x1:x2]
except:
pass
|
cs |
**결과물
'Data' 카테고리의 다른 글
딥러닝 이해하기_GAN (0) | 2020.12.25 |
---|---|
[Practice]얼굴의 랜드마크 탐지하기 (0) | 2020.12.25 |
딥러닝 이해하기_컴퓨터비전(CV) (0) | 2020.12.17 |
[Practice]성별, 나이 예측하기 (0) | 2020.12.13 |
[Practice]Face Mask Detector (0) | 2020.12.10 |