Concept
지난 포스팅에 이어, 얼굴 인식 후 적용할 수 있는 성별 및 나이 예측 알고리즘입니다. 모두 파이썬 기반 OpenCV를 통해 구현하였으며 지난 포스팅을 참고하시면 기본적인 얼굴 탐지 알고리즘을 구현할 수 있습니다.
Algorithm
비교적 단순한 구조를 가지는 CNN 기반 신경망 모델입니다. 얼굴 탐지를 통해 예측된 얼굴의 위치 (경계 상자)를 기준으로 이미지를 추출한 뒤, 성별 또는 연령 데이터에 학습된 분류기에 입력하는 방식입니다.
MNIST나 강아지 고양이 분류 모델과 구조적으로 동일하며 그림 1과 같이 입력 영상과 출력 클래스가 다를 뿐이죠.
SourceCode
전체 코드는 깃허브를 통해 공유하고 있습니다. 링크를 참조해주세요.
github.com/DEEPI-LAB/python-opencv-face-detector.git
git clone https://github.com/DEEPI-LAB/python-opencv-face-detector.git
구글 드라이브 링크를 통해 학습된 가중치를 다운받으세요. 얼굴 탐지기, 성별 분류기, 연령 분류기 학습 가중치이며 90mb 정도 됩니다. 이후 코드가 작성될 경로로 복사해주시면 됩니다.
1. 사전학습된 가중치 파일 불러오기
MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
# 언령 예측 모델 불러오기
age_net = cv2.dnn.readNetFromCaffe(
'deploy_age.prototxt',
'age_net.caffemodel')
# 성별 예측 모델 불러오기
gender_net = cv2.dnn.readNetFromCaffe(
'deploy_gender.prototxt',
'gender_net.caffemodel')
# 연령 클래스
age_list = ['(0 ~ 2)','(4 ~ 6)','(8 ~ 12)','(15 ~ 20)',
'(25 ~ 32)','(38 ~ 43)','(48 ~ 53)','(60 ~ 100)']
# 성별 클래스
gender_list = ['Male', 'Female']
readNetFromCaffe 함수로 연령과 성별 예측 모델을 불러옵니다. 학습된 클래스는 age_list와 gender_list로 표현됩니다. 연령의 경우 분포도가 조금 신기합니다. 20세 이하 클래스에 대해선 분포도가 촘촘하네요.
만약 최종적으로 예측된 age_net의 결과가 1, gender_net의 결과가 0이라면 성별은 남자, 연령은 4 ~ 6세로 예측된 겁니다.
2. 인식된 얼굴을 기준으로 성별 및 연령 예측하기
for box in results:
# 예측된 얼굴의 위치
x, y, w, h = box
# 얼굴 이미지 추출
face = img[int(y):int(y+h),int(x):int(x+h)].copy()
# 성별 및 연령 예측을 위한 이미지 변환 맟 전처리
blob = cv2.dnn.blobFromImage(face, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
# gender detection
gender_net.setInput(blob)
gender_preds = gender_net.forward()
# 가장 높은 Score값을 선정
gender = gender_preds.argmax()
# Predict age
age_net.setInput(blob)
age_preds = age_net.forward()
# 가장 높은 Score값을 선정
age = age_preds.argmax()
info = gender_list[gender] +' '+ age_list[age]
cv2.rectangle(img, (x,y), (x+w, y+h), (255,255,255), thickness=2)
cv2.putText(img,info,(x,y-10),0, 0.5, (0, 255, 0), 1)
인식된 얼굴을 기준으로 성별과 연령 예측 모델을 입력한 뒤, cv2.putText()로 예측된 정보를 경계 상자 테두리에 입력해줍니다.
3. 전체 소스코드
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 4
@author: jongwon Kim
Deep.I Inc.
"""
import cv2
# 영상 검출기
def videoDetector(cam,cascade,age_net,gender_net,MODEL_MEAN_VALUES,age_list,gender_list):
while True:
# 캡처 이미지 불러오기
ret,img = cam.read()
# 영상 압축
try:
img = cv2.resize(img,dsize=None,fx=1.0,fy=1.0)
except: break
# 그레이 스케일 변환
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cascade 얼굴 탐지 알고리즘
results = cascade.detectMultiScale(gray, # 입력 이미지
scaleFactor= 1.1,# 이미지 피라미드 스케일 factor
minNeighbors=5, # 인접 객체 최소 거리 픽셀
minSize=(20,20) # 탐지 객체 최소 크기
)
for box in results:
x, y, w, h = box
face = img[int(y):int(y+h),int(x):int(x+h)].copy()
blob = cv2.dnn.blobFromImage(face, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
# gender detection
gender_net.setInput(blob)
gender_preds = gender_net.forward()
gender = gender_preds.argmax()
# Predict age
age_net.setInput(blob)
age_preds = age_net.forward()
age = age_preds.argmax()
info = gender_list[gender] +' '+ age_list[age]
cv2.rectangle(img, (x,y), (x+w, y+h), (255,255,255), thickness=2)
cv2.putText(img,info,(x,y-15),0, 0.5, (0, 255, 0), 1)
# 영상 출력
cv2.imshow('facenet',img)
if cv2.waitKey(1) > 0:
break
# 사진 검출기
def imgDetector(img,cascade,age_net,gender_net,MODEL_MEAN_VALUES,age_list,gender_list):
# 영상 압축
img = cv2.resize(img,dsize=None,fx=1.0,fy=1.0)
# 그레이 스케일 변환
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# cascade 얼굴 탐지 알고리즘
results = cascade.detectMultiScale(gray, # 입력 이미지
scaleFactor= 1.5,# 이미지 피라미드 스케일 factor
minNeighbors=5, # 인접 객체 최소 거리 픽셀
minSize=(20,20) # 탐지 객체 최소 크기
)
for box in results:
x, y, w, h = box
face = img[int(y):int(y+h),int(x):int(x+h)].copy()
blob = cv2.dnn.blobFromImage(face, 1, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
# gender detection
gender_net.setInput(blob)
gender_preds = gender_net.forward()
gender = gender_preds.argmax()
# Predict age
age_net.setInput(blob)
age_preds = age_net.forward()
age = age_preds.argmax()
info = gender_list[gender] +' '+ age_list[age]
cv2.rectangle(img, (x,y), (x+w, y+h), (255,255,255), thickness=2)
cv2.putText(img,info,(x,y-15),0, 0.5, (0, 255, 0), 1)
# 사진 출력
cv2.imshow('facenet',img)
cv2.waitKey(10000)
# 얼굴 탐지 모델 가중치
cascade_filename = 'haarcascade_frontalface_alt.xml'
# 모델 불러오기
cascade = cv2.CascadeClassifier(cascade_filename)
MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
age_net = cv2.dnn.readNetFromCaffe(
'deploy_age.prototxt',
'age_net.caffemodel')
gender_net = cv2.dnn.readNetFromCaffe(
'deploy_gender.prototxt',
'gender_net.caffemodel')
age_list = ['(0 ~ 2)','(4 ~ 6)','(8 ~ 12)','(15 ~ 20)',
'(25 ~ 32)','(38 ~ 43)','(48 ~ 53)','(60 ~ 100)']
gender_list = ['Male', 'Female']
# 영상 파일
cam = cv2.VideoCapture('sample.mp4')
# 이미지 파일
img = cv2.imread('sample.jpg')
# 영상 탐지기
videoDetector(cam,cascade,age_net,gender_net,MODEL_MEAN_VALUES,age_list,gender_list )
# 사진 탐지기
# imgDetector(img,cascade,age_net,gender_net,MODEL_MEAN_VALUES,age_list,gender_list )
Your Best AI Partner DEEP.I
AI 바우처 공급 기업
객체 추적 및 행동 분석 솔루션 | 제조 생산품 품질 검사 솔루션 | AI 엣지 컴퓨팅 시스템 개발
인공지능 프로젝트 개발 외주 및 상담
E-mail: contact@deep-i.ai
Site: www.deep-i.ai
'Python > Python' 카테고리의 다른 글
[Python] 파이썬에서 매트랩 MAT 파일 읽기 (scipy) (0) | 2021.02.06 |
---|---|
[Python] Windows에서 파이썬 아나콘다 가상 환경 만들기 (0) | 2021.01.13 |
[Python] 파이썬을 이용한 DBSCAN 군집화 알고리즘 구현 (0) | 2020.12.08 |
[YOLO] 객체 탐지 알고리즘 학습을 위한 이미지 데이터 라벨링 #3 YOLO 라벨링 프로그램 (2) | 2020.12.02 |
[Python] 파이썬을 이용한 다층신경망 (Multi-Layer Perceptron: MLP) 구현하기 (XOR 문제) (0) | 2020.11.28 |