딥러닝

딥러닝 3주차_마스크 착용 여부, 성별 나이 예측

끈끈 2023. 5. 18. 04:27

 

✅ 수업 목표

[COVID-19] 마스크를 썼는지 안썼는지 알아내는 인공지능 만들기

  1. 얼굴 영역 탐지 모델과 마스크 판단 모델의 두 개 모델을 결합한다
  2. 텐서플로 모델을 사용하여 추론하는 방법을 배운다

 

머신러닝

 

Supervised Learning (지도학습) : 해답과 데이터를 가지고 규칙을 찾아내는 일

 

Unsupervised Learning (비지도학습) : 데이터만을 가지고 규칙을 찾아내는 일

 

  • OR, AND모델

 

 

  • XOR 모델 ( 파란색 : False , 빨간색 : True )

 

 

  • Loss Function과 Optimizer

 

optimizer는 input 값에 주는 weight를 feedback을 통해 조금씩 바꿔가면서 머신의 성능을 개선함

 

 


 

패키지 불러오기

 

from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
import numpy as np
import cv2

 

모델 로드하기

 

facenet 이 얼굴 영역 탐지 모델

 

model 이 마스크 판단 모델

 

facenet = cv2.dnn.readNet('models/deploy.prototxt', 'models/res10_300x300_ssd_iter_140000.caffemodel')
model = load_model('models/mask_detector.model')

 

동영상 플레이어부터 만들기

 

cap = cv2.VideoCapture('videos/04.mp4')

while True:
    ret, img = cap.read()

    if ret == False:
        break

		cv2.imshow('result', img)
    if cv2.waitKey(1) == ord('q'):
        break

 

얼굴 영역 탐지

 

얼굴 영역 탐지하기

 

from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
import numpy as np
import cv2

facenet = cv2.dnn.readNet('models/deploy.prototxt', 'models/res10_300x300_ssd_iter_140000.caffemodel')
model = load_model('models/mask_detector.model')

cap = cv2.VideoCapture('videos/04.mp4')

while True:
    ret, img = cap.read() # 한 프레임씩 받아와서

    if ret == False:
        break

    h, w, c = img.shape
    
    # 이미지 전처리하기 # mean은 커피를 맛있게 하기 위해 빼주는 값
    blob = cv2.dnn.blobFromImage(img, size=(300, 300), mean=(104., 177., 123.))

    # 얼굴 영역 탐지 모델로 추론하기
    facenet.setInput(blob)
    dets = facenet.forward() # 얼굴 영역 좌표 저장

    # 각 얼굴에 대해서 반복문 돌기
    for i in range(dets.shape[2]): # range(dets.shape[2]) → 얼굴의 개수
        confidence = dets[0, 0, i, 2] # confidence → 1에 가까울수록 진짜 얼굴 확신

        if confidence < 0.5: # confidence의 임계치 설정
            continue

        # 이미지가 모델에 들어갈 때 resize가 되어 들어가므로
        # 이미지의 너비와 높이를 다시 곱해주어 원래 좌표로 복원
        # 사각형 꼭지점 찾기
        x1 = int(dets[0, 0, i, 3] * w)
        y1 = int(dets[0, 0, i, 4] * h)
        x2 = int(dets[0, 0, i, 5] * w)
        y2 = int(dets[0, 0, i, 6] * h)

        # 사각형 그리기
        cv2.rectangle(img, pt1=(x1, y1), pt2=(x2, y2), thickness=2, color=(0, 255, 0))

    cv2.imshow('result', img)
    if cv2.waitKey(1) == ord('q'):
        break

 

마스크 착용 여부 판단

 

얼굴 영역 잘라내고 전처리하기

 

아래 코드 반복문 안에 붙여넣기

 

# 잘라낸 얼굴 저장
face = img[y1:y2, x1:x2]

