class MainGUI(QWidget): # ~~~~~~~~ constructor ~~~~~~~~ def __init__(self): super().__init__() self.jsonConfig() self.init_pipeline() self.init_UI() return # ~~~~~~~~ initialize pipeline ~~~~~~~~ def init_pipeline(self): self.pipeline = Pipeline() self.engine = 'EN' return # ~~~~~~~~ initialize ui ~~~~~~~~ def init_UI(self): self.configColor = (200, 110, 0) self.configColor = self.configColor[::-1] self.result_main_label = 'Predicted Value(s): NA' self.result_alt1_label = 'Alternate Value(s) #1: NA' self.result_alt2_label = 'Alternate Value(s) #2: NA' # set properties self.setGeometry(0, 0, 0, 0) self.setStyleSheet('QWidget {background-color: #ffffff;}') self.setWindowIcon(QIcon('assets/logo.png')) self.setWindowTitle('Air-Writing') # create widgets # -- connect camera button -- self.btn_conn = QPushButton('Connect Camera') self.btn_conn.setMinimumSize(350, 40) self.btn_conn_style_0 = 'QPushButton {background-color: #00a86c; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_conn_style_1 = 'QPushButton {background-color: #ff6464; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_conn.setStyleSheet(self.btn_conn_style_0) # -- connect file button -- self.btn_file = QPushButton() self.btn_file.setMinimumSize(50, 40) self.btn_file_style_0 = 'QPushButton {background-color: #f1c40f; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_file_style_1 = 'QPushButton {background-color: #e67e22; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_file.setStyleSheet(self.btn_file_style_0) self.btn_file.setIcon(QIcon('assets/file.png')) self.btn_file.setIconSize(QSize(30, 30)) # -- connect calibration button -- self.btn_cal = QPushButton() self.btn_cal.setMinimumSize(50, 40) self.btn_cal_style_0 = 'QPushButton {background-color: rgb' + str(self.configColor) + '; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_cal_style_1 = 'QPushButton {background-color: #8c8c8c; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_cal.setStyleSheet(self.btn_cal_style_0) self.btn_cal.setIcon(QIcon('assets/config.png')) self.btn_cal.setIconSize(QSize(30, 30)) # -- camera feed -- self.cam_feed = QLabel() self.cam_feed.setMinimumSize(640, 480) self.cam_feed.setAlignment(Qt.AlignCenter) self.cam_feed.setFrameStyle(QFrame.StyledPanel) self.cam_feed.setStyleSheet('QLabel {background-color: #000000;}') # -- inference results -- self.trace_label = QLabel('Traced Input') self.trace_label.setMinimumHeight(30) self.trace_label.setAlignment(Qt.AlignCenter) self.trace_label.setFrameStyle(QFrame.NoFrame) self.trace_label.setStyleSheet('QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 20px;}') self.trace_disp = QLabel('!') self.trace_disp.setMinimumHeight(260) self.trace_disp.setAlignment(Qt.AlignCenter) self.trace_disp.setFrameStyle(QFrame.StyledPanel) self.trace_disp.setStyleSheet('QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 200px;}') self.result_label = QLabel('Prediction Results') self.result_label.setMinimumHeight(30) self.result_label.setAlignment(Qt.AlignCenter) self.result_label.setFrameStyle(QFrame.NoFrame) self.result_label.setStyleSheet('QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 20px;}') self.result_main = QLabel(self.result_main_label) self.result_main.setMinimumHeight(20) self.result_main.setAlignment(Qt.AlignLeft) self.result_main.setFrameStyle(QFrame.NoFrame) self.result_main.setStyleSheet('QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 16px; font-weight: bold}') self.result_alt1 = QLabel(self.result_alt1_label) self.result_alt1.setMinimumHeight(20) self.result_alt1.setAlignment(Qt.AlignLeft) self.result_alt1.setFrameStyle(QFrame.NoFrame) self.result_alt1.setStyleSheet('QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 16px;}') self.result_alt2 = QLabel(self.result_alt2_label) self.result_alt2.setMinimumHeight(20) self.result_alt2.setAlignment(Qt.AlignLeft) self.result_alt2.setFrameStyle(QFrame.NoFrame) self.result_alt2.setStyleSheet('QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 16px;}') # -- repository link button -- self.btn_repo = QPushButton() self.btn_repo.setFixedSize(20, 20) self.btn_repo.setStyleSheet('QPushButton {background-color: none; border: none;}') self.btn_repo.setIcon(QIcon('assets/button_repo.png')) self.btn_repo.setIconSize(QSize(20, 20)) self.btn_repo.setToolTip('Fork me on GitHub') # -- copyright -- self.copyright = QLabel('\u00A9 2019 Indian Statistical Institute') self.copyright.setFixedHeight(20) self.copyright.setAlignment(Qt.AlignCenter) self.copyright.setStyleSheet('QLabel {background-color: #ffffff; font-family: ubuntu, arial; font-size: 14px;}') # -- indicator -- self.indicator = QLabel() self.indicator.setFixedSize(20, 20) self.indicator.setAlignment(Qt.AlignCenter) self.indicator.setFrameStyle(QFrame.NoFrame) self.indicator_style_0 = 'QLabel {background-color: #646464;}' self.indicator_style_1 = 'QLabel {background-color: #8ce312;}' self.indicator_style_2 = 'QLabel {background-color: rgb(255, 200, 0);}' self.indicator.setStyleSheet(self.indicator_style_0) # font info self.font = cv2.FONT_HERSHEY_SIMPLEX self.posMain = (15,400) self.posProgress = (300, 425) self.fontScale = 0.65 self.fontColorMain = (255,255,255) self.fontColorProgress = (255,200,0) self.lineType = 2 self.textMain = "Place your object on the marker and press 'a' to continue" self.textProgress = "1/5" self.progressCount = 1 # create layouts h_box1 = QHBoxLayout() h_box1.addWidget(self.btn_conn) # h_box1.addWidget(self.btn_file) h_box1.addWidget(self.btn_cal) h_box2 = QHBoxLayout() h_box2.addWidget(self.trace_label) h_box3 = QHBoxLayout() h_box3.addWidget(self.trace_disp) h_box4 = QHBoxLayout() h_box4.addWidget(self.result_label) h_box5 = QHBoxLayout() h_box5.addWidget(self.result_main) h_box6 = QHBoxLayout() h_box6.addWidget(self.result_alt1) h_box7 = QHBoxLayout() h_box7.addWidget(self.result_alt2) h_box8 = QHBoxLayout() h_box8.addWidget(self.btn_repo) h_box8.addWidget(self.copyright) h_box8.addWidget(self.indicator) v_box1 = QVBoxLayout() v_box1.addLayout(h_box1) v_box1.addStretch() v_box1.addLayout(h_box2) v_box1.addLayout(h_box3) v_box1.addStretch() v_box1.addLayout(h_box4) v_box1.addLayout(h_box5) v_box1.addLayout(h_box6) v_box1.addLayout(h_box7) v_box1.addStretch() v_box1.addLayout(h_box8) v_box2 = QVBoxLayout() v_box2.addWidget(self.cam_feed) g_box0 = QGridLayout() g_box0.addLayout(v_box1, 0, 0, -1, 2) g_box0.addLayout(v_box2, 0, 2, -1, 4) self.setLayout(g_box0) # set slots for signals self.flg_conn = False self.flg_cal = False self.trace_img = None self.btn_conn.clicked.connect(self.connect) # self.btn_file.clicked.connect(self.openFile) self.btn_cal.clicked.connect(self.calibrate) self.btn_repo.clicked.connect(self.openRepository) return def keyPressEvent(self, qKeyEvent): if qKeyEvent.key() == ord('A'): if self.calibrator: if self.calibrator._getCalIndex() < 5: self.calibrator._increaseCalIndex(); self.progressCount = self.progressCount + 1 self.textProgress = str(self.progressCount) + '/5' if self.calibrator._getCalIndex() == 5: self.calibrator._generateJSON() self.pipeline._loadConfig() self.configColor = self.calibrator._getCenterRGB() self.configColor = self.configColor[::-1] self.btn_cal_style_0 = 'QPushButton {background-color: rgb' + str(self.configColor) + '; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.progressCount = 1 self.textProgress = str(self.progressCount) + '/5' self.calibrate() msg = QMessageBox() msg.setIcon(QMessageBox.Information) msg.setText("Calibration Successful") msg.setWindowTitle("Success") msg.exec_() else: super().keyPressEvent(qKeyEvent) def moveWindowToCenter(self): window_rect = self.frameGeometry() screen_cent = QDesktopWidget().availableGeometry().center() window_rect.moveCenter(screen_cent) self.move(window_rect.topLeft()) return def connect(self): if not self.flg_cal: self.flg_conn = not self.flg_conn if self.flg_conn: self.btn_conn.setStyleSheet(self.btn_conn_style_1) self.btn_conn.setText('Disconnect Camera') self.indicator.setStyleSheet(self.indicator_style_1) self.video = VideoStream() self.timer = QTimer() self.timer.timeout.connect(self.update) self.timer.start(50) else: self.btn_conn.setStyleSheet(self.btn_conn_style_0) self.btn_conn.setText('Connect Camera') self.indicator.setStyleSheet(self.indicator_style_0) self.cam_feed.clear() self.timer.stop() self.video.clear() return def calibrate(self): if not self.flg_conn: self.flg_cal = not self.flg_cal if self.flg_cal: self.btn_cal.setStyleSheet(self.btn_cal_style_1) self.indicator.setStyleSheet(self.indicator_style_2) self.video = VideoStream() self.calibrator = CalibrationInterface() self.timer = QTimer() self.timer.timeout.connect(self.updateCalibration) self.timer.start(50) else: self.btn_cal.setStyleSheet(self.btn_cal_style_0) self.indicator.setStyleSheet(self.indicator_style_0) self.cam_feed.clear() self.timer.stop() self.video.clear() self.calibrator = None return def update(self): frame = self.video.getFrame(flip=1) if not frame is None: frame, trace, bi, fwd, rev = self.pipeline.run_inference(frame, self.engine, True) frame = QImage(frame, frame.shape[1], frame.shape[0], frame.strides[0], QImage.Format_RGB888) self.cam_feed.setPixmap(QPixmap.fromImage(frame)) if not trace is None and not bi == []: self.trace_img = trace self.result_main_label = 'Predicted Value(s): ' + str(bi) if not str(fwd) == str(bi): self.result_alt1_label = 'Alternate Value(s) #1: ' + str(fwd) if not str(rev) == str(bi) and not str(rev) == str(fwd): self.result_alt2_label = 'Alternate Value(s) #2: ' + str(rev) else: self.result_alt2_label = 'Alternate Value(s) #2: NA' elif not str(rev) == str(bi): self.result_alt1_label = 'Alternate Value(s) #1: ' + str(rev) self.result_alt2_label = 'Alternate Value(s) #2: NA' else: self.result_alt1_label = 'Alternate Value(s) #1: NA' self.result_alt2_label = 'Alternate Value(s) #2: NA' toolTipString = 'Bi-directional Scan: ' + str(bi) + '\n' + 'Forward Scan: ' + str(fwd) + '\n' + 'Reverse Scan: ' + str(rev) self.result_label.setToolTip(toolTipString) else: self.result_label.setToolTip('') else: self.cam_feed.clear() if not self.trace_img is None: trace_img_disp = QImage(self.trace_img, self.trace_img.shape[1], self.trace_img.shape[0], self.trace_img.strides[0], QImage.Format_RGB888) self.trace_disp.setPixmap(QPixmap.fromImage(trace_img_disp)) self.result_main.setText(self.result_main_label) self.result_alt1.setText(self.result_alt1_label) self.result_alt2.setText(self.result_alt2_label) return def updateCalibration(self): frame = self.video.getFrame(flip=1) if not frame is None: frame = self.calibrator._calibrate(frame) cv2.putText(frame, self.textMain, self.posMain, self.font, self.fontScale, self.fontColorMain, self.lineType) cv2.putText(frame, self.textProgress, self.posProgress, self.font, self.fontScale, self.fontColorProgress, self.lineType) frame = QImage(frame, frame.shape[1], frame.shape[0], frame.strides[0], QImage.Format_RGB888) self.cam_feed.setPixmap(QPixmap.fromImage(frame)) else: self.cam_feed.clear() return def jsonConfig(self): self.calibrator = CalibrationInterface() if not os.path.exists('config.json'): self.calibrator._generateDefaultJSON() self.configColor = self.calibrator._getCenterRGB() self.configColor = self.configColor[::-1] self.calibrator = None return def openFile(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName(self,"Open Saved Character Co-ordinate File", "","Numpy Files (*.npy)", options=options) if fileName: pts = numpy.load(fileName) if not len(pts.shape) == 2: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Incorrect File Loaded") msg.setWindowTitle("Error") msg.exec_() elif not pts.shape[1] == 2: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Incorrect File Loaded") msg.setWindowTitle("Error") msg.exec_() else: self.readPts(pts) return def readPts(self, pts): trace, bi, fwd, rev = self.pipeline.run_inference_file(pts) if not trace is None and not bi == []: self.trace_img = trace self.result_main_label = 'Predicted Value(s): ' + str(bi) if not str(fwd) == str(bi): self.result_alt1_label = 'Alternate Value(s) #1: ' + str(fwd) if not str(rev) == str(bi) and not str(rev) == str(fwd): self.result_alt2_label = 'Alternate Value(s) #2: ' + str(rev) else: self.result_alt2_label = 'Alternate Value(s) #2: NA' elif not str(rev) == str(bi): self.result_alt1_label = 'Alternate Value(s) #1: ' + str(rev) self.result_alt2_label = 'Alternate Value(s) #2: NA' else: self.result_alt1_label = 'Alternate Value(s) #1: NA' self.result_alt2_label = 'Alternate Value(s) #2: NA' toolTipString = 'Bi-directional Scan: ' + str(bi) + '\n' + 'Forward Scan: ' + str(fwd) + '\n' + 'Reverse Scan: ' + str(rev) self.result_label.setToolTip(toolTipString) else: self.result_label.setToolTip('') if not self.trace_img is None: trace_img_disp = QImage(self.trace_img, self.trace_img.shape[1], self.trace_img.shape[0], self.trace_img.strides[0], QImage.Format_RGB888) self.trace_disp.setPixmap(QPixmap.fromImage(trace_img_disp)) self.result_main.setText(self.result_main_label) self.result_alt1.setText(self.result_alt1_label) self.result_alt2.setText(self.result_alt2_label) return def openRepository(self): webbrowser.open('https://github.com/adildsw/air-writing-v2') return def closeEvent(self, event): if self.flg_conn or self.flg_cal: self.connect() sys.exit() return
class MainGUI(QWidget): # ~~~~~~~~ constructor ~~~~~~~~ def __init__(self): super().__init__() self.init_pipeline() self.init_UI() return # ~~~~~~~~ initialize pipeline ~~~~~~~~ def init_pipeline(self): self.pipeline = Pipeline() self.engine = 'EN' return # ~~~~~~~~ initialize ui ~~~~~~~~ def init_UI(self): # set properties self.setGeometry(0, 0, 0, 0) self.setStyleSheet('QWidget {background-color: #ffffff;}') self.setWindowIcon(QIcon('assets/logo.png')) self.setWindowTitle('Air-Writing') # create widgets # -- connect camera button -- self.btn_conn = QPushButton('Connect Camera') self.btn_conn.setMinimumSize(500, 40) self.btn_conn_style_0 = 'QPushButton {background-color: #00a86c; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_conn_style_1 = 'QPushButton {background-color: #ff6464; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_conn.setStyleSheet(self.btn_conn_style_0) # -- camera feed -- self.cam_feed = QLabel() self.cam_feed.setMinimumSize(640, 480) self.cam_feed.setAlignment(Qt.AlignCenter) self.cam_feed.setFrameStyle(QFrame.StyledPanel) self.cam_feed.setStyleSheet('QLabel {background-color: #000000;}') # -- recognition engine selection buttons -- self.btn_engine_style_0 = 'QPushButton {background-color: #646464; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 14px;}' self.btn_engine_style_1 = 'QPushButton {background-color: #6464ff; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 14px;}' self.btn_en = QPushButton('English Numerals') self.btn_en.setMinimumSize(150, 30) self.btn_en.setStyleSheet(self.btn_engine_style_1) self.btn_bn = QPushButton('Bengali Numerals') self.btn_bn.setMinimumSize(150, 30) self.btn_bn.setStyleSheet(self.btn_engine_style_0) self.btn_dv = QPushButton('Devanagari Numerals') self.btn_dv.setMinimumSize(150, 30) self.btn_dv.setStyleSheet(self.btn_engine_style_0) # -- inference results -- self.disp_pred = QLabel('!') self.disp_pred.setMinimumHeight(250) self.disp_pred.setAlignment(Qt.AlignCenter) self.disp_pred.setFrameStyle(QFrame.NoFrame) self.disp_pred.setStyleSheet( 'QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 200px;}' ) self.disp_prob = QLabel('Confidence 0.0%') self.disp_prob.setMinimumHeight(20) self.disp_prob.setAlignment(Qt.AlignCenter) self.disp_prob.setFrameStyle(QFrame.NoFrame) self.disp_prob.setStyleSheet( 'QLabel {background-color: #ffffff; color: #646464; font-family: ubuntu, arial; font-size: 20px;}' ) # -- repository link button -- self.btn_repo = QPushButton() self.btn_repo.setFixedSize(20, 20) self.btn_repo.setStyleSheet( 'QPushButton {background-color: none; border: none;}') self.btn_repo.setIcon(QIcon('assets/button_repo.png')) self.btn_repo.setIconSize(QSize(20, 20)) self.btn_repo.setToolTip('Fork me on GitHub') # -- copyright -- self.copyright = QLabel('\u00A9 2018 Indian Staistical Institute') self.copyright.setFixedHeight(20) self.copyright.setAlignment(Qt.AlignCenter) self.copyright.setStyleSheet( 'QLabel {background-color: #ffffff; font-family: ubuntu, arial; font-size: 14px;}' ) # -- indicator -- self.indicator = QLabel() self.indicator.setFixedSize(20, 20) self.indicator.setAlignment(Qt.AlignCenter) self.indicator.setFrameStyle(QFrame.NoFrame) self.indicator.setStyleSheet('QLabel {background-color: #646464;}') # create layouts h_box1 = QHBoxLayout() h_box1.addWidget(self.btn_conn) h_box2 = QHBoxLayout() h_box2.addWidget(self.btn_en) h_box2.addWidget(self.btn_bn) h_box2.addWidget(self.btn_dv) h_box3 = QHBoxLayout() h_box3.addWidget(self.disp_pred) h_box4 = QHBoxLayout() h_box4.addWidget(self.disp_prob) h_box5 = QHBoxLayout() h_box5.addWidget(self.btn_repo) h_box5.addWidget(self.copyright) h_box5.addWidget(self.indicator) v_box1 = QVBoxLayout() v_box1.addLayout(h_box1) v_box1.addLayout(h_box2) v_box1.addStretch() v_box1.addLayout(h_box3) v_box1.addLayout(h_box4) v_box1.addStretch() v_box1.addLayout(h_box5) v_box2 = QVBoxLayout() v_box2.addWidget(self.cam_feed) g_box0 = QGridLayout() g_box0.addLayout(v_box1, 0, 0, -1, 2) g_box0.addLayout(v_box2, 0, 2, -1, 4) self.setLayout(g_box0) # set slots for signals self.flg_conn = False self.btn_conn.clicked.connect(self.connect) self.btn_en.clicked.connect(lambda: self.setRecognitionEngine('EN')) self.btn_bn.clicked.connect(lambda: self.setRecognitionEngine('BN')) self.btn_dv.clicked.connect(lambda: self.setRecognitionEngine('DV')) self.btn_repo.clicked.connect(self.openRepository) return # ~~~~~~~~ window centering ~~~~~~~~ def moveWindowToCenter(self): window_rect = self.frameGeometry() screen_cent = QDesktopWidget().availableGeometry().center() window_rect.moveCenter(screen_cent) self.move(window_rect.topLeft()) return # ~~~~~~~~ connect camera ~~~~~~~~ def connect(self): self.flg_conn = not self.flg_conn if self.flg_conn: self.btn_conn.setStyleSheet(self.btn_conn_style_1) self.btn_conn.setText('Disconnect Camera') self.video = VideoStream() self.timer = QTimer() self.timer.timeout.connect(self.update) self.timer.start(50) else: self.btn_conn.setStyleSheet(self.btn_conn_style_0) self.btn_conn.setText('Connect Camera') self.cam_feed.clear() self.timer.stop() self.video.clear() self.disp_pred.setText('!') self.disp_prob.setText('Confidence 0.0%') self.indicator.setStyleSheet('QLabel {background-color: #646464;}') return # ~~~~~~~~ update ~~~~~~~~ def update(self): # update frame frame = self.video.getFrame(flip=1) if not frame is None: prediction, predprobas, mask, frame = self.pipeline.run_inference( frame, self.engine, True) frame = QImage(frame, frame.shape[1], frame.shape[0], frame.strides[0], QImage.Format_RGB888) self.cam_feed.setPixmap(QPixmap.fromImage(frame)) if not prediction is None and len(prediction) > 0: self.disp_pred.setText(prediction[0]) if not predprobas is None and len(prediction) > 0: self.disp_prob.setText('Confidence {:.1f}%'.format( float(predprobas[0]) * 100)) else: self.cam_feed.clear() # update indicator if self.pipeline._marker_tip is None: self.indicator.setStyleSheet('QLabel {background-color: #646464;}') elif self.pipeline._vx < 2.0 and self.pipeline._vy < 2.0: self.indicator.setStyleSheet('QLabel {background-color: #f00000;}') else: self.indicator.setStyleSheet('QLabel {background-color: #00f000;}') return # ~~~~~~~~ set recognition engine ~~~~~~~~ def setRecognitionEngine(self, engine='EN'): if engine.upper() == 'EN': self.engine = 'EN' self.btn_en.setStyleSheet(self.btn_engine_style_1) self.btn_bn.setStyleSheet(self.btn_engine_style_0) self.btn_dv.setStyleSheet(self.btn_engine_style_0) elif engine.upper() == 'BN': self.engine = 'BN' self.btn_en.setStyleSheet(self.btn_engine_style_0) self.btn_bn.setStyleSheet(self.btn_engine_style_1) self.btn_dv.setStyleSheet(self.btn_engine_style_0) elif engine.upper() == 'DV': self.engine = 'DV' self.btn_en.setStyleSheet(self.btn_engine_style_0) self.btn_bn.setStyleSheet(self.btn_engine_style_0) self.btn_dv.setStyleSheet(self.btn_engine_style_1) return # ~~~~~~~~ open repository ~~~~~~~~ def openRepository(self): webbrowser.open('https://github.com/prasunroy/air-writing') return # ~~~~~~~~ close event ~~~~~~~~ def closeEvent(self, event): if self.flg_conn: self.connect() return
class MainGUI(QWidget): def __init__(self): super().__init__() self.init_pipeline() self.init_UI() return def init_pipeline(self): self.pipeline = Pipeline() self.engine = 'EN' return def init_UI(self): self.setGeometry(0, 0, 0, 0) self.setStyleSheet('QWidget {background-color: #ffffff;}') self.setWindowIcon(QIcon('assets/logo.png')) self.setWindowTitle('Air-Writing Data Generator') self.btn_conn = QPushButton('Connect Camera') self.btn_conn.setMinimumSize(500, 40) self.btn_conn_style_0 = 'QPushButton {background-color: #00a86c; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_conn_style_1 = 'QPushButton {background-color: #ff6464; border: none; color: #ffffff; font-family: ubuntu, arial; font-size: 16px;}' self.btn_conn.setStyleSheet(self.btn_conn_style_0) self.cam_feed = QLabel() self.cam_feed.setMinimumSize(640, 480) self.cam_feed.setAlignment(Qt.AlignCenter) self.cam_feed.setFrameStyle(QFrame.StyledPanel) self.cam_feed.setStyleSheet('QLabel {background-color: #000000;}') h_box1 = QHBoxLayout() h_box1.addWidget(self.btn_conn) v_box1 = QVBoxLayout() v_box1.addLayout(h_box1) v_box1.addWidget(self.cam_feed) g_box0 = QGridLayout() g_box0.addLayout(v_box1, 0, 0, -1, 2) self.setLayout(g_box0) self.flg_conn = False self.btn_conn.clicked.connect(self.connect) return def moveWindowToCenter(self): window_rect = self.frameGeometry() screen_cent = QDesktopWidget().availableGeometry().center() window_rect.moveCenter(screen_cent) self.move(window_rect.topLeft()) return def connect(self): self.flg_conn = not self.flg_conn if self.flg_conn: self.btn_conn.setStyleSheet(self.btn_conn_style_1) self.btn_conn.setText('Disconnect Camera') self.video = VideoStream() self.timer = QTimer() self.timer.timeout.connect(self.update) self.timer.start(50) else: self.btn_conn.setStyleSheet(self.btn_conn_style_0) self.btn_conn.setText('Connect Camera') self.cam_feed.clear() self.timer.stop() self.video.clear() return def update(self): frame = self.video.getFrame(flip=1) if not frame is None: frame = self.pipeline.run_inference(frame, self.engine, True) frame = QImage(frame, frame.shape[1], frame.shape[0], frame.strides[0], QImage.Format_RGB888) self.cam_feed.setPixmap(QPixmap.fromImage(frame)) else: self.cam_feed.clear() return def closeEvent(self, event): if self.flg_conn: self.connect() return