🎆

008 머신러닝을 이용한 마스크 자동 인식기 만들기

1. 스토리

모든 가게를 무인화 했지만, 코로나19로 인해 대리인 No.1은 매장에 출입하는 모든 사람들이 마스크를 쓰도록하는 프로그램을 만들기로 하였습니다.
"이미 만들어진 코드를 기반으로 짜보자냥!"

2. 코드

import sys from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * import numpy as np #pip install numpy import tensorflow as tf from PIL import Image, ImageOps # pip install --upgrade pip # pip install tensorflow # python이 32bit으로 깔려있다면, 오류가 남 -> window에서 지워주시고 다시 64비트로 설치해주세요. # ERROR: Could not find a version that satisfies the requirement tensorflow (from versions: none) # ERROR: No matching distribution found for tensorflow class 마스크경고음(QMainWindow): def __init__(self): super().__init__() self.UI초기화() def UI초기화(self): self.대표이미지 = QLabel(self) #이미지 원본 크기 : 175, 220 self.대표이미지.setPixmap(QPixmap('img/weniv-licat.png').scaled(35, 44)) self.대표이미지.move(20, 65) self.대표이미지.resize(35, 44) self.가게이름 = QLabel('라이캣의 무인가게 마스크 경고음', self) self.가게이름.setFont(QFont("Decorative", 15)) self.가게이름.adjustSize() self.가게이름.move(80, 70) self.이미지 = QLabel(self) self.이미지.move(200, 180) self.가이드 = QLabel('상단바 File을 눌러 모델 추가 후 이미지를 삽입하여 인식합니다.', self) self.가이드.move(40, 500) self.가이드.adjustSize() self.마스크경고 = QLabel('마스크를 써주세요!!', self) self.마스크경고.move(200, 550) self.마스크경고.adjustSize() self.마스크경고.setHidden(True) self.이미지업로드 = QPushButton("파일 업로드", self) self.이미지업로드.move(170, 430) self.이미지업로드.resize(240, 40) self.이미지업로드.setEnabled(False) self.이미지업로드.clicked.connect(self.loadImage) self.인식모델 = None 메뉴바 = self.menuBar() 메뉴바.setNativeMenuBar(False) 파일메뉴 = 메뉴바.addMenu('File') 모델불러오기메뉴 = QAction('모델 불러오기', self) 모델불러오기메뉴.setShortcut('Ctrl+L') 모델불러오기메뉴.triggered.connect(self.loadModel) 파일메뉴.addAction(모델불러오기메뉴) self.setWindowTitle('(주)캣네생선 무인상점 마스크 경고음 프로그램') self.setGeometry(300, 300, 600, 600) self.show() def loadModel(self): try: 모델파일, _ = QFileDialog.getOpenFileName(self, '모델 추가', '') if 모델파일: self.인식모델 = tf.keras.models.load_model(모델파일, compile=False) self.가이드.setText('모델 추가 완료!') self.이미지업로드.setEnabled(True) except: self.가이드.setText("모델 파일이 아닙니다.") def loadImage(self): ## 추가 np.set_printoptions(suppress=True) data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32) 이미지이름 = QFileDialog.getOpenFileName(self, 'Open file', './') 이미지파일 = QPixmap(이미지이름[0])\ .scaled(200, 200, aspectRatioMode=Qt.KeepAspectRatio) self.이미지.setPixmap(이미지파일) self.이미지.adjustSize() if 이미지파일: #추가 print(이미지이름) image = Image.open(이미지이름[0]) size = (224, 224) image = ImageOps.fit(image, size, Image.ANTIALIAS) image_array = np.asarray(image) # Normalize the image normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1 # Load the image into the array data[0] = normalized_image_array # run the inference prediction = self.인식모델.predict(data) print(prediction) l = list(prediction[0]) print(l) if l.index(max(l)) == 0: print('노마스크') self.마스크경고.setHidden(False) elif l.index(max(l)) == 1: print('마스크') self.마스크경고.setHidden(False) self.마스크경고.setText('마스크를 써주셔서 감사합니다.') 프로그램무한반복 = QApplication(sys.argv) 실행인스턴스 = 마스크경고음() 프로그램무한반복.exec_()
 

3. 코드설명

이미 앞 챕터에서 대부분 설명했던 내용이며, 모델을 학습하기 위해 코드를 짠 것이 아니라 teachablemachine를 이용해 학습을 시켰습니다.
 
해당 튜토리얼은 유튜브로도 업로드 해두었으니 영상을 확인해주세요.
Video preview
 
Code는 모두 Teachable Machine에서 제공하는 코드입니다. 아래 코드를 참고해주세요.
import tensorflow.keras from PIL import Image, ImageOps import numpy as np # Disable scientific notation for clarity np.set_printoptions(suppress=True) # Load the model model = tensorflow.keras.models.load_model('keras_model.h5') # Create the array of the right shape to feed into the keras model # The 'length' or number of images you can put into the array is # determined by the first position in the shape tuple, in this case 1. data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32) # Replace this with the path to your image image = Image.open('test_photo.jpg') #resize the image to a 224x224 with the same strategy as in TM2: #resizing the image to be at least 224x224 and then cropping from the center size = (224, 224) image = ImageOps.fit(image, size, Image.ANTIALIAS) #turn the image into a numpy array image_array = np.asarray(image) # display the resized image image.show() # Normalize the image normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1 # Load the image into the array data[0] = normalized_image_array # run the inference prediction = model.predict(data) print(prediction)
 
제공되는 코드 중 수정한 부분은 아래와 같습니다.
model = tensorflow.keras.models.load_model('keras_model.h5')
 
기존에 티쳐블머신에서 제공한 코드입니다. 이 코드가 아래 함수에서 self.인식모델로 바뀌었어요.
def loadModel(self): try: 모델파일, _ = QFileDialog.getOpenFileName(self, '모델 추가', '') if 모델파일: self.인식모델 = tf.keras.models.load_model(모델파일, compile=False) self.가이드.setText('모델 추가 완료!') self.이미지업로드.setEnabled(True) except: self.가이드.setText("모델 파일이 아닙니다.")
 
나머지 코드는 가능하면 재사용하려고 주석도 그대로 달아두었습니다.
def loadImage(self): ## 추가 np.set_printoptions(suppress=True) data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32) 이미지이름 = QFileDialog.getOpenFileName(self, 'Open file', './') 이미지파일 = QPixmap(이미지이름[0])\ .scaled(200, 200, aspectRatioMode=Qt.KeepAspectRatio) self.이미지.setPixmap(이미지파일) self.이미지.adjustSize() if 이미지파일: #추가 print(이미지이름) image = Image.open(이미지이름[0]) size = (224, 224) image = ImageOps.fit(image, size, Image.ANTIALIAS) image_array = np.asarray(image) # Normalize the image normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1 # Load the image into the array data[0] = normalized_image_array # run the inference prediction = self.인식모델.predict(data) print(prediction) l = list(prediction[0]) print(l) if l.index(max(l)) == 0: print('노마스크') self.마스크경고.setHidden(False) elif l.index(max(l)) == 0: print('마스크') self.마스크경고.setHidden(False) self.마스크경고.setText('마스크를 써주셔서 감사합니다.')