오픈소스를 활용한 딥러닝 얼굴인식 맛보기 (Feat. DeepFace)

2023. 8. 4.Tech

본 포스팅에서는 딥러닝 얼굴인식 오픈소스 중 하나인 DeepFace의 주요 기능 및 간단한 사용 방법을 소개하고자 합니다.

 

들어가며

최근 몇 년 사이, 딥러닝 기반의 얼굴인식 기술은 금융권을 중심으로 빠르게 확산하고 있습니다.

이미 많은 금융기관에서 얼굴인식 기술을 활용한 비대면 본인 확인을 진행하고 있고,

간편 인증 및 사기거래 탐지 등에도 얼굴인식을 적용하고 있습니다.

 

저희 케이뱅크에서도 고객이 제출한 신분증이 실제 고객의 신분증인지,

또는 다른 사람의 신분증인지 여부를 판단하기 위해 얼굴인식 기술을 활용하고 있습니다.

 

이처럼 얼굴인식은 사용자에게 높은 편의성을 제공할 수 있는데다 정확도 또한 신뢰할 만한 수준이기 때문에 은행 및 카드사, 증권사에 빠르게 확대 도입되고 있는 추세입니다.


딥러닝 얼굴인식 과정

그렇다면, 딥러닝 얼굴인식은 어떤 과정으로 진행되는지 살펴보겠습니다.

얼굴인식 단계

1. 얼굴 검출 (Face Detection)

먼저, 입력된 이미지에서 얼굴 영역을 찾아 추출합니다.

2. 얼굴 정렬 (Face Alignment)

그리고 얼굴의 주요 랜드마크 포인트(눈, 코, 입, 얼굴 윤곽 등)를 추출합니다.

3. 얼굴 정규화 (Face Normalization)

랜드마크 포인트를 기준으로 얼굴 영역을 회전시키고 얼굴 매칭이 가능한 상태로 변경합니다.

4. 얼굴 표현 (Face Representation)

이후, 얼굴 영역을 임베딩 과정을 거쳐 N차원의 특징벡터로 표현합니다.

임베딩(Embedding)이란?
고차원 데이터를 저차원 공간으로 변환(일정 크기의 벡터로 매핑)하는 것으로, 인식에 필요한 정보만 남기는 과정이라고 보시면 됩니다.
그리고 임베딩 과정을 거친 특징벡터는 사람마다 고유의 값을 가지므로, 이후에 서로 비교하는 방식으로 신원 확인이 가능합니다.

5. 얼굴 비교 (Face Matching)

마지막 단계는 입력된 이미지 속 얼굴이 누구인지 판단하기 위해 특징 벡터 간의 유사도를 계산하는 것으로, 목적에 따라 두 종류로 구분할 수 있습니다.

  • 얼굴 검증 (Verification)
    두 이미지 속 얼굴이 같은 인물인지 검증 (1:1 비교)
    ex) 모바일 앱 로그인 및 간편 결제
  • 얼굴 식별 (Identification)이미지 속 얼굴이 누구인지 식별 (1:N 비교)
    ex) 인가된 직원의 건물 출입

DeepFace를 사용하기 전에

DeepFace는 얼굴 검출 및 인식, 그리고 나이/성별/감정 등 얼굴 분석 기능을 제공하는 Python 얼굴인식 프레임워크입니다.

 

GitHub - serengil/deepface: A Lightweight Face Recognition and Facial Attribute Analysis (Age, Gender, Emotion and Race) Library

A Lightweight Face Recognition and Facial Attribute Analysis (Age, Gender, Emotion and Race) Library for Python - GitHub - serengil/deepface: A Lightweight Face Recognition and Facial Attribute Ana...

github.com

DeepFace의 주요 특징

  • 얼굴 검출/표현/검증/식별/분석 기능을 Python 함수 및 API 형태로 제공
  • 얼굴 검출 및 표현 단계에 다양한 딥러닝 SOTA 모델을 선택하여 조합 사용할 수 있음
    SOTA (State-of-the-art) 모델이란?
    : AI의 특정 분야에서 가장 높은 성능을 달성한 모델
  • 검출 모델 : OpenCV, MTCNN, RetinaFace 등 총 6가지 모델 사용 가능
  • 표현 모델 : Dlib, Facenet, ArcFace 등 총 9가지 모델 사용 가능
    (실제 모델은 8가지이나, Facenet은 128, 512차원의 두 가지 버전 제공)
  • 두 얼굴 특징벡터 간 유사도를 측정하기 위해 거리 기반 및 각도 기반의 메트릭(Metric) 사용 가능