face_input = cv2.resize(face, dsize=(224, 224)) # 가로 224, 세로 224 크기로 변형
face_input = cv2.cvtColor(face_input, cv2.COLOR_BGR2RGB) # 컬러 시스템을 BGR에서 RGB로 변경
face_input = preprocess_input(face_input) # preprocess_input 명령어에 넣어 전처리 연산
face_input = np.expand_dims(face_input, axis=0) # 0번 축의 차원을 하나 늘려서 전처리 과정 마치기

 

결과 추론하기

 

mask, nomask = model.predict(face_input).squeeze()

 

결과 표시하기

 

if mask > nomask:
    color = (0, 255, 0)
else:
    color = (0, 0, 255)

cv2.rectangle(img, pt1=(x1, y1), pt2=(x2, y2), thickness=2, color=color)

 

 

전체 코드

 

더보기
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
import numpy as np
import cv2

facenet = cv2.dnn.readNet('models/deploy.prototxt', 'models/res10_300x300_ssd_iter_140000.caffemodel')
model = load_model('models/mask_detector.model')

cap = cv2.VideoCapture('videos/04.mp4')

while True:
    ret, img = cap.read()

    if ret == False:
        break

    h, w, c = img.shape

    # 이미지 전처리하기
    blob = cv2.dnn.blobFromImage(img, size=(300, 300), mean=(104., 177., 123.))

    # 얼굴 영역 탐지 모델로 추론하기
    facenet.setInput(blob)
    dets = facenet.forward()

    # 각 얼굴에 대해서 반복문 돌기
    for i in range(dets.shape[2]):
        confidence = dets[0, 0, i, 2]

        if confidence < 0.5:
            continue

        # 사각형 꼭지점 찾기
        x1 = int(dets[0, 0, i, 3] * w)
        y1 = int(dets[0, 0, i, 4] * h)
        x2 = int(dets[0, 0, i, 5] * w)
        y2 = int(dets[0, 0, i, 6] * h)

        # 잘라낸 얼굴 저장
        face = img[y1:y2, x1:x2]

        face_input = cv2.resize(face, dsize=(224, 224))
        face_input = cv2.cvtColor(face_input, cv2.COLOR_BGR2RGB)
        face_input = preprocess_input(face_input)
        face_input = np.expand_dims(face_input, axis=0)

        mask, nomask = model.predict(face_input).squeeze()

        if mask > nomask:
            color = (0, 255, 0)
        else:
            color = (0, 0, 255)

        cv2.rectangle(img, pt1=(x1, y1), pt2=(x2, y2), thickness=2, color=color)

    cv2.imshow('result', img)
    if cv2.waitKey(1) == ord('q'):
        break

 


 

성별, 나이를 예측하는 모델 준비하기

 

모델 로드하기

 

gender_list = ['Male', 'Female']
age_list = ['(0, 2)','(4, 6)','(8, 12)','(15, 20)','(25, 32)','(38, 43)','(48, 53)','(60, 100)']
# age_list 8개의 인덱스

gender_net = cv2.dnn.readNetFromCaffe('models/deploy_gender.prototxt', 'models/gender_net.caffemodel')
age_net = cv2.dnn.readNetFromCaffe('models/deploy_age.prototxt', 'models/age_net.caffemodel')

 

전처리하기

 

blob = cv2.dnn.blobFromImage(face, size=(227, 227), mean=(78.4263377603, 87.7689143744, 114.895847746))

 

추론하기

 

gender_net.setInput(blob)
gender_index = gender_net.forward().squeeze().argmax()
gender = gender_list[gender_index]

age_net.setInput(blob)
age_index = age_net.forward().squeeze().argmax()
age = age_list[age_index]

 

결과 출력하기

 

cv2.putText(img, '%s, %s' % (gender, age), org=(x1, y1), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(0,255,0), thickness=2)

 

 

전체 코드

 

더보기
import numpy as np
import cv2

facenet = cv2.dnn.readNet('models/deploy.prototxt', 'models/res10_300x300_ssd_iter_140000.caffemodel')

gender_list = ['Male', 'Female']
age_list = ['(0, 2)','(4, 6)','(8, 12)','(15, 20)','(25, 32)','(38, 43)','(48, 53)','(60, 100)']

