[Python] 파이썬으로 얼굴의 특징값(Face Landmark) 가져오기

랜드마크(Landmark)라는 것은 탐험가 혹은 여행가들이 원래의 장소를 돌아오기 위해서 표식을 해두는 것을 말하였지만 현대에 들어서는 유명한 장소를 랜드마크라고 한다. 예를 들어 서울의 랜드마크 중 하나로 63 빌딩, 롯데 타워, 남산 타워 등 다양한 랜드마크들이 있다.

 

Face Landmark는 얼굴의 특징점을 말한다. 예를 들어 동공의 위치, 입술의 좌표, 눈썹의 좌표 등 이런 값들을 추출하여 x,y 값으로 리턴을 하는데 대표적으로 Python의 라이브러리 중 dlib, opencv로 랜드마크를 추출하는 방법이 있으며 본 포스팅에서는 opencv로 얼굴의 특징점들을 추출하는 것을 보여드리고자 한다.

 

파이썬으로 얼굴 특징점(Face Landamrk) 가져오기

 

라이브러리 설치

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을 설치한다.

 

needneo.tistory.com/98

 

[Python] you need to install visual studio for c++

dlib를 설치하는 도중, 아래와 같은 에러가 발생하였음 C:\project>pip install dlib Collecting dlib Using cached dlib-19.21.1.tar.gz (3.6 MB) Building wheels for collected packages: dlib Building wheel..

needneo.tistory.com

 

 

68개의 얼굴의 특징점

68개의 얼굴 특징점들

 

본 포스팅에 사용하는 랜드마크 추출 알고리즘은 다음과 같이 68개의 특징점을 가지고 온다. python 기반의 랜드마크 추출 알고리즘의 아버지격의 포스팅은 

 

www.pyimagesearch.com/2017/04/03/facial-landmarks-dlib-opencv-python/

 

Facial landmarks with dlib, OpenCV, and Python - PyImageSearch

Learn how to detect and extract facial landmarks from images using dlib, OpenCV, and Python.

www.pyimagesearch.com

이 포스팅이며 이것을 기반으로 수많은 OpenCV, dlib 랜드마크 프로젝트들이 탄생하고 있다. 

 

github.com/nicoTrombon/facial-landmarks

 

nicoTrombon/facial-landmarks

Facial landmarks with dlib, OpenCV, and Python. Contribute to nicoTrombon/facial-landmarks development by creating an account on GitHub.

github.com

그리고 이 깃허브(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

위 코드는 show_raw_detection으로 한번에 값을 가져오는 것과, draw_individual_detections를 이용하여 개별적으로 가져오기도 한다. 

 

입술을 가져온 화면

 

소스가 워낙 쉽고, 필요한 것만 가져오기도 편리하기 때문에 이를 활용하여, 얼굴을 탐지하는 것이라던지 혹은 관상을 볼 수 있게 한다던지 등등 얼굴과 관련된 프로그램을 쉽게 제작할 수 있을 것이다.

 

 

댓글

Designed by JB FACTORY