아나콘다(Anaconda) 가상환경 구성

본 포스팅에서는 Python 기반의 머신러닝/딥러닝 개발 플랫폼인 아나콘다가 설치된 상태를 전제로 진행하겠습니다.
(설치 전이거나 아나콘다를 잘 모르시는 분들은 구글 검색란에 ‘아나콘다란?’, ‘아나콘다 설치' 등의 키워드로 검색하시면 무수히 많은 친절한 설명글이 있으니 참고 부탁드립니다. 😄)

 

1. 가상환경 생성

python 3.6 버전의 deepface라는 가상환경을 생성합니다.

$ conda create -n deepface-env python=3.6

2. 가상환경 목록 확인

$ conda env list
# conda environments:
#
base                  *  /home/user/anaconda3
deepface-env             /home/user/anaconda3/envs/deepface

3. 가상환경 활성화

$ conda activate deepface-env

4. DeepFace 라이브러리 설치

DeepFace를 사용하기 위한 두 가지 방법이 있습니다.

1) pip를 통해 PyPI에서 라이브러리를 다운받거나,
2) git을 통해 Github에서 DeepFace 레파지토리를 복제(clone)하는 것입니다.

 

보다 간단하게, 우리는 pip를 통해 DeepFace 라이브러리를 설치하겠습니다.

(deepface)$ pip install deepface

5. DeepFace import 확인

DeepFace 라이브러리를 설치한 후에는 Jupyter Notebook나 PyCharm, VSCode 등 다양한 개발 환경에서 import하여 사용할 수 있습니다.

(deepface)$ python
>>> from deepface import Deepface

+) Jupyter Notebook에서 아나콘다 가상환경 사용하는 방법

  1. 아나콘다 가상환경 생성 후, Jupyter Notebook에서 사용하기 위해 먼저 kernel을 확인합니다.
New 버튼 클릭 > kernel 목록 확인

 

2. 사용하고자 하는 환경이 없을 경우, CLI창에서 아래 과정을 진행합니다.

$ conda activate <MY_ENV_NAME>
$ pip install ipykernel
$ python -m ipykernel install --user --name <MY_ENV_NAME> --display-name <MY_ENV_NAME>

3. Jupyter Notebook에서 kernel을 재확인합니다.

New 버튼 클릭 > 추가한 가상환경 이름 확인

DeepFace 주요 기능 맛보기

위에서 말씀드렸듯이, DeepFace에서는 얼굴 검출 및 얼굴 표현, 얼굴 검증, 얼굴 식별, 얼굴 분석 기능을 제공합니다.

그럼 이제부터 하나씩 간단하게 사용해보겠습니다.

시작하기 전에, 얼굴 사진이 필요합니다. 본인 사진도 좋고, 좋아하는 연예인이나 운동 선수 사진도 상관 없습니다.

저는 구글에서 배우 ‘공유' 사진을 다운받아 data 폴더에 저장했습니다.

1. 얼굴 검출

먼저, 위에서 준비한 이미지를 불러온 후, 확인해 봅시다.

# 라이브러리 import
import cv2
import matplotlib.pyplot as plt
from deepface import DeepFace# 이미지 저장 경로
img_path = './data/face_1.jpg'# 이미지 읽기
img = cv2.imread(img_path)# 이미지 확인
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
matplotlib 라이브러리를 통한 원본 이미지 출력

그 다음, detectFace 함수에 이미지와 얼굴 검출 모델을 인자로 넣습니다.
저는 얼굴 검출 모델로 RetinaFace를 사용할 건데요.
이 모델은 one-stage 검출 모델로, CPU 연산만으로도 빠르고 정확한 추론이 가능합니다.

# 얼굴 검출 모델 목록 (원하는 모델 선택 사용)
detection_models = ['opencv', 'ssd', 'dlib', 'mtcnn', 'retinaface', 'mediapipe']
# 얼굴 검출 및 정렬 진행
face = DeepFace.detectFace(img_path=img,
                        detector_backend='retinaface')
# 얼굴 영역 확인
plt.imshow(cv2.cvtColor(face, cv2.COLOR_BGR2RGB))
얼굴 검출 결과

위와 같이, detectFace 함수를 통해 얼굴 영역이 추출되었습니다.
추가적으로, detectFace 함수에는 더 많은 인자를 전달할 수 있는데요.
Jupyter Notebook에서 아래와 같이 입력하면 모든 파라미터에 대한 정보를 확인하실 수 있습니다.