gender_net = cv2.dnn.readNetFromCaffe('models/deploy_gender.prototxt', 'models/gender_net.caffemodel')
age_net = cv2.dnn.readNetFromCaffe('models/deploy_age.prototxt', 'models/age_net.caffemodel')

img = cv2.imread('imgs/02.jpg')

h, w, c = img.shape

# 이미지 전처리하기
blob = cv2.dnn.blobFromImage(img, size=(300, 300), mean=(104., 177., 123.))

# 얼굴 영역 탐지 모델로 추론하기
facenet.setInput(blob)
dets = facenet.forward()

# 각 얼굴에 대해서 반복문 돌기
for i in range(dets.shape[2]):
    confidence = dets[0, 0, i, 2]

    if confidence < 0.5:
        continue

    # 사각형 꼭지점 찾기
    x1 = int(dets[0, 0, i, 3] * w)
    y1 = int(dets[0, 0, i, 4] * h)
    x2 = int(dets[0, 0, i, 5] * w)
    y2 = int(dets[0, 0, i, 6] * h)

    face = img[y1:y2, x1:x2]

    blob = cv2.dnn.blobFromImage(face, size=(227, 227), mean=(78.4263377603, 87.7689143744, 114.895847746))

    gender_net.setInput(blob)
    gender_index = gender_net.forward().squeeze().argmax()
    gender = gender_list[gender_index]

    age_net.setInput(blob)
    age_index = age_net.forward().squeeze().argmax()
    age = age_list[age_index]

    cv2.rectangle(img, pt1=(x1, y1), pt2=(x2, y2), color=(255, 0, 0), thickness=2)
    cv2.putText(img, '%s, %s' % (gender, age), org=(x1, y1), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1, color=(0,255,0), thickness=2)


cv2.imshow('result', img)
cv2.waitKey(0)

 


 

숙제

 

더보기
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from tensorflow.keras.models import load_model
import numpy as np
import cv2

facenet = cv2.dnn.readNet('models/deploy.prototxt', 'models/res10_300x300_ssd_iter_140000.caffemodel')
model = load_model('models/mask_detector.model')

cap = cv2.VideoCapture('videos/02.mp4')

while True:
    ret, img = cap.read()

    if ret == False:
        break

    h, w, c = img.shape

    # 이미지 전처리하기
    blob = cv2.dnn.blobFromImage(img, size=(300, 300), mean=(104., 177., 123.))

    # 얼굴 영역 탐지 모델로 추론하기
    facenet.setInput(blob)
    dets = facenet.forward()

    # 각 얼굴에 대해서 반복문 돌기
    for i in range(dets.shape[2]):
        confidence = dets[0, 0, i, 2]

        if confidence < 0.5:
            continue

        # 사각형 꼭지점 찾기
        x1 = int(dets[0, 0, i, 3] * w)
        y1 = int(dets[0, 0, i, 4] * h)
        x2 = int(dets[0, 0, i, 5] * w)
        y2 = int(dets[0, 0, i, 6] * h)

        # 잘라낸 얼굴 저장
        face = img[y1:y2, x1:x2]

        face_input = cv2.resize(face, dsize=(224, 224))
        face_input = cv2.cvtColor(face_input, cv2.COLOR_BGR2RGB)
        face_input = preprocess_input(face_input)
        face_input = np.expand_dims(face_input, axis=0)

        mask, nomask = model.predict(face_input).squeeze()

        if mask > nomask:
            color = (0, 255, 0)
            label = 'Mask %d%%' % (mask * 100)
        else:
            color = (0, 0, 255)
            label = 'No Mask %d%%' % (nomask * 100)

        cv2.rectangle(img, pt1=(x1, y1), pt2=(x2, y2), thickness=2, color=color)
        cv2.putText(img, text=label, org=(x1, y1 - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.8, color=color, thickness=2)

    cv2.imshow('result', img)
    if cv2.waitKey(1) == ord('q'):
        break