class Ui_MainWindowcamera(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) MainWindow.setIconSize(QtCore.QSize(48, 48)) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget.setGeometry(QtCore.QRect(130, 10, 651, 561)) self.tabWidget.setObjectName("tabWidget") # self.tabWidget.setCurrentIndex() self.tab = QtWidgets.QWidget() self.tab.setObjectName("tab") self.groupBox_2 = QtWidgets.QGroupBox(self.tab) self.groupBox_2.setGeometry(QtCore.QRect(60, 20, 181, 261)) self.groupBox_2.setObjectName("groupBox_2") self.widget = QCameraViewfinder(self.groupBox_2) self.widget.setGeometry(QtCore.QRect(20, 20, 141, 231)) self.widget.setObjectName("widget") self.label = QtWidgets.QLabel(self.tab) self.label.setGeometry(QtCore.QRect(10, 10, 621, 441)) self.label.setText("") self.label.setPixmap( QtGui.QPixmap("../../aipicture/145940263255235.jpeg")) self.label.setScaledContents(True) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.tab) self.label_2.setGeometry(QtCore.QRect(410, 30, 151, 251)) self.label_2.setText("") self.label_2.setPixmap(QtGui.QPixmap("")) self.label_2.setScaledContents(False) self.label_2.setObjectName("label_2") # self.btn1 = QtWidgets.QPushButton("确定", self) # self.btn1.move(20, 120) self.plainTextEdit = QtWidgets.QPlainTextEdit(self.tab) self.plainTextEdit.setGeometry(QtCore.QRect(140, 320, 171, 31)) self.plainTextEdit.setObjectName("plainTextEdit") self.label_3 = QtWidgets.QLabel(self.tab) self.label_3.setGeometry(QtCore.QRect(40, 310, 81, 31)) self.label_3.setStyleSheet("font: 14pt'楷体';color:rgb(255,255,255);") self.label_3.setObjectName("label_3") self.label_4 = QtWidgets.QLabel(self.tab) self.label_4.setGeometry(QtCore.QRect(40, 382, 81, 21)) self.label_4.setStyleSheet("font:14pt '楷体';color:rgb(255,255,255);") self.label_4.setObjectName("label_4") self.plainTextEdit_2 = QtWidgets.QPlainTextEdit(self.tab) self.plainTextEdit_2.setGeometry(QtCore.QRect(140, 380, 171, 31)) self.plainTextEdit_2.setObjectName("plainTextEdit_2") self.btnget = QtWidgets.QPushButton(self.tab) self.btnget.setGeometry(QtCore.QRect(380, 340, 75, 23)) self.btnget.setObjectName("pushButton") self.label.raise_() self.groupBox_2.raise_() self.label_2.raise_() self.plainTextEdit.raise_() self.label_3.raise_() self.label_4.raise_() self.plainTextEdit_2.raise_() self.btnget.raise_() self.tabWidget.addTab(self.tab, "") self.tab_3 = QtWidgets.QWidget() self.tab_3.setObjectName("tab_3") self.label_5 = QtWidgets.QLabel(self.tab_3) self.label_5.setGeometry(QtCore.QRect(0, 0, 661, 451)) self.label_5.setText("") self.label_5.setPixmap(QtGui.QPixmap("../../aipicture/searchbg.jpg")) self.label_5.setScaledContents(True) self.label_5.setObjectName("label_5") self.groupBox_3 = QtWidgets.QGroupBox(self.tab_3) self.groupBox_3.setGeometry(QtCore.QRect(20, 20, 611, 411)) self.groupBox_3.setObjectName("groupBox_3") self.btncap = QtWidgets.QPushButton(self.groupBox_3) self.btncap.setGeometry(QtCore.QRect(150, 30, 72, 23)) self.btnget.setObjectName("pushButton") self.widget_2 = QCameraViewfinder(self.groupBox_3) self.widget_2.setGeometry(QtCore.QRect(50, 100, 171, 271)) self.widget_2.setObjectName("widget_2") self.label_6 = QtWidgets.QLabel(self.groupBox_3) self.label_6.setGeometry(QtCore.QRect(50, 21, 101, 31)) self.label_6.setLineWidth(1) self.label_6.setTextFormat(QtCore.Qt.AutoText) self.label_6.setScaledContents(False) self.label_6.setStyleSheet("font:14pt '楷体';color:rgb(255,255,255);") self.label_6.setObjectName("label_6") self.plainTextEdit_3 = QtWidgets.QPlainTextEdit(self.groupBox_3) self.plainTextEdit_3.setGeometry(QtCore.QRect(320, 100, 201, 31)) self.plainTextEdit_3.setObjectName("plainTextEdit_3") self.plainTextEdit_3.setStyleSheet("font:14pt '楷体';") self.label_7 = QtWidgets.QLabel(self.groupBox_3) self.label_7.setGeometry(QtCore.QRect(230, 100, 80, 19)) self.label_7.setObjectName("label_7") self.label_7.setStyleSheet("font:14pt '楷体';color:rgb(255,255,255);") self.label_8 = QtWidgets.QLabel(self.groupBox_3) self.label_8.setGeometry(QtCore.QRect(230, 180, 81, 31)) self.label_8.setObjectName("label_8") self.label_8.setStyleSheet("font:14pt '楷体';color:rgb(255,255,255);") self.label_9 = QtWidgets.QLabel(self.groupBox_3) self.label_9.setGeometry(QtCore.QRect(230, 260, 81, 31)) self.label_9.setObjectName("label_9") self.label_9.setStyleSheet("font:14pt '楷体';color:rgb(255,255,255);") self.plainTextEdit_4 = QtWidgets.QPlainTextEdit(self.groupBox_3) self.plainTextEdit_4.setGeometry(QtCore.QRect(320, 180, 201, 31)) self.plainTextEdit_4.setObjectName("plainTextEdit_4") self.plainTextEdit_4.setStyleSheet("font:14pt '楷体';") self.plainTextEdit_5 = QtWidgets.QPlainTextEdit(self.groupBox_3) self.plainTextEdit_5.setGeometry(QtCore.QRect(320, 260, 201, 31)) self.plainTextEdit_5.setObjectName("plainTextEdit_5") self.plainTextEdit_5.setStyleSheet("font:14pt '楷体';") self.label_10 = QtWidgets.QLabel(self.groupBox_3) self.label_10.setGeometry(QtCore.QRect(250, 350, 61, 21)) self.label_10.setObjectName("label_10") self.label_10.setStyleSheet("font:14pt '楷体';color:rgb(255,255,255);") self.plainTextEdit_6 = QtWidgets.QPlainTextEdit(self.groupBox_3) self.plainTextEdit_6.setGeometry(QtCore.QRect(320, 340, 201, 31)) self.plainTextEdit_6.setObjectName("plainTextEdit_6") self.plainTextEdit_6.setStyleSheet("font:14pt '楷体';") self.tabWidget.addTab(self.tab_3, "") self.tab_2 = QtWidgets.QWidget() self.tab_2.setObjectName("tab_2") self.btndata = QtWidgets.QPushButton(self.tab_2) self.btndata.setGeometry(QtCore.QRect(30, 210, 75, 23)) self.btndata.setObjectName("pushButton") self.btndata.raise_() self.plainTextEdit_7 = QtWidgets.QPlainTextEdit(self.tab_2) self.plainTextEdit_7.setGeometry(QtCore.QRect(130, 60, 431, 331)) self.plainTextEdit_7.setObjectName("plainTextEdit_7") self.plainTextEdit_7.setStyleSheet("font:14pt '楷体';") self.label_11 = QtWidgets.QLabel(self.tab_2) self.label_11.setGeometry(QtCore.QRect(60, 60, 54, 12)) self.label_11.setObjectName("label_11") self.tabWidget.addTab(self.tab_2, "") self.groupBox = QtWidgets.QGroupBox(self.centralwidget) self.groupBox.setGeometry(QtCore.QRect(0, 10, 121, 471)) self.groupBox.setObjectName("groupBox") self.addnew = QtWidgets.QPushButton(self.groupBox) self.addnew.setGeometry(QtCore.QRect(20, 40, 91, 51)) self.addnew.setObjectName("addnew") self.searchinfo = QtWidgets.QPushButton(self.groupBox) self.searchinfo.setGeometry(QtCore.QRect(20, 170, 91, 51)) self.searchinfo.setObjectName("searchinfo") self.pushButton_3 = QtWidgets.QPushButton(self.groupBox) self.pushButton_3.setGeometry(QtCore.QRect(20, 300, 91, 51)) self.pushButton_3.setObjectName("pushButton_3") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23)) self.menubar.setObjectName("menubar") self.menuwtf = QtWidgets.QMenu(self.menubar) self.menuwtf.setObjectName("menuwtf") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.toolBar = QtWidgets.QToolBar(MainWindow) self.toolBar.setEnabled(True) self.toolBar.setIconSize(QtCore.QSize(60, 60)) self.toolBar.setObjectName("toolBar") MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.actionActStartCamera = QtWidgets.QAction(MainWindow) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap("E:/aipicture/videocam_video_72px.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionActStartCamera.setIcon(icon) self.actionActStartCamera.setObjectName("actionActStartCamera") self.actionActCloseCamrera = QtWidgets.QAction(MainWindow) icon1 = QtGui.QIcon() icon1.addPixmap( QtGui.QPixmap("E:/aipicture/videocam_off_video_72px.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionActCloseCamrera.setIcon(icon1) self.actionActCloseCamrera.setObjectName("actionActCloseCamrera") self.actionActCaputure = QtWidgets.QAction(MainWindow) icon2 = QtGui.QIcon() icon2.addPixmap(QtGui.QPixmap("E:/aipicture/camcorder_72px.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionActCaputure.setIcon(icon2) self.actionActCaputure.setObjectName("actionActCaputure") self.actionActExit = QtWidgets.QAction(MainWindow) icon3 = QtGui.QIcon() icon3.addPixmap(QtGui.QPixmap("E:/aipicture/power_exit_72px.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.actionActExit.setIcon(icon3) self.actionActExit.setObjectName("actionActExit") self.menuwtf.addAction(self.actionActStartCamera) self.menuwtf.addSeparator() self.menuwtf.addAction(self.actionActCloseCamrera) self.menuwtf.addSeparator() self.menuwtf.addAction(self.actionActCaputure) self.menuwtf.addSeparator() self.menuwtf.addAction(self.actionActExit) self.menuwtf.addSeparator() self.menubar.addAction(self.menuwtf.menuAction()) self.toolBar.addAction(self.actionActStartCamera) self.toolBar.addSeparator() self.toolBar.addAction(self.actionActCloseCamrera) self.toolBar.addSeparator() self.toolBar.addAction(self.actionActCaputure) self.toolBar.addSeparator() self.toolBar.addAction(self.actionActExit) self.toolBar.addSeparator() self.retranslateUi(MainWindow) # self.tabWidget.setCurrentIndex(0) # self.addnew.clicked['bool'].connect(self.addnew.click) # self.searchinfo.clicked.connect(self.searchinfo.click) # self.pushButton_3.clicked['bool'].connect(self.pushButton_3.click) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.groupBox_2.setTitle(_translate("MainWindow", "GroupBox")) self.label_3.setText(_translate("MainWindow", "学生姓名")) self.label_4.setText(_translate("MainWindow", "学生成绩")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "拍照增加")) self.groupBox_3.setTitle(_translate("MainWindow", "GroupBox")) self.label_6.setText(_translate("MainWindow", "照片查找")) self.label_7.setText(_translate("MainWindow", "学生姓名")) self.label_8.setText(_translate("MainWindow", "学生性别")) self.label_9.setText(_translate("MainWindow", "学生成绩")) self.label_10.setText(_translate("MainWindow", "颜值")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "查找")) self.label_11.setText(_translate("MainWindow", "数据库")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "查看")) self.groupBox.setTitle(_translate("MainWindow", "shiftscene")) self.addnew.setText(_translate("MainWindow", "拍照增加")) self.searchinfo.setText(_translate("MainWindow", "查找")) self.pushButton_3.setText(_translate("MainWindow", "查看")) self.btncap.setText(_translate("MainWindow", "搜索")) self.btnget.setText(_translate("MainWindow", "提交")) self.btndata.setText(_translate("MainWindow", "查看")) self.menuwtf.setTitle(_translate("MainWindow", "开始")) self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar")) self.actionActStartCamera.setText( _translate("MainWindow", "ActStartCamera")) self.actionActStartCamera.setToolTip( _translate("MainWindow", "使用摄像头(ctrl+s)")) self.actionActStartCamera.setShortcut( _translate("MainWindow", "Ctrl+S")) self.actionActCloseCamrera.setText( _translate("MainWindow", "ActCloseCamrera")) self.actionActCloseCamrera.setToolTip( _translate("MainWindow", "关闭摄像头(ctrl+c)")) self.actionActCloseCamrera.setShortcut( _translate("MainWindow", "Ctrl+C")) self.actionActCaputure.setText(_translate("MainWindow", "ActCaputure")) self.actionActCaputure.setToolTip( _translate("MainWindow", "拍照(ctrl+d)")) self.actionActCaputure.setShortcut(_translate("MainWindow", "Ctrl+D")) self.actionActExit.setText(_translate("MainWindow", "ActExit")) self.actionActExit.setToolTip(_translate("MainWindow", "退出(esc)")) self.actionActExit.setShortcut(_translate("MainWindow", "Esc"))
class MyWindow(Window, Form): __slots__ = [ # widgets 'cameraViewfinder', 'statCanvas0', 'statCanvas1', 'statCanvas2', # commons 'threadpool', # camera 'camera', 'capture', 'capture_timer', # photo 'photo_timestamp', 'photo_pixmap', # setting 'warn_notifier', 'warn_notifier_timer', 'stat_notifier', 'stat_notifier_timer', ] def __init__(self): super().__init__() self.setupUi(self) # widgets self.cameraViewfinder = QCameraViewfinder(self.cameraWidget) self.cameraViewfinder.setGeometry(QRect(-1, 52, 641, 481)) self.cameraViewfinder.setObjectName('cameraViewfinder') self.statCanvas0 = StatCanvas(self.statWidget0, 'statCanvas0', 640, 480) self.statCanvas1 = StatCanvas(self.statWidget1, 'statCanvas1', 640, 480) self.statCanvas2 = StatCanvas(self.statWidget2, 'statCanvas2', 640, 480) # common self.threadpool = QThreadPool() # camera self.camera = None self.capture = None self.init_camera_and_capture() self.capture_timer = self.create_timer(5_000, self.capture_safe) # photo self.photo_timestamp = None self.photo_pixmap = QPixmap() # setting self.warn_notifier = Notifier(['확인', '무시']) self.warn_notifier_timer = self.create_timer(60_000, self.notify_warn_if_bad) self.stat_notifier = Notifier(['확인', '무시']) self.stat_notifier_timer = self.create_timer( self.get_setting_stat_interval(), self.notify_stat) # connect: camera self.cameraButton.toggled.connect( lambda toggle: self.cameraButton.setText('정지' if toggle else '시작')) self.cameraButton.toggled.connect(self.toggle_all_timers) # connect: stat, photo self.statTabWidget.tabBarClicked.connect(self.load_stat) self.tabWidget.tabBarClicked.connect(lambda index: self.load_photo( ) if index == 1 else self.load_stat(self.statTabWidget.currentIndex()) if index == 2 else None) self.photoLeftButton.clicked.connect( lambda: self.load_photo(left=True)) self.photoRightButton.clicked.connect( lambda: self.load_photo(right=True)) # connect: setting self.settingWarnButton.toggled.connect(self.toggle_warn_timer) self.connect_setting_stat_cycle_selected(self.settingStatCycleOff) self.connect_setting_stat_cycle_selected(self.settingStatCycle1) self.connect_setting_stat_cycle_selected(self.settingStatCycle2) self.connect_setting_stat_cycle_selected(self.settingStatCycle3) self.connect_setting_stat_cycle_selected(self.settingStatCycle6) self.settingStatTestButton.pressed.connect( lambda: self.settingStatTestButton.setIcon( QIcon('resource/test_off.png'))) self.settingStatTestButton.released.connect( lambda: self.settingStatTestButton.setIcon( QIcon('resource/test_on.png'))) self.settingStatTestButton.clicked.connect(self.notify_stat) def connect_setting_stat_cycle_selected(self, cycle: QPushButton) -> None: def selected(toggle: bool) -> None: checkeds = [x for x in others if x.isChecked()] if not checkeds: cycle.setChecked(True) elif toggle: checkeds[0].setChecked(False) self.toggle_stat_timer(cycle is not self.settingStatCycleOff) others: List[QPushButton] = [ self.settingStatCycle1, self.settingStatCycle2, self.settingStatCycle3, self.settingStatCycle6, self.settingStatCycleOff, ] others.remove(cycle) cycle.toggled.connect(selected) def init_camera_and_capture(self) -> bool: available_cameras = QCameraInfo.availableCameras() if not available_cameras: return False self.camera = self.create_camera(available_cameras, 0, self.cameraViewfinder, self.error_camera) self.capture = self.create_capture(self.camera, self.process_image_on_threadpool, self.error_camera) if self.camera.isAvailable(): self.camera.start() return True def check_camera(self) -> bool: if (self.camera is None or not self.camera.isAvailable() ) and not self.init_camera_and_capture(): return False if not self.capture.isReadyForCapture(): self.camera.start() return True def start_capture_timer_safe(self) -> None: if self.check_camera(): self.capture_timer.start() else: self.error_camera() def capture_safe(self) -> None: if self.check_camera(): self.capture.capture() else: self.error_camera() def error_camera(self, *args) -> None: self.cameraButton.setChecked(False) def get_setting_stat_interval(self) -> int: cycles: List[QPushButton] = [ self.settingStatCycle1, self.settingStatCycle2, self.settingStatCycle3, self.settingStatCycle6, ] checkeds = [x for x in cycles if x.isChecked()] text = checkeds[0].objectName().replace('settingStatCycle', '', 1) if checkeds else 1 msec = int(text) * 3_600_000 return msec def process_image_on_threadpool(self, id: int, qimg: QImage) -> None: def display_result(record: RecordType) -> None: if record['success']: self.display_ihunch_status(self.cameraStatusBar, record['human'], record['ihunch']) worker = Worker(upload_image_save_record, qimg) worker.signals.result.connect(display_result) self.threadpool.start(worker) def load_stat(self, index: int = 0) -> None: statCanvas = getattr(self, f'statCanvas{index}') if index == 0: statCanvas.plot_today_vs_yesterday() elif index == 1: statCanvas.plot_week_to_day() else: statCanvas.plot_week_to_percent() statCanvas.draw() def load_photo(self, left=False, right=False) -> None: beg, end = None, None index = -1 if left: end = self.photo_timestamp elif right: beg = self.photo_timestamp index = 0 records = RecordsDriver.load(beg, end) if records: record = records[index] timestamp = record['timestamp'] self.photo_timestamp = datetime.strptime(timestamp, DATETIME_FORMAT) self.photo_pixmap.load(str(PHOTOS_DIR / f'{timestamp}.jpg')) self.photoImage.setPixmap(self.photo_pixmap) self.display_ihunch_status(self.photoStatusBar, record['human'], record['ihunch']) def toggle_all_timers(self, toggle: bool) -> None: if toggle: self.start_capture_timer_safe() else: self.capture_timer.stop() self.toggle_warn_timer(toggle) self.toggle_stat_timer(toggle) def toggle_warn_timer(self, toggle: bool) -> None: if toggle and self.cameraButton.isChecked(): self.warn_notifier_timer.start() else: self.warn_notifier_timer.stop() def toggle_stat_timer(self, toggle: bool) -> None: if toggle and self.cameraButton.isChecked(): self.stat_notifier_timer.setInterval( self.get_setting_stat_interval()) self.stat_notifier_timer.start() else: self.stat_notifier_timer.stop() def notify_warn_if_bad(self) -> None: minutes = 5 beg = datetime.now() - timedelta(minutes=minutes) records = RecordsDriver.load(beg) stats = [x['ihunch'] > 0.5 for x in records if x['human']] if not stats: return ihunch_percent = sum(stats) / len(stats) * 100 if ihunch_percent < 90: return self.warn_notifier.notify( '거북목 경고', f'최근 {minutes}분 중에 거북목 자세 비중이 {ihunch_percent:.2f}%를 차지합니다!', '거북목 탈출 넘버원', on_action=lambda nid, index: self.settingWarnButton.setChecked( False) if index == 1 else None) def notify_stat(self) -> None: hours = self.stat_notifier_timer.interval() // 3_600_000 beg = datetime.now() - timedelta(hours=hours) records = RecordsDriver.load(beg) stats = [x['ihunch'] > 0.5 for x in records if x['human']] if not stats: return ihunch_percent = sum(stats) / len(stats) * 100 self.stat_notifier.notify( '최근 거북목 통계', f'최근 {hours}시간 중에 거북목 자세 비중이 {ihunch_percent:.2f}%를 차지했습니다.', '거북목 탈출 넘버원', on_action=lambda nid, index: self.settingStatCycleOff.setChecked( True) if index == 1 else None) @staticmethod def create_camera(cameras: list, index: int, viewfinder: QCameraViewfinder, error: Callable) -> QCamera: camera = QCamera(cameras[index]) camera.setViewfinder(viewfinder) camera.setCaptureMode(QCamera.CaptureStillImage) camera.error.connect(error) return camera @staticmethod def create_capture(camera: QCamera, callback: Callable, error: Callable) -> QCameraImageCapture: capture = QCameraImageCapture(camera) capture.setCaptureDestination(QCameraImageCapture.CaptureToBuffer) capture.imageCaptured.connect(callback) capture.error.connect(error) return capture @staticmethod def create_timer(interval: int, callback: Callable) -> QTimer: timer = QTimer() timer.setInterval(interval) timer.timeout.connect(callback) return timer @staticmethod def display_ihunch_status(statusbar: QLabel, human: bool, ihunch: float) -> None: if human: if ihunch > 0.5: text, color = '거북목', 'FF0000' else: text, color = '정상', '23F200' text += f' ({ihunch:.4f})' else: text, color = '자리비움', 'FF971E' statusbar.setText(text) statusbar.setAlignment(Qt.AlignCenter) statusbar.setStyleSheet(f'color: #{color};')