?DeepFace.detectFace # 물음표 뒤에 검색할 함수명 등 입력
Signature:
DeepFace.detectFace(
    img_path,
    target_size=(224, 224),
    detector_backend='opencv',
    enforce_detection=True,
    align=True,
)
Docstring:
This function applies pre-processing stages of a face recognition pipeline including detection and alignment

Parameters:
        img_path: exact image path, numpy array (BGR) or base64 encoded image

        detector_backend (string): face detection backends are retinaface, mtcnn, opencv, ssd or dlib

Returns:
        deteced and aligned face in numpy format
File:      ~/anaconda3/envs/deepface/lib/python3.6/site-packages/deepface/DeepFace.py
Type:      function

2. 얼굴 표현

다음으로, 얼굴 표현을 진행해보겠습니다.
얼굴 표현은 검출된 얼굴 영역을 임베딩 과정을 거쳐 N차원으로 벡터화하는 과정입니다.
DeepFace에서는 총 9가지 모델을 제공하는데, 저는 ArcFace를 사용하겠습니다.

# 얼굴 표현 모델 목록 (원하는 모델 선택 사용)
embedding_models = ['VGG-Face', 'Facenet', 'Facenet512', 'OpenFace', 'DeepFace', 'DeepID', 'ArcFace', 'Dlib', 'SFace']
# 얼굴 표현(임베딩)
embedding = DeepFace.represent(img_path=img,
                               detector_backend='retinaface',
                               model_name='ArcFace')
                               
# 벡터 크기 확인
print(len(embedding))
# 벡터값 확인
print(embedding)

ArcFace를 통한 특징벡터의 크기는 512이고,
실제값을 출력하면 [0.037662699818611145, 0.11781536042690277, -0.06978499889373779, …, -0.02058405801653862, -0.12805138528347015]와 같이 실수로 구성되어 있습니다.
이 특징벡터는 개인마다 구분될 수 있는 고유의 값을 가지므로, 이후 얼굴인식 단계에서 특징벡터 간의 거리 비교를 통해 신원 확인을 할 수 있습니다.

3. 얼굴 검증 (1:1 비교)

이제, 얼굴 검증을 진행해보겠습니다.
얼굴 검증은 1:1 얼굴 비교로, 입력된 두 얼굴이 서로 같은 인물인지 다른 인물인지 확인할 때 사용합니다.
Face ID를 통한 휴대폰 잠금 해제/송금/결제 등이얼굴 검증에 속합니다.
얼굴 검증은 두 장의 얼굴 이미지가 필요합니다.
저는 추가로 공유의 사진과 다른 배우의 사진을 다운받아 data 폴더에 저장했습니다.

# 첫 번째 이미지 불러오기
img1_path = './data/face_1.jpg'
img1 = cv2.imread(img1_path)
# 두 번째 이미지 불러오기
img2_path = './data/face_2.jpg'
img2 = cv2.imread(img2_path)
# 얼굴 검증
result = DeepFace.verify(img1_path=img1_path,
                         img2_path=img2_path,
                         detector_backend='retinaface',
                         model_name='ArcFace')
# 결과 확인
distance = result['distance']
threshold = result['threshold']
verified = result['verified']
if verified:
    verified_str = 'Same'
    distance_str =  '(%.2f <= %.2f)' % (distance, threshold)
else:
    verified_str = 'Different'
    distance_str =  '(%.2f > %.2f)' % (distance, threshold)# 결과 시각화
fig = plt.figure()
rows = 1
cols = 2ax1 = fig.add_subplot(rows, cols, 1)
ax1.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB))
ax1.set_title(verified_str)
ax1.axis("off")ax2 = fig.add_subplot(rows, cols, 2)
ax2.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
ax2.set_title(distance_str)
ax2.axis("off")plt.show()
같은 인물 간 얼굴을 비교한 결과

서로 다른 인물 간 얼굴을 비교한 결과

위 코드와 같이 verify 함수에 인자를 전달하면, 검증 결과를 리턴합니다.
검증 결과에는 거리(distance), 임계치(threshold), 동일인 여부(verified) 등의 정보가 담겨 있습니다.

동일인 여부는 두 특징벡터 간의 거리가 임계치 이하일 경우에는 같은 인물로, 그렇지 않은 경우에는 다른 인물로 판단합니다.

임계치는 일반적으로 0과 1 사이의 값을 설정하며, 얼굴인식 목적에 따라
1에 가깝도록 높게, 또는 0에 가깝도록 낮게 설정합니다.
임계치를 높게 설정하면 본인거부율은 낮아지지만 타인허용률은 높아질 수 있고,
임계치를 낮게 설정하면 타인허용률은 낮아지지만 본인거부율은 높아질 수 있습니다.
따라서 적절한 임계치 설정이 중요합니다.

 

