728x90

스파르타 코딩클럽의 딥러닝 이미지 처리 수업을 기반으로 공부한 내용을 정리하고 있습니다.

 

사용된 모델 관련된 아티클 : www.pyimagesearch.com/2020/05/04/covid-19-face-mask-detector-with-opencv-keras-tensorflow-and-deep-learning/

 

이미 학습된 모델을 기반으로 주어진 데이터들을 추론하는 연습을 하는 거라, 모델 자체를 학습하고 만드는 과정에 대한 내용은 없습니다

 

딥러닝 모델을 만들수 있는 일종의 패키지로서 tensorflow를 사용할 것이다. 

 

기존에 만들어진 모델 중, 얼굴을 탐지하는 모델은 deploy.prototxt 와 res10 이며, 이는 cv2의 dnn을 통해서 불러올 것이다.

이와 다르게 마스크를 탐지하는 mask detector 모델은 tensorflow의 load model을 통해 불러올 것이다.

(해당 모델들은 내가 만든 것이 아니라 누군가가 만들어 놓은 모델을 가지고 온것!)

1
2
3
4
5
6
7
8
9
10
11
#필요한 패키지 로드하기
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')
cs

 

얼굴 영역 탐지하기

 

입력값이 이미지(동영상이 이미지로 이루어져있으므로), 출력값이 confidence와 얼굴의 영역 위치이다. 

얼굴 영역에서 가장 핵심은 얼굴영역의 x,y 좌표를 구하는 것이다. 

 

confidence 라는 개념이 등장하는데, 일종의 확률과 비슷한 의미이다. 딥러닝 모델이 얼굴이라고 인지하는 영역을 잡아내고, confidence로 해당 영역이 얼굴이라고 인지하는데 확신하는 확률을 표시한다. 

이때 1에 가까울수록 자신감이 넘치고, 즉 얼굴일 가능성이 높고, 낮을수록 얼굴일 확률이 낮은 것이다. 

 

따라서 엄격하게 검사하고 싶으면 confidence의 임계치를 높이고, 자유롭게 검사하고 싶으면 임계치를 낮추면 된다. 

따라서 임의로 confidence가 0.5보다 작으면 얼굴이 아니라고 지정해준다.

 

이후 결과 출력값이 즉, 얼굴의 위치가 x,y축에서의 %로 표시된다. 즉 가장 꼭지점을 0%로 본다면, 특정 얼굴의 위치를 x가 몇%, y가 몇%로 나오는 것이다. 따라서 원래 이미지의 길이를 곱해주면 진짜 위치가 나오게 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
while True:
    ret, img = cap.read()
 
    if ret == False:
        break
 
    h, w, c = img.shape
    # 이미지 전처리하기(이미지를 blobFromImage를 통해 blob 처리하기)
    # 리사이즈도 진행하고, 전처리에서 mean 값도 정의하기
    blob = cv2.dnn.blobFromImage(img, size=(300300), mean=(104.177.123.))
 
    # 얼굴 영역 탐지 모델로 추론하기
    facenet.setInput(blob)
    # dets 변수에 얼굴 영역 탐지결과가 저장된다. 
    dets = facenet.forward()
 
    # 위에서 저장된 각 얼굴 탐지를 반복문을 돌면서 처리를 해주는 것이다. 왜냐면 영상에서 얼굴의 갯수가 여러개일 수 있기 때문
    # 각 얼굴에 대해서 반복문 돌기
    for i in range(dets.shape[2]):
        confidence = dets[00, i, 2]
 
        #즉 confidence 수치가 0.5보다 작은 경우는 그냥 넘어간다. 
        if confidence < 0.5:
            continue
 
        # 사각형 꼭지점 찾기
        x1 = int(dets[00, i, 3* w) 
        # dets에서는 x의 위치가 %로 나오고 여기에 이미지의 길이인 w를 곱해주면 된다. 
        y1 = int(dets[00, i, 4* h)
        x2 = int(dets[00, i, 5* w)
        y2 = int(dets[00, i, 6* h)
 
        face = img[y1:y2, x1:x2]
 
        # 사각형 그리기
        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
cs

 

마스크 탐지하기

마스크 탐지에서는 입력값이 위의 얼굴 탐지의 출력값인 얼굴 위치와 그 confidence이고 출력값이 마스크 착용에 대한 confidence이다.

아래의 코드를 얼굴영역을 탐지해서 출력한 코드와 그 영역에 따라 사각형을 그리는 코드 사이에 넣어준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        # 마스크 탐지하는 영역에 대한 전처리
        # 1. 우선 얼굴 영역 이미지를 리사이즈하기
        face_input = cv2.resize(face, dsize=(224224))
        # 2. BGR에서 RGB로 컬러시스템 바꿔주기
        face_input = cv2.cvtColor(face_input, cv2.COLOR_BGR2RGB)
        # 3. preprocess_input 해당 함수가 전처리에서 필수
        face_input = preprocess_input(face_input)
        # 4. 차원 변형, 0번 축에 차원을 추가 해줌. 해당 코드의 결과가 (1,224,224,3)의 형태가 될 것.
        face_input = np.expand_dims(face_input, axis=0)
 
        # 해당 코드로 추론 과정을 거친다. mask에는 마스크를 쓴 confidence / no mask에는 안쓴 confidence가 출력
        mask, nomask = model.predict(face_input).squeeze()
 
        if mask > nomask:
          color = (02550)
        else:
          color = (0,0,255)
cs

 

-> 만약에 마스크 착용 여부에 대해 인지한 confidence를 표시해 주고 싶다면? 

1
2
3
4
5
6
7
8
9
10
        if mask > nomask:
            color = (02550)
            #기본적으로 0.333 같이 백분율이 아닌 수치로 표시되므로, 아래와 같이 100을 곱하고 소수점자리를 날린다.
            label = 'Mask %d%%' % (mask * 100)
        else:
            color = (00255)
            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)
cs

 

728x90

+ Recent posts