From b2312d0758098ab6619fbd55d4da55a0a84a046d Mon Sep 17 00:00:00 2001 From: JEFF Date: Mon, 10 Mar 2025 13:45:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=9B=B8=E6=A9=9F=E9=80=B2?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Detection_window.py | 23 ++++++++-- Detection_window.ui | 95 +++++++++++++++++++++++++++++++--------- camera/camera_process.py | 5 ++- detection.py | 41 ++++++++++++++--- 4 files changed, 134 insertions(+), 30 deletions(-) diff --git a/Detection_window.py b/Detection_window.py index 68095f1..d9adb6b 100644 --- a/Detection_window.py +++ b/Detection_window.py @@ -14,16 +14,31 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") - MainWindow.resize(1308, 865) + MainWindow.resize(2024, 1118) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.bt_KeepShot = QtWidgets.QPushButton(self.centralwidget) + self.bt_KeepShot.setMinimumSize(QtCore.QSize(100, 50)) + self.bt_KeepShot.setMaximumSize(QtCore.QSize(100, 50)) + self.bt_KeepShot.setObjectName("bt_KeepShot") + self.horizontalLayout.addWidget(self.bt_KeepShot) + self.bt_StopKeepShot = QtWidgets.QPushButton(self.centralwidget) + self.bt_StopKeepShot.setMinimumSize(QtCore.QSize(100, 50)) + self.bt_StopKeepShot.setMaximumSize(QtCore.QSize(100, 50)) + self.bt_StopKeepShot.setObjectName("bt_StopKeepShot") + self.horizontalLayout.addWidget(self.bt_StopKeepShot) self.bt_detection = QtWidgets.QPushButton(self.centralwidget) self.bt_detection.setMinimumSize(QtCore.QSize(100, 50)) self.bt_detection.setMaximumSize(QtCore.QSize(100, 50)) self.bt_detection.setObjectName("bt_detection") - self.gridLayout.addWidget(self.bt_detection, 0, 0, 1, 1) + self.horizontalLayout.addWidget(self.bt_detection) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1) self.view_origin = QtWidgets.QLabel(self.centralwidget) self.view_origin.setMinimumSize(QtCore.QSize(1000, 1000)) self.view_origin.setMaximumSize(QtCore.QSize(1000, 1000)) @@ -36,7 +51,7 @@ class Ui_MainWindow(object): self.gridLayout.addWidget(self.view_predict, 1, 1, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1308, 22)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 2024, 22)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) @@ -49,6 +64,8 @@ class Ui_MainWindow(object): def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) + self.bt_KeepShot.setText(_translate("MainWindow", "開始連續取像")) + self.bt_StopKeepShot.setText(_translate("MainWindow", "停止連續取像")) self.bt_detection.setText(_translate("MainWindow", "檢測")) self.view_origin.setText(_translate("MainWindow", "原圖影像")) self.view_predict.setText(_translate("MainWindow", "檢測影像")) diff --git a/Detection_window.ui b/Detection_window.ui index 3f32aa8..abfef76 100644 --- a/Detection_window.ui +++ b/Detection_window.ui @@ -6,8 +6,8 @@ 0 0 - 1308 - 865 + 2024 + 1118 @@ -16,23 +16,78 @@ - - - - 100 - 50 - - - - - 100 - 50 - - - - 檢測 - - + + + + + + 100 + 50 + + + + + 100 + 50 + + + + 開始連續取像 + + + + + + + + 100 + 50 + + + + + 100 + 50 + + + + 停止連續取像 + + + + + + + + 100 + 50 + + + + + 100 + 50 + + + + 檢測 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + @@ -79,7 +134,7 @@ 0 0 - 1308 + 2024 22 diff --git a/camera/camera_process.py b/camera/camera_process.py index 73fff3c..3fe5468 100644 --- a/camera/camera_process.py +++ b/camera/camera_process.py @@ -46,4 +46,7 @@ class CameraProcess(multiprocessing.Process): def stop(self): """ 停止相機擷取進程 """ - self.running.value = False + print("正在停止相機擷取...") + self.running.value = False # 設定為 False,讓 while 迴圈停止 + self.terminate() # 強制終止進程 + print("相機擷取進程已終止") diff --git a/detection.py b/detection.py index 652b1d5..3b47da2 100644 --- a/detection.py +++ b/detection.py @@ -12,17 +12,47 @@ class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow): super(DetectionApp, self).__init__() self.setupUi(self) + # ✅ 先初始化 image_queue,再啟動相機擷取 self.image_queue = multiprocessing.Queue(maxsize=1) + self.camera_process = None # 相機進程尚未啟動 - # ✅ 啟動 CameraProcess - self.camera_process = CameraProcess(self.image_queue) - self.camera_process.start() + self.bt_KeepShot.clicked.connect(self.KeepShot) + self.bt_StopKeepShot.clicked.connect(self.StopKeepShot) # ✅ 設定 QTimer,每 100ms 更新影像 self.timer = QTimer(self) self.timer.timeout.connect(self.update_view_origin) self.timer.start(100) # 每 100ms 更新一次影像 + def KeepShot(self): + """ 啟動相機擷取 """ + if self.camera_process is None or not self.camera_process.is_alive(): + self.StopKeepShot() # 確保先停止舊的 Process,避免衝突 + + # ✅ 重新建立 Queue,避免殘留影像影響新擷取 + self.image_queue = multiprocessing.Queue(maxsize=1) + + # ✅ 確保 `CameraProcess` 是新的 + self.camera_process = CameraProcess(self.image_queue) + self.camera_process.start() + else: + print("相機已經在擷取") + + def StopKeepShot(self): + """ 停止相機擷取 """ + if self.camera_process and self.camera_process.is_alive(): + self.camera_process.stop() # 停止擷取 + self.camera_process.join() # 等待進程完全結束 + self.camera_process = None + print("已停止影像擷取") + + # ✅ 清空 Queue,確保新擷取不會讀取到舊影像 + while not self.image_queue.empty(): + try: + self.image_queue.get_nowait() + except: + break + def update_view_origin(self): """ 從 Queue 獲取影像並顯示在 QLabel (view_origin) 上 """ if not self.image_queue.empty(): @@ -40,9 +70,8 @@ class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow): def closeEvent(self, event): """ 確保程式關閉時正確停止相機擷取進程 """ - self.camera_process.stop() # 停止相機擷取 - self.camera_process.join() # 等待進程結束 - event.accept() + self.StopKeepShot() # 確保關閉程式時停止相機擷取 + event.accept() # ✅ 允許視窗關閉 if __name__ == "__main__":