4. 얼굴 식별 (1:N 비교)

이번에는 얼굴 식별을 진행해보겠습니다.
얼굴 식별은 1:N 비교로, 입력된 얼굴이 DB 내 인물 중 어떤 인물인지 판단할 때 사용합니다.
얼굴인식을 통한 출입 통제 및 출퇴근 관리 시스템 등이 얼굴 식별에 속합니다.
얼굴 식별은 DB 구성을 위해 여러 인물의 얼굴 이미지가 필요합니다.
따라서 배우 20명의 얼굴 사진을 다운받아 data 하위 face_db 폴더에 저장했습니다.

# 입력 이미지 불러오기
img_path = './data/face_1.jpg'
img = cv2.imread(img_path)
# 얼굴 이미지 저장 경로
db_path = './data/face_db'
# 얼굴 식별  
result = DeepFace.find(img_path=img,
                       db_path=db_path,
                       detector_backend='retinaface',
                       model_name='ArcFace')
# 결과 확인
print(result)
# 결과 시각화
fig = plt.figure()
rows = 1
cols = 2ax1 = fig.add_subplot(rows, cols, 1)
ax1.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
ax1.axis("off")res_img_path = result['identity'][0]
res_img = cv2.imread(res_img_path)
ax2 = fig.add_subplot(rows, cols, 2)
ax2.imshow(cv2.cvtColor(res_img, cv2.COLOR_BGR2RGB))
ax2.axis("off")plt.show()
(좌) 입력 이미지 / (우) 얼굴 식별 결과

위 코드를 실행하면 식별 결과가 DataFrame 형태로 반환되고, 입력된 얼굴에 대해 DB 내 인물 중 가장 유사한 인물의 정보(이미지 경로, 임베딩 모델, 거리 계산 메트릭, 거리값)를 확인할 수 있습니다.

5. 얼굴 분석

마지막으로 얼굴 분석을 진행해보겠습니다.
DeepFace에서는 나이, 성별 감정, 인종 속성 정보를 제공합니다.

result = DeepFace.analyze(img_path=img,
                          actions=['emotion', 'age', 'gender', 'race'],
                          detector_backend='retinaface')
''' 실행 결과
{'emotion': {'angry': 0.0004515215634290456,
  'disgust': 2.763969938234259e-10,
  'fear': 0.004208742167655376,
  'happy': 55.99315833963851,
  'sad': 0.0019148158125778883,
  'surprise': 0.029963159547452278,
  'neutral': 43.97030698899114},
 'dominant_emotion': 'happy',
 'region': {'x': 88, 'y': 17, 'w': 35, 'h': 48},
 'age': 31,
 'gender': 'Man',
 'race': {'asian': 37.11312115192413,
  'indian': 6.017506867647171,
  'black': 3.814232349395752,
  'white': 23.604530096054077,
  'middle eastern': 12.007694691419601,
  'latino hispanic': 17.442917823791504},
 'dominant_race': 'asian'}
'''
31살의 행복한 아시아 남성으로 예측된 공유 사진

결과를 보면, ‘emotion’ 인 감정은 7가지 각 감정에 대해 확률값을 제공하며, 대표 감정은 행복이라고 예측되었습니다.
그 다음, ‘region’은 검출된 사각형 얼굴 영역의 좌표값이며,
‘age’는 나이로, 공유 얼굴을 31살로 실제 나이보다 매우 젊게 예측하고 있습니다.
‘gender’인 성별은 남자로 예측하고 있으며,
마지막으로 ‘race’인 인종은 6가지 인종 중에 아시아인의 확률값이 37.11%로 가장 높습니다.

 


마치며

이것으로 DeepFace 오픈소스를 통한 딥러닝 얼굴인식을 간단하게 살펴봤습니다.
기본적인 사용 방법만으로도 꽤나 괜찮은 성능을 확인할 수 있지만, 이미지 전처리 또는 메트릭(metric) 변경, 모델 결합(ensemble) 등의 방법을 통해 인식 성능을 보다 개선할 수 있습니다.
다음 포스팅에서는 DeepFace 코드를 좀 더 자세히 살펴보고 수정하여 성능을 높일 수 있는 방법에 대해 작성해보겠습니다.

그럼 긴 글 읽어주셔서 감사합니다. 😀

 

 

케이뱅크와 함께 하고 싶다면 🚀