머신러닝 & 딥러닝/컴퓨터 비전

[OpenCV with Python] - 15. 인물 사진 9000장 얼굴 인식 해보고 잘라서 저장해보기

by seokii 2022. 3. 17.
728x90
반응형

코드 및 이미지 : https://github.com/Seokii/Study_OpenCV

 

GitHub - Seokii/Study_OpenCV: study about OpenCV

study about OpenCV. Contribute to Seokii/Study_OpenCV development by creating an account on GitHub.

github.com

https://seokii.tistory.com/111

 

[ML 논문 공부 - 004] Occlusion aware Facial Landmark Detection based Facial Expression Recognition with Face Mask

마스크 인식 관련 논문을 찾아보다가 발견해 읽게 된 논문입니다. 2021년 3월 IPSJ(일본정보처리학회)에 올라온 논문입니다. 세 명의 저자(Yang Bo, Wu Jianming, Hattori Gen)들은 도쿄대(the university of toky..

seokii.tistory.com

OpenCV 관련 글은 되게 오랜만에 쓰는 것 같습니다.

위의 FER(Facial Emotion Recognition, 표정 인식)분야의 논문을 읽다가 OpenCV로 얼굴 부분을 인식해 잘라서 저장해 보는 실습을 코드로 올려보면 재밌을 것 같아 글을 올리게 되었습니다.

 

데이터셋

실습할 이미지 데이터는 위의 논문에서 제공하는 연구용 데이터셋을 활용했습니다.

데이터셋에 정확한 구성 및 내용은 위의 글에서 확인하실 수 있습니다.

데이터셋 링크 : https://github.com/KDDI-AI-Center/LFW-emotion-dataset

위의 GitHub에서 다운로드 링크를 통해 데이터를 다운로드할 수 있습니다.

압축을 해제하면 다음과 같은 구성으로 이루어져 있으며,

LFW-BER.zip의 압축을 풀어 train폴더 안에 있는 negative, neutral, positive 폴더 내의 모든 사진들을 합쳐서 한 폴더로 저장을 했습니다.

제가 올려놓은 코드에서는 "images/faces"의 경로에 모든 사진 파일을 넣었습니다.

 

 

얼굴 인식 모델 파일

https://github.com/opencv/opencv/tree/master/data/haarcascades

 

GitHub - opencv/opencv: Open Source Computer Vision Library

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

OpenCV에서 제공하는 훈련된 얼굴 인식 모델을 사용하겠습니다.

해당 GitHub에서 다운로드할 수 있으며, 편의를 위해 올려놓도록 하겠습니다.

haarcascade_frontalface_default.xml
1.20MB

올려놓은 실습 코드의 models/haarcascade_frontalface_default.xml 경로에도 파일이 존재합니다.

 

 

주피터 노트북으로 구현하기

In [1] : 

import cv2
import numpy as np
import os

- 필요한 라이브러리를 import 합니다.

 

In [2] : 

path_dir = "images/faces/"
file_list = os.listdir(path_dir)

In [3] : 

file_list[0]
'Aaron_Eckhart_0001.jpg'

- 사진이 있는 디렉터리의 경로를 설정해주고 os.listdir()을 통해 디렉토리의 파일명을 배열로 받아옵니다.

- 첫 번째 배열을 출력해보며 배열에 위와 같은 파일명이 담겨있음을 확인할 수 있습니다.

 

In [4] : 

len(file_list)
9330

- 배열에 들어간 원소의 개수는 총 9330개입니다. 즉, 처리할 사진 파일의 수가 9330장임을 뜻합니다.

 

In [5] : 

file_name_list = []

for i in range(len(file_list)):
    file_name_list.append(file_list[i].replace(".jpg",""))

In [6] : 

file_name_list[0]
'Aaron_Eckhart_0001'

- file_name_list의 이름으로 배열을 만들고 .replace를 통해 확장자명이 없는 파일명을 새로 만들었습니다.

- 이는 최종적으로 이미지를 저장할 때 이름이 "이미지이름.jpg.jpg"와 같이 확장자명이 이름으로 들어가지 않게 하기 위해서 별도로 처리해 이름을 따로 저장했습니다.

 

In [7] : 

image = cv2.imread('images/faces/Aaron_Eckhart_0001.jpg')
face_cascade = cv2.CascadeClassifier('models/haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
    cv2.rectangle(image, (x,y), (x+w, y+h), (255,0,0), 2)
    cv2.imshow("face_recognition", image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

- 자르기 전 이미지에서 얼굴을 잘 인식하는지 확인하기 위해 출력을 하는 코드입니다.

- image변수에 cv2.imread()를 통해 이미지를 불러옵니다.

- face_cascade 변수에 cv2.CascadeClassfier()를 통해 얼굴 인식 모델을 불러옵니다.

CascadeClassifier은 OpenCV에서 제공하는 객체 검출을 위한 분류기 클래스입니다.

- faces 변수에 모델에서 제공하는 .detectMultiScale()을 통해 얼굴을 검출할 수 있습니다.

 

.detectMultiScale()

  • image : 입력 영상(이미지)
  • scaleFactor : 검색 윈도우 확대 비율. (1보다 커야함)
  • minNeighbors : 검출 영역으로 선택하기 위한 최소 검출 횟수

- 검출된 객체 영역의 값을 받아와 for문을 통해 영역을 출력합니다.

영역을 출력하기 위해 cv2.rectangle() 함수와 cv2.imshow() 함수를 사용합니다.

 

Out [7] : 

 

In [8] : 

image = cv2.imread('images/faces/Aaron_Eckhart_0001.jpg')
face_cascade = cv2.CascadeClassifier('models/haarcascade_frontalface_default.xml')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
    cv2.rectangle(image, (x,y), (x+w, y+h), (255,0,0), 2)
    cropped = image[y: y+h, x: x+w]
    resize = cv2.resize(cropped, (180,180))
    cv2.imshow("crop&resize", resize)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

- 위의 코드에서 얼굴을 잘라 사이즈를 조정해 출력해주는 코드입니다.

- cropped 변수에 검출한 얼굴 영역을 지정하고 해당 부분을 180*180의 크기로 재조정합니다.

- 본래 사진의 크기는 250*250이며, 사진의 재조정은 cv2.resize() 함수를 통해 간단히 진행할 수 있습니다.

 

Out [8] :  

 

In [9] : 

def Cutting_face_save(image, name):
    face_cascade = cv2.CascadeClassifier('models/haarcascade_frontalface_default.xml')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        # cv2.rectangle(image, (x,y), (x+w, y+h), (255,0,0), 2)
        cropped = image[y: y+h, x: x+w]
        resize = cv2.resize(cropped, (180,180))
        # cv2.imshow("crop&resize", resize)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()

        # 이미지 저장하기
        cv2.imwrite(f"images/cutting_faces/{name}.jpg", resize)

- 여러 장의 사진을 작업하기 위해 코드를 함수화시켰습니다.

- 위의 코드에서 사각형으로 영역 표시하는 코드, 이미지 출력 부분은 주석 처리했습니다.

 

In [10] : 

for name in file_name_list:
    img = cv2.imread("images/faces/"+name+".jpg")
    Cutting_face_save(img, name)

- 지정한 경로의 모든 사진들에서 이미지를 검출해 자르고 저장하는 작업을 수행하는 코드입니다.

- 위의 사진처럼 잘 진행이 되는 것을 확인할 수 있습니다.

 

- 총 9330개의 사진 파일 중 8952개의 사진 파일에서 얼굴을 검출하고 잘라서 저장한 것을 확인할 수 있습니다.

- 이는 OpenCV에서 제공하는 얼굴 검출 모델이 해당 데이터셋에서 약 95.9% 정도 얼굴 검출을 하는 것에 성공했다는 것을 의미합니다.

 

 

728x90
반응형

댓글