🎆

007 머신러닝을 이용한 무인 상점 만들기 - 2

1. 코드

 
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 # 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.예측정보리스트 = { 0 : ["티셔츠", 5000], 1 : ["트라우저 진", 30000], 2 : ["스웨터", 15000], 3 : ["드레스", 50000], 4 : ["코트", 50000], 5 : ["샌들", 10000], 6 : ["셔츠", 15000], 7 : ["스니커즈", 30000], 8 : ["가방", 5000], 9 : ["부츠", 40000]} self.가게이름 = QLabel('라이캣의 무인가게', self) self.가게이름.setFont(QFont("Decorative", 20)) self.가게이름.adjustSize() self.가게이름.move(180, 30) self.이미지 = QLabel(self) self.이미지.move(170, 100) self.가이드 = QLabel('File을 눌러 모델 추가 후 이미지 삽입하여 인식', self) self.가이드.move(150, 500) self.가이드.adjustSize() self.계좌번호 = QLabel('(주)생선가게 위니브은행 999-999999-9999', self) self.계좌번호.move(200, 550) self.계좌번호.adjustSize() self.계좌번호.setHidden(True) self.이미지업로드 = QPushButton("이미지 업로드", self) self.이미지업로드.move(170, 430) self.이미지업로드.setEnabled(False) self.이미지업로드.clicked.connect(self.loadImage) self.결제버튼 = QPushButton("결제하기", self) self.결제버튼.move(370, 430) self.결제버튼.setEnabled(False) 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( 모델파일) self.가이드.setText('모델 추가 완료!') self.이미지업로드.setEnabled(True) except: self.가이드.setText("모델 파일이 아닙니다.") def loadImage(self): 이미지이름 = QFileDialog.getOpenFileName(self, 'Open file', './') 이미지파일 = QPixmap(이미지이름[0]).scaled( 300, 300, aspectRatioMode=Qt.KeepAspectRatio) self.이미지.setPixmap(이미지파일) self.이미지.adjustSize() if 이미지파일: 행렬 = np.zeros((28, 28)) for 행 in range(28): for 열 in range(28): 행렬[열, 행] = 1 - QImage(QPixmap(이미지이름[0]))\ .scaled(28,28).pixelColor(행, 열).getRgb()[0] / 255.0 # 이미지를 압축시켜 음영의 효과로 구분하여 요소들을 추가 행렬 = 행렬.reshape(-1, 28, 28) 예측 = self.인식모델.predict(행렬)[0] # 이미지 인식 진행 결과 = np.argmax(예측) # 제일 높게 나온 예측 값 self.가이드.setText("선택하신 제품은 " + str(self.예측정보리스트.get(결과)[0])\ + "이고 결재하실 금액은 "\ + "{:,}".format(self.예측정보리스트.get(결과)[1])\ + '원 입니다.') self.가이드.adjustSize() self.가이드.move(150, 500) self.계좌번호.setHidden(False) self.결제버튼.setEnabled(True) 프로그램무한반복 = QApplication(sys.argv) 실행인스턴스 = 무인가게프로그램() 프로그램무한반복.exec_()

4. 상세 내용

여기서는 MNIST라고 하는 예제를 사용해서 간단하게 사물인식을 해볼 예정인데요. MNIST라고 한다면 인공지능을 처음 공부해보시는 분들이 print('hello world')처럼 가장 처음에 하시는 예제입니다.
그중에서도 fashion에 관련해서 여러가지 사물을 인식할 수 있는 MNIST를 해보도록 하겠습니다. (기초 MNIST는 손글씨 인식하기 입니다.)
notion imagenotion image
notion imagenotion image
  1. GUI 설계
    1. self.store = QLabel('라이캣의 무인가게', self) self.store.setFont(QFont("Decorative", 20)) self.store.adjustSize() self.store.move(180, 30) self.label = QLabel(self) self.label.move(170, 100) self.label2 = QLabel('File을 눌러 모델 추가 후 이미지 삽입하여 인식', self) self.label2.move(150, 500) self.label2.adjustSize() self.label3 = QLabel('(주)생선가게 위니브은행 999-999999-9999', self) self.label3.move(200, 550) self.label3.adjustSize() self.label3.setHidden(True) self.uploadPicture = QPushButton("사진 업로드", self) self.uploadPicture.move(170, 430) self.uploadPicture.setEnabled(False) self.uploadPicture.clicked.connect(self.loadImage)
      • 기획에 맞게 Label, Button 위젯을 추가합니다. move를 사용하여 원하는 위치에 배치합니다.
      • setHidden(True)을 통해 최종적으로 이미지를 인식했을 때 해당 QLabel이 보여질 수 있도록 숨겨둡니다.
      • setEnabled(False)을 통해 인식 모델이 성공적으로 추가가 되어야만 버튼이 활성화 되어 사용자가 이미지를 선택할 수 있도록 만들도록 하겠습니다. 잘못된 파일이 올라가서 활성화가 안될 경우에는 계속해서 False인 상태로 남게 됩니다.
      self.Model = None menubar = self.menuBar() menubar.setNativeMenuBar(False) filemenu = menubar.addMenu('File') load_model = QAction('모델 불러오기', self) load_model.setShortcut('Ctrl+L') load_model.triggered.connect(self.loadModel) filemenu.addAction(load_model)
      • 모델이 정상적으로 추가되었는지 판단하기 위해 self.Model 변수 추가합니다.
      • 메뉴바를 생성하여 모델 불러오기 기능을 추가합니다.
      여기서 어떻게 물체를 인식할 수 있는지, 머신러닝은 어떻게 학습을 하는지는 강의의 범주를 넘어선다 생각하여 아래 문서로 대체합니다. 영상 강의에서는 이 부분을 좀 더 상세하게 다룹니다.
      • 실행 결과
        • notion imagenotion image
           
  1. 인식 모델은 어떻게 동작할까?
    1. notion imagenotion image
      • 위 이미지 중 fashion.h5를 다운로드 받아주시면 됩니다.
       
      • 앞서 한 번 보여드렸던 모델이 인식할 수있는 이미지에 레이블입니다.
        • notion imagenotion image
           
      • 인식된 결과값을 나타내기 위해 딕셔너리로 정의해 매핑합니다.
        • self.예측정보리스트 = { 0 : ["티셔츠", 5000], 1 : ["트라우저 진", 30000], 2 : ["스웨터", 15000], 3 : ["드레스", 50000], 4 : ["코트", 50000], 5 : ["샌들", 10000], 6 : ["셔츠", 15000], 7 : ["스니커즈", 30000], 8 : ["가방", 5000], 9 : ["부츠", 40000]}
       
      • 모델 추가 함수 작성
        • def loadModel(self): try: fname, _ = QFileDialog.getOpenFileName(self, '모델 추가', '') if fname: self.Model = tf.keras.models.load_model( fname) self.label2.setText('모델 추가 완료!') self.uploadPicture.setEnabled(True) except: self.label2.setText("모델 파일이 아닙니다.")
        • QFileDialog.getOpenFileName ()을 통해 파일을 가져옵니다.
        • tf.keras.models.load_mode(모델 파일)을 통해 인식 모델을 추가합니다.
        • setEnabled(True)로 이미지 추가 버튼 활성화 합니다.
        • 모델이 아닌 다른 파일을 넣어 오류가 날 경우를 대비하여 try-except 문으로 구성합니다.
        •  
  1. 이미지 추가 함수 작성
    1. def loadImage(self): iname = QFileDialog.getOpenFileName(self, 'Open file', './') image = QPixmap(iname[0]).scaled( 300, 300, aspectRatioMode=Qt.KeepAspectRatio) # 라벨에 표시해주기 위해 압축을 진행 self.label.setPixmap(image) self.label.adjustSize()
      • getOpenFileName()으로 파일 가져오기
      • scaled 함수를 통해 이미지가 크더라도 라벨 크기에 맞도록 압축을 진행
       
      • 이미지 인식 코드
        • if image: arr = np.zeros((28, 28)) # 28X 28의 행렬을 만들어 for i in range(28): for j in range(28): arr[j, i] = 1 - QImage(QPixmap(iname[0])).scaled(28, 28)\ .pixelColor(i, j).getRgb()[0] / 255.0 arr = arr.reshape(-1, 28, 28) predictions = self.Model.predict(arr)[0] result = np.argmax(predictions) self.가이드.setText("선택하신 제품은 "\ + str(self.예측정보리스트.get(결과)[0])\ + "이고 결재하실 금액은 "\ + "{:,}".format(self.예측정보리스트.get(결과)[1])\ + '원 입니다.')
           
  • 간단히 설명하자면 이미지 인식은 이미지를 행렬형태로 변환하여 음영의 효과로 구분하여 각 행렬의 값을 높여 인식합니다. 즉, 행렬의 요소를 파악하여 이미지 인식 진행합니다.
  • np.zeros((28, 28)) : 28x28의 행렬을 만들고
    • arr[j, i] = 1 - QImage(QPixmap(iname[0])).scaled(28,28)\ .pixelColor(i, j).getRgb()[0] / 255.0
  • 모델은 아래와 같은 행렬의 형태로 학습이 진행됩니다. 아래 이미지는 '신발'입니다.
  • 즉, 이미지를 압축시켜 rgb값을 통해 음영의 효과로 구분하여 각 행렬의 값을 증가시킵니다.
    • notion imagenotion image
       

5. 실행 화면

notion imagenotion image
 
notion imagenotion image
 
notion imagenotion image
notion imagenotion image