최성환

마스크 디텍션 출력

1 +# USAGE
2 +# python detect_mask_video.py
3 +
4 +# import the necessary packages
5 +from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
6 +from tensorflow.keras.preprocessing.image import img_to_array
7 +from tensorflow.keras.models import load_model
8 +from imutils.video import VideoStream
9 +import numpy as np
10 +import argparse
11 +import imutils
12 +import time
13 +import os
14 +
15 +import cv2
16 +import sys
17 +from PyQt5 import QtCore
18 +from PyQt5 import QtWidgets
19 +from PyQt5 import QtGui
20 +
21 +class ShowVideo(QtCore.QObject):
22 +
23 + flag = 0
24 +
25 + camera = cv2.VideoCapture(0) # 연결된 영상장치 index, 기본은 0
26 +
27 + ret, image = camera.read() # 2개의 값 리턴, 첫 번째는 프레임 읽음여부, 두 번째는 프레임 자체
28 + height, width = image.shape[:2]
29 +
30 + VideoSignal1 = QtCore.pyqtSignal(QtGui.QImage) # VideoSignal1이라는 사용자 정의 시그널 생성
31 + VideoSignal2 = QtCore.pyqtSignal(QtGui.QImage) # VideoSignal2이라는 사용자 정의 시그널 생성
32 +
33 + def __init__(self, parent=None):
34 + super(ShowVideo, self).__init__(parent)
35 +
36 + @QtCore.pyqtSlot()
37 + def startVideo(self, faceNet, maskNet):
38 + global image
39 +
40 + run_video = True
41 + while run_video:
42 + ret, image = self.camera.read()
43 +
44 + # detect faces in the frame and determine if they are wearing a
45 + # face mask or not
46 + (locs, preds) = detect_and_predict_mask(image, faceNet, maskNet)
47 +
48 + frame = image
49 + # loop over the detected face locations and their corresponding
50 + # locations
51 + for (box, pred) in zip(locs, preds):
52 + # unpack the bounding box and predictions
53 + (startX, startY, endX, endY) = box
54 + (mask, withoutMask) = pred
55 +
56 + # determine the class label and color we'll use to draw
57 + # the bounding box and text
58 + label = "Mask" if mask > withoutMask else "No Mask"
59 + color = (0, 255, 0) if label == "Mask" else (0, 0, 255)
60 +
61 + # include the probability in the label
62 + label = "{}: {:.2f}%".format(label, max(mask, withoutMask) * 100)
63 +
64 + # display the label and bounding box rectangle on the output
65 + # frame
66 + cv2.putText(frame, label, (startX, startY - 10),
67 + cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2)
68 + cv2.rectangle(frame, (startX, startY), (endX, endY), color, 2)
69 + ###
70 + color_swapped_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
71 +
72 + qt_image1 = QtGui.QImage(color_swapped_image.data,
73 + self.width,
74 + self.height,
75 + color_swapped_image.strides[0],
76 + QtGui.QImage.Format_RGB888)
77 + self.VideoSignal1.emit(qt_image1)
78 +
79 +
80 + if self.flag:
81 + img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
82 + img_canny = cv2.Canny(img_gray, 50, 100)
83 +
84 + qt_image2 = QtGui.QImage(img_canny.data,
85 + self.width,
86 + self.height,
87 + img_canny.strides[0],
88 + QtGui.QImage.Format_Grayscale8)
89 +
90 + self.VideoSignal2.emit(qt_image2)
91 +
92 +
93 + loop = QtCore.QEventLoop()
94 + QtCore.QTimer.singleShot(25, loop.quit) #25 ms
95 + loop.exec_()
96 +
97 + @QtCore.pyqtSlot()
98 + def canny(self):
99 + self.flag = 1 - self.flag
100 +
101 +
102 +class ImageViewer(QtWidgets.QWidget):
103 + def __init__(self, parent=None):
104 + super(ImageViewer, self).__init__(parent)
105 + self.image = QtGui.QImage()
106 + self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)
107 +
108 + def paintEvent(self, event):
109 + painter = QtGui.QPainter(self)
110 + painter.drawImage(0, 0, self.image)
111 + self.image = QtGui.QImage()
112 +
113 + def initUI(self):
114 + self.setWindowTitle('Webcam')
115 +
116 + @QtCore.pyqtSlot(QtGui.QImage)
117 + def setImage(self, image):
118 + if image.isNull():
119 + print("Viewer Dropped frame!")
120 +
121 + self.image = image
122 + if image.size() != self.size():
123 + self.setFixedSize(image.size())
124 + self.update()
125 +
126 +def detect_and_predict_mask(frame, faceNet, maskNet):
127 + # grab the dimensions of the frame and then construct a blob
128 + # from it
129 + (h, w) = frame.shape[:2]
130 + blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300),
131 + (104.0, 177.0, 123.0))
132 +
133 + # pass the blob through the network and obtain the face detections
134 + faceNet.setInput(blob)
135 + detections = faceNet.forward()
136 +
137 + # initialize our list of faces, their corresponding locations,
138 + # and the list of predictions from our face mask network
139 + faces = []
140 + locs = []
141 + preds = []
142 +
143 + # loop over the detections
144 + for i in range(0, detections.shape[2]):
145 + # extract the confidence (i.e., probability) associated with
146 + # the detection
147 + confidence = detections[0, 0, i, 2]
148 +
149 + # filter out weak detections by ensuring the confidence is
150 + # greater than the minimum confidence
151 + if confidence > args["confidence"]:
152 + # compute the (x, y)-coordinates of the bounding box for
153 + # the object
154 + box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
155 + (startX, startY, endX, endY) = box.astype("int")
156 +
157 + # ensure the bounding boxes fall within the dimensions of
158 + # the frame
159 + (startX, startY) = (max(0, startX), max(0, startY))
160 + (endX, endY) = (min(w - 1, endX), min(h - 1, endY))
161 +
162 + # extract the face ROI, convert it from BGR to RGB channel
163 + # ordering, resize it to 224x224, and preprocess it
164 + face = frame[startY:endY, startX:endX]
165 + face = cv2.cvtColor(face, cv2.COLOR_BGR2RGB)
166 + face = cv2.resize(face, (224, 224))
167 + face = img_to_array(face)
168 + face = preprocess_input(face)
169 +
170 + # add the face and bounding boxes to their respective
171 + # lists
172 + faces.append(face)
173 + locs.append((startX, startY, endX, endY))
174 +
175 + # only make a predictions if at least one face was detected
176 + if len(faces) > 0:
177 + # for faster inference we'll make batch predictions on *all*
178 + # faces at the same time rather than one-by-one predictions
179 + # in the above `for` loop
180 + faces = np.array(faces, dtype="float32")
181 + preds = maskNet.predict(faces, batch_size=32)
182 +
183 + # return a 2-tuple of the face locations and their corresponding
184 + # locations
185 + return (locs, preds)
186 +
187 +
188 +if __name__ == '__main__':
189 +
190 + # construct the argument parser and parse the arguments
191 + ap = argparse.ArgumentParser()
192 + ap.add_argument("-f", "--face", type=str,default="face_detector",
193 + help="path to face detector model directory")
194 + ap.add_argument("-m", "--model", type=str,default="mask_detector.model",
195 + help="path to trained face mask detector model")
196 + ap.add_argument("-c", "--confidence", type=float, default=0.5,
197 + help="minimum probability to filter weak detections")
198 + args = vars(ap.parse_args())
199 +
200 + # load our serialized face detector model from disk
201 + print("[INFO] loading face detector model...")
202 + prototxtPath = os.path.sep.join([args["face"], "deploy.prototxt"])
203 + weightsPath = os.path.sep.join([args["face"],
204 + "res10_300x300_ssd_iter_140000.caffemodel"])
205 + faceNet = cv2.dnn.readNet(prototxtPath, weightsPath)
206 +
207 + # load the face mask detector model from disk
208 + print("[INFO] loading face mask detector model...")
209 + maskNet = load_model(args["model"])
210 +
211 +
212 + app = QtWidgets.QApplication(sys.argv) # app 생성
213 +
214 +
215 + thread = QtCore.QThread()
216 + thread.start()
217 + vid = ShowVideo()
218 + vid.moveToThread(thread)
219 +
220 + image_viewer1 = ImageViewer()
221 + #image_viewer2 = ImageViewer()
222 +
223 + vid.VideoSignal1.connect(image_viewer1.setImage)
224 + #vid.VideoSignal2.connect(image_viewer2.setImage)
225 +
226 + #push_button1 = QtWidgets.QPushButton('Start')
227 + #push_button2 = QtWidgets.QPushButton('Canny')
228 + #push_button1.clicked.connect(vid.startVideo)
229 + #push_button2.clicked.connect(vid.canny)
230 +
231 + vertical_layout = QtWidgets.QVBoxLayout()
232 + horizontal_layout = QtWidgets.QHBoxLayout()
233 + horizontal_layout.addWidget(image_viewer1)
234 + #horizontal_layout.addWidget(image_viewer2)
235 + vertical_layout.addLayout(horizontal_layout)
236 + #vertical_layout.addWidget(push_button1)
237 + #vertical_layout.addWidget(push_button2)
238 +
239 + layout_widget = QtWidgets.QWidget()
240 + layout_widget.setLayout(vertical_layout)
241 +
242 + main_window = QtWidgets.QMainWindow()
243 + main_window.setCentralWidget(layout_widget)
244 + main_window.setWindowTitle('웹캠 테스트') # main window 제목
245 + main_window.show()
246 + ####
247 + vid.startVideo(faceNet, maskNet)
248 + ####
249 + sys.exit(app.exec_()) # 프로그램 대기상태 유지, 무한루프