반응형

원본 링크



Facial Landmarks for Face Recognition with Dlib

Dlib는 턱과 하관라인을 포함하는 68개의 다른 얼굴의 랜드마크 포인트를 찾을 수 있다. 대략적인 얼굴 탐지를 넘어 이 랜드마크 포인트로 정확한 얼굴 영역을 추출할 수 있다. 이러한 방식으로 노이즈를 제거하기 때문에 얼굴인식 모델의 정확도를 극적으로 향상시킨다.


Extracting faces with landmarks



Objective

여기서는 파이썬을 사용한 Dlib로 얼굴 랜드마크 탐지기(facial landmarks detector)를 실행한다. 랜드마크 포인트는 하관(jaw), 턱, 눈, 눈썹, 입술의 안쪽과 바깥쪽 영역, 코이다.

 



Requirements

Dlib가 설치되어 있어도 랜드마크 탐지기를 로드해야 한다. 다름 코드는 필요한 파일의 위치와 로드하는 방법을 보여준다.


import dlib
#http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
face_detector = dlib.get_frontal_face_detector()
landmark_detector = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")



Reading the image

Dlib 또는 Opencv로 이미지를 읽을 수 있다. 여기서 dlib가 RGB 포멧으로 이미지를 로드하지만 opencv는 BGR로 이미지를 로드한다. 따라서 opencv로 이미지를 로드한다면 아래처럼 RGB로 변경해야 한다.


img_path = "deepface/tests/dataset/img1.jpg"

#read with dlib
img = dlib.load_rgb_image(img_path)

#read with opencv
#img = cv2.imread(img_path)[:,:,::-1]



Face detection

얼굴의 랜드마크를 찾는 것은 얼굴을 찾기위해 무선 필요하다. Dlib는 바로 사용할 수 있는 정면 얼굴 탐지기 모듈을 포함한다.


faces = face_detector(img, 1)

우리는 이미 일반적인 얼굴 탐지기 중 Dlib Hog가 강력한 한가지라는 것을 알고 있다.




Landmark detections

그 다음 탐지된 얼굴을 랜드마크 탐지기로 전달한다.


landmark_tuple = []
for k, d in enumerate(faces):
    landmarks = landmark_detector(img, d)
    for n in range(0, 27):
        x = landmarks.part(n).x
        y = landmarks.part(n).y
        landmark_tuple.append((x, y))
        cv2.circle(img, (x, y), 2, (255, 255, 0), -1)

여기 68개의 랜드마크 포인트가 있다. 그러나 지금은 단지 얼굴 영역의 가장지리에만 흥미가 있다. 따라서 눈, 코, 입과 관련된 점을 제외한다. 따라서 0에서 27까지 for 루프를 구현한다.


Landmark points

아래 그림에서 안젤리나 졸리의 이미지에 대한 얼굴의 랜드마크를 볼 수 있다.


Landmarks of Angelina Jolie

여기서 랜드마크 포인트 좌표를 landmark_tuple 변수에 저장했다는 것을 기억하자. 경로(route)는 17번 점에서 시작하여 27번 점에서 끝난다.


routes = []

for i in range(15, -1, -1):
    from_coordinate = landmark_tuple[i+1]
    to_coordinate = landmark_tuple[i]
    routes.append(from_coordinate)

from_coordinate = landmark_tuple[0]
to_coordinate = landmark_tuple[17]
routes.append(from_coordinate)

for i in range(17, 20):
    from_coordinate = landmark_tuple[i]
    to_coordinate = landmark_tuple[i+1]
    routes.append(from_coordinate)

from_coordinate = landmark_tuple[19]
to_coordinate = landmark_tuple[24]
routes.append(from_coordinate)

for i in range(24, 26):
    from_coordinate = landmark_tuple[i]
    to_coordinate = landmark_tuple[i+1]
    routes.append(from_coordinate)

from_coordinate = landmark_tuple[26]
to_coordinate = landmark_tuple[16]
routes.append(from_coordinate)
routes.append(to_coordinate)

이제 경로를 선으로 그려보자.


for i in range(0, len(routes)-1):
   from_coordinate = routes[i]
   to_coordinate = routes[i+1]
   img = cv2.line(img, from_coordinate, to_coordinate, (255, 255, 0), 1)


Drawing the face boundaries



Extract facial area

이제 얼굴 랜드마크로 이미지의 배경을 제외할 수 있다. 경로(route)가 각각 얼굴 랜드마크를 저장하기 때문에 경로만을 전달한다.


mask = np.zeros((img.shape[0], img.shape[1]))
mask = cv2.fillConvexPoly(mask, np.array(routes), 1)
mask = mask.astype(np.bool)

out = np.zeros_like(img)
out[mask] = img[mask]

plt.imshow(out)


Discarding background

이런 방법으로 오직 얼굴영역에만 집중할 수 있다. 검정색 픽셀은 RGB에서 0을 나타내고 이것들은 훈련 단계에서 중립요소가 된다. 따라서 이미지에서 노이즈를 무시하기 때문에 얼굴인식 모델의 정확도가 증가한다.

게다가 얼굴 교환(face swap) 연구는 주로 이런 접근법에 기초한다.



Sketch drawing

게다가 dlib 얼굴 랜드마크 탐지기로 스케치를 그릴 수 있다.


Background blurring

Face and Background Blurring with OpenCV in Python에서 탐지된 얼굴을 제외한 이미지의 배경을 흐릿하게 만들었다. 그러나, 얼굴 탐지는 사각형 영역을 반환하고 이것은 매끄럽지 않다.


Background blurring by detected area

여기서 얼굴 랜드마크 영역외 이미지를 흐리게 만들 수 있다. 이런 방법으로 오직 얼굴 영역에 집중하면서 더 매끄러운 결과를 얻을 수 있다.

Face and Background Blurring with OpenCV in Python에서 사용했던 blur_img 함수를 사용한다.


blurred_img = blur_img(img, factor = 60)
blurred_img[mask] = img[mask]
plt.imshow(blurred_img)


Sensitive background blurring

얼굴영역은 명확한 반면 이미지 자신은 흐릿해 졌다.



Conclusion

이 글에서 Dlib로 얼굴 랜드마크를 어떻게 찾는지를 알아보았다. 이것은 이미지의 노이즈를 무시하여 얼굴 인식 파이프라인의 정확도를 높힌다.

여기서 사용된 소스코드를 여기에서 찾아 볼 수 있다

반응형

+ Recent posts