강의자료/머신러닝

[머신러닝활용]dlib 모듈을 이용한 얼굴 인식 및 활용하기

파아란 기쁨 2023. 2. 13. 11:31

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 파일은 머신러닝으로 학습된 데이터 이므로 해당 사이트에서 다운로드 받자.

https://osdn.net/projects/sfnet_dclib/downloads/dlib/v18.10/shape_predictor_68_face_landmarks.dat.bz2/

 

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

 

사업자 정보 표시
원당컴퓨터학원 | 기희경 | 인천 서구 당하동 1028-2 장원프라자 502호 | 사업자 등록번호 : 301-96-83080 | TEL : 032-565-5497 | Mail : icon001@naver.com | 통신판매신고번호 : 호 | 사이버몰의 이용약관 바로가기