본문 바로가기

Computer Vision

딥러닝으로 얼굴 검출하기

개요

OpenCV에서는 딥러닝의 Deep Neural Network를 통해 얼굴을 검출할 수 있는 기능 구현이 가능하다. 그것에 대해 학습한다.

본론

1. OpenCV에서의 dnn 사용이란

  • 이미 학습이 완료되어 있는 모델을 사용한 얼굴 검출 기능 구현이 가능하다. 따라서 OpenCV에서 자체적으로 학습하는 것은 불가능하다.

library import

코드

import cv2
import numpy as np

model_name = "files/res10_300x300_ssd_iter_140000.caffemodel"
prototext_name = "files/deploy.prototxt.txt"
file_name = "images/obama_01.jpeg"

해설

  • model_name
    model_name에서는 경량화된 모델인 caffemodel 파일을 불러왔다.
    파일명을 해석하자면 resnet10으로 가로세로 300의 single shot detection으로 14만번 돌린 모델이라는 뜻이다.
    경량화된 모델이라 크기가 작아서 10MB 정도다.
  • prototext_name
    모델 네트워크 구성을 저장하는 파일이다.
  • file_name
    미국의 상왕(?)이라는 소문이 있는 오바마 전 미 대통령 사진이다.

상수값 설정

코드

min_confidence = 0.3
frame_width = 300
frame_height = 300

frame = cv2.imread(file_name)
(height, width) = frame.shape[:2]

해설

  • min_confidence
    얼굴을 검출했을 때 그 확률이 최소 30% 이상이라고 여겨지는 것에 대해 알아보겠다는 기준을 정한 것이다.
  • frame_width, frame_height
    모델이 300 x 300으로 학습되었으므로 똑같이 설정한다.
  • frame
    cv2의 기본 기능으로 위에서 설정한 오바마 사진을 불러왔다.
  • height, width
    실제 불러온 사진의 세로, 가로(아마 행-열 순인 듯). [:2]라는 지정이 된 이유는 3번째 인자가 채널인데 필요 없으니까.

model 및 blob 설정

코드

model = cv2.dnn.readNetFromCaffe(prototext_name, model_name)

blob = cv2.dnn.blobFromImage(
    cv2.resize(frame, (frame_width, frame_height)),
    1.0,
    (frame_width, frame_height),
    (104.0, 177.0, 123.0),
)

model.setInput(blob)

해설

  • model
    위에서 미리 설정한 파일경로명을 사용해 네트워크를 불러오는 것이다. readNetFromCaffe 메소드의 인자는 저 두 개 뿐이다.
  • blob
    네트워크 입력 블롭을 만든다.
    이번에 사용하는 모델이 300x300으로 학습된 모델이니 그에 맞게 이미지 파일을 300x300으로 resize한다.
    scalefactor 1.0은 입력 영상 픽셀 값에 곱할 값을 설정한 것이다.기본 값도 1이다.
    (300,300)은 원본과 같이 출력 크기도 300x300으로 지정했다.
    (104.0, 177.0, 123.0)은 RGB 값을 줘서 색상 이해를 쉽게 한다.입력 영상 각 채널에서 빼는 평균 값인 것이다.
  • model.setInput
    네트워크 입력을 설정한다. 첫번째 인자는 blob이므로 바로 위에서 설정한 blob 객체를 지정한다.

검출 실행

코드

detections = model.forward()

해설

순방향 추정 실행
결과는 아래와 같이 나온다.

검출한 부분에 대한 이미지상의 표시

코드

for i in range(detections.shape[2]):
    # extract the confidence (i.e., probability)
    confidence = detections[0, 0, i, 2]
    if confidence > min_confidence:
        box = detections[0, 0, i, 3:7] * np.array([width, height, width, height])
        (startX, startY, endX, endY) = box.astype('int')
        print(confidence, startX, startY, endX, endY)
        text = '{:.2f}%'.format(confidence * 100)
        y = startY - 10 if startY -10 > 10 else startY + 10
        cv2.rectangle(frame, (startX, startY), (endX, endY), (0, 255, 0), 2)
        cv2.putText(frame, text, (startX, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 255, 0), 1)

해설

  • for문
    detections.shape는 (1, 1, 200, 7)라는 결과값이 나온다.
    2번째 인자인 200까지 for문을 도니 200번 돈다는 뜻이다.
  • confidence
    detections의 [0, 0, i, 2] 값을 갖고 오게 되면 얼굴이라고 추정한 확률을 가져오게 된다.
  • if문
    위에서 설정했던 최소 확률인 0.3보다 confidence값이 높을 때에만 실행한다.
    이번 같은 경우 0.3을 넘는 것은 단 하나 뿐이였다.
  • box
    검출된 부분에 대한 좌표를 가져온다.
    각각 왼쪽위 X,Y, 오른쪽아래 X,Y를 가져온다.
  • 출력문

0.9999944 74 16 122 84라는 결과값이 나온다.
단 하나 검출된 것이 무조건 얼굴일 확률 99.99%라는 것이며 각각 XY 좌표를 보여준다.

  • 그 이하
    좌표를 선택해 사각형과 함께 확률을 그린다.

결과


원래는 300x300이라 작게 나오지만 크게 해 봤다.
99.999%의 확률이였으니 2자리수 반올림으로 100%로 나온 것 같다.

'Computer Vision' 카테고리의 다른 글

병변 검출 AI 경진대회(후기)  (0) 2021.12.07