랜드마크(Landmark)라는 것은 탐험가 혹은 여행가들이 원래의 장소를 돌아오기 위해서 표식을 해두는 것을 말하였지만 현대에 들어서는 유명한 장소를 랜드마크라고 한다. 예를 들어 서울의 랜드마크 중 하나로 63 빌딩, 롯데 타워, 남산 타워 등 다양한 랜드마크들이 있다.
Face Landmark는 얼굴의 특징점을 말한다. 예를 들어 동공의 위치, 입술의 좌표, 눈썹의 좌표 등 이런 값들을 추출하여 x,y 값으로 리턴을 하는데 대표적으로 Python의 라이브러리 중 dlib, opencv로 랜드마크를 추출하는 방법이 있으며 본 포스팅에서는 opencv로 얼굴의 특징점들을 추출하는 것을 보여드리고자 한다.
라이브러리 설치
pip install dlib
pip install imutils
pip install opencv-python
만약 dlib를 설치하는 동안 에러가 발생한다면, cmake를 설치하도록 한다.
dlib 설치 에러 발생 케이스
Building wheel for dlib (setup.py) ... error
ERROR: Command errored out with exit status 1:
command: 'C:\Anaconda3\envs\face\python.exe' -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'C:\\Users\\Steel Stark\\AppData\\Local\\Temp\\pip-install-dqgu3zpd\\dlib_21bd53fa22aa4c48be11263b5e29b992\\setup.py'"'"'; __file__='"'"'C:\\Users\\Steel Stark\\AppData\\Local\\Temp\\pip-install-dqgu3zpd\\dlib_21bd53fa22aa4c48be11263b5e29b992\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d 'C:\Users\Steel Stark\AppData\Local\Temp\pip-wheel-97eo8lmv'
cwd: C:\Users\Steel Stark\AppData\Local\Temp\pip-install-dqgu3zpd\dlib_21bd53fa22aa4c48be11263b5e29b992\
(face) C:\project\face>pip install cmake
Collecting cmake
Downloading cmake-3.18.4.post1-py3-none-win_amd64.whl (34.7 MB)
|████████████████████████████████| 34.7 MB 6.8 MB/s
Installing collected packages: cmake
Successfully installed cmake-3.18.4.post1
cmake를 설치 후, 다시 dlib를 설치할 때 visual tool 이 설치가 되지 않아 에러가 발생할 수 있다. 이럴 경우 아래의 포스팅을 참고하여 visual tool을 설치한다.
68개의 얼굴의 특징점
본 포스팅에 사용하는 랜드마크 추출 알고리즘은 다음과 같이 68개의 특징점을 가지고 온다. python 기반의 랜드마크 추출 알고리즘의 아버지격의 포스팅은
www.pyimagesearch.com/2017/04/03/facial-landmarks-dlib-opencv-python/
이 포스팅이며 이것을 기반으로 수많은 OpenCV, dlib 랜드마크 프로젝트들이 탄생하고 있다.
github.com/nicoTrombon/facial-landmarks
그리고 이 깃허브(Github) 프로젝트는 콘솔 기반으로 쉽게 사용하는 것을 보여주고 있다. 본 포스팅에는 argument 부분을 삭제하여 소스 코드 내에 직접 모델과 이미지 경로값을 입력하였다. 본 코드를 실행하기 전에 모델을 가져와야 하는데 [ 여기 ] 를 클릭하여 모델을 저장한 후, 압축을 해제한다. 만약 클릭해도 아무런 반응이 없을 경우 우클릭하여 "다른 이름으로 링크 저장"을 선택하여 저장한다.
전체 소스코드
# Facial landmarks with dlib, OpenCV, and PythonPython
# import the necessary packages
from imutils import face_utils
import numpy as np
import imutils
import dlib
import cv2
def show_raw_detection(image, detector, predictor):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# detect faces in the grayscale image
rects = detector(gray, 1)
# loop over the face detections
for (i, rect) in enumerate(rects):
# determine the facial landmarks for the face region, then
# convert the facial landmark (x, y)-coordinates to a NumPy
# array
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# convert dlib's rectangle to a OpenCV-style bounding box
# [i.e., (x, y, w, h)], then draw the face bounding box
(x, y, w, h) = face_utils.rect_to_bb(rect)
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# show the face number
cv2.putText(image, "Face #{}".format(i + 1), (x - 10, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# loop over the (x, y)-coordinates for the facial landmarks
# and draw them on the image
for (x, y) in shape:
cv2.circle(image, (x, y), 1, (0, 0, 255), -1)
# show the output image with the face detections + facial landmarks
cv2.imshow("Output", image)
cv2.waitKey(0)
def draw_individual_detections(image, detector, predictor):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# detect faces in the grayscale image
rects = detector(gray, 1)
# loop over the face detections
for (i, rect) in enumerate(rects):
# determine the facial landmarks for the face region, then
# convert the landmark (x, y)-coordinates to a NumPy array
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
# loop over the face parts individually
for (name, (i, j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
# clone the original image so we can draw on it, then
# display the name of the face part on the image
clone = image.copy()
cv2.putText(clone, name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
0.7, (0, 0, 255), 2)
# loop over the subset of facial landmarks, drawing the
# specific face part
for (x, y) in shape[i:j]:
cv2.circle(clone, (x, y), 1, (0, 0, 255), -1)
# extract the ROI of the face region as a separate image
(x, y, w, h) = cv2.boundingRect(np.array([shape[i:j]]))
roi = image[y:y + h, x:x + w]
roi = imutils.resize(roi, width=250, inter=cv2.INTER_CUBIC)
# show the particular face part
cv2.imshow("ROI", roi)
cv2.imshow("Image", clone)
cv2.waitKey(0)
# visualize all facial landmarks with a transparent overlay
output = face_utils.visualize_facial_landmarks(image, shape)
cv2.imshow("Image", output)
cv2.waitKey(0)
# initialize dlib's face detector (HOG-based) and then create
# the facial landmark predictor
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
# load the input image, resize it, and convert it to grayscale
image = cv2.imread('image/tonystark.jpg')
image = imutils.resize(image, width=500)
show_raw_detection(image, detector, predictor)
draw_individual_detections(image, detector, predictor)
실행화면
위 코드는 show_raw_detection으로 한번에 값을 가져오는 것과, draw_individual_detections를 이용하여 개별적으로 가져오기도 한다.
소스가 워낙 쉽고, 필요한 것만 가져오기도 편리하기 때문에 이를 활용하여, 얼굴을 탐지하는 것이라던지 혹은 관상을 볼 수 있게 한다던지 등등 얼굴과 관련된 프로그램을 쉽게 제작할 수 있을 것이다.
'인공지능 및 데이터과학 > 인공지능 기술' 카테고리의 다른 글
희소 표현과 분산 표현, 차원의 저주 (0) | 2021.03.11 |
---|---|
GAN(Generative Adversarial network)이란? (0) | 2021.01.28 |
원핫 인코딩(One-Hot Encoding) 개념과 구현해보기 (1) | 2020.08.01 |
선의보다 악의가 더 많은 AI의 어두운 기술, 딥페이크(Deep Fake) (0) | 2020.01.24 |
AWS vs IBM Watson vs MS Azure vs Google Cloud AI 비교 (0) | 2020.01.21 |