增加讀檔及log事件
This commit is contained in:
parent
b2312d0758
commit
d91bbd1003
@ -14,44 +14,44 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||||||
class Ui_MainWindow(object):
|
class Ui_MainWindow(object):
|
||||||
def setupUi(self, MainWindow):
|
def setupUi(self, MainWindow):
|
||||||
MainWindow.setObjectName("MainWindow")
|
MainWindow.setObjectName("MainWindow")
|
||||||
MainWindow.resize(2024, 1118)
|
MainWindow.resize(2182, 1118)
|
||||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||||
self.centralwidget.setObjectName("centralwidget")
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
|
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
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.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 = QtWidgets.QLabel(self.centralwidget)
|
||||||
self.view_origin.setMinimumSize(QtCore.QSize(1000, 1000))
|
self.view_origin.setMinimumSize(QtCore.QSize(1000, 1000))
|
||||||
self.view_origin.setMaximumSize(QtCore.QSize(1000, 1000))
|
self.view_origin.setMaximumSize(QtCore.QSize(1000, 1000))
|
||||||
self.view_origin.setObjectName("view_origin")
|
self.view_origin.setObjectName("view_origin")
|
||||||
self.gridLayout.addWidget(self.view_origin, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.view_origin, 2, 0, 1, 1)
|
||||||
self.view_predict = QtWidgets.QLabel(self.centralwidget)
|
self.view_predict = QtWidgets.QLabel(self.centralwidget)
|
||||||
self.view_predict.setMinimumSize(QtCore.QSize(1000, 1000))
|
self.view_predict.setMinimumSize(QtCore.QSize(1000, 1000))
|
||||||
self.view_predict.setMaximumSize(QtCore.QSize(1000, 1000))
|
self.view_predict.setMaximumSize(QtCore.QSize(1000, 1000))
|
||||||
self.view_predict.setObjectName("view_predict")
|
self.view_predict.setObjectName("view_predict")
|
||||||
self.gridLayout.addWidget(self.view_predict, 1, 1, 1, 1)
|
self.gridLayout.addWidget(self.view_predict, 2, 1, 1, 1)
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.bt_KeepShot = QtWidgets.QPushButton(self.centralwidget)
|
||||||
|
self.bt_KeepShot.setMinimumSize(QtCore.QSize(150, 50))
|
||||||
|
self.bt_KeepShot.setMaximumSize(QtCore.QSize(100, 50))
|
||||||
|
self.bt_KeepShot.setObjectName("bt_KeepShot")
|
||||||
|
self.verticalLayout.addWidget(self.bt_KeepShot)
|
||||||
|
self.bt_StopKeepShot = QtWidgets.QPushButton(self.centralwidget)
|
||||||
|
self.bt_StopKeepShot.setMinimumSize(QtCore.QSize(150, 50))
|
||||||
|
self.bt_StopKeepShot.setMaximumSize(QtCore.QSize(100, 50))
|
||||||
|
self.bt_StopKeepShot.setObjectName("bt_StopKeepShot")
|
||||||
|
self.verticalLayout.addWidget(self.bt_StopKeepShot)
|
||||||
|
self.bt_detection = QtWidgets.QPushButton(self.centralwidget)
|
||||||
|
self.bt_detection.setMinimumSize(QtCore.QSize(150, 50))
|
||||||
|
self.bt_detection.setMaximumSize(QtCore.QSize(100, 50))
|
||||||
|
self.bt_detection.setObjectName("bt_detection")
|
||||||
|
self.verticalLayout.addWidget(self.bt_detection)
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
|
self.verticalLayout.addItem(spacerItem)
|
||||||
|
self.gridLayout.addLayout(self.verticalLayout, 2, 2, 1, 1)
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 2024, 22))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 2182, 22))
|
||||||
self.menubar.setObjectName("menubar")
|
self.menubar.setObjectName("menubar")
|
||||||
MainWindow.setMenuBar(self.menubar)
|
MainWindow.setMenuBar(self.menubar)
|
||||||
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
self.statusbar = QtWidgets.QStatusBar(MainWindow)
|
||||||
@ -64,8 +64,8 @@ class Ui_MainWindow(object):
|
|||||||
def retranslateUi(self, MainWindow):
|
def retranslateUi(self, MainWindow):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
|
||||||
|
self.view_origin.setText(_translate("MainWindow", "原圖影像"))
|
||||||
|
self.view_predict.setText(_translate("MainWindow", "檢測影像"))
|
||||||
self.bt_KeepShot.setText(_translate("MainWindow", "開始連續取像"))
|
self.bt_KeepShot.setText(_translate("MainWindow", "開始連續取像"))
|
||||||
self.bt_StopKeepShot.setText(_translate("MainWindow", "停止連續取像"))
|
self.bt_StopKeepShot.setText(_translate("MainWindow", "停止連續取像"))
|
||||||
self.bt_detection.setText(_translate("MainWindow", "檢測"))
|
self.bt_detection.setText(_translate("MainWindow", "檢測"))
|
||||||
self.view_origin.setText(_translate("MainWindow", "原圖影像"))
|
|
||||||
self.view_predict.setText(_translate("MainWindow", "檢測影像"))
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>2024</width>
|
<width>2182</width>
|
||||||
<height>1118</height>
|
<height>1118</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -15,81 +15,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="2" column="0">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="bt_KeepShot">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>開始連續取像</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="bt_StopKeepShot">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>停止連續取像</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="bt_detection">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>100</width>
|
|
||||||
<height>50</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>檢測</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>40</width>
|
|
||||||
<height>20</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="view_origin">
|
<widget class="QLabel" name="view_origin">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
@ -108,7 +34,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QLabel" name="view_predict">
|
<widget class="QLabel" name="view_predict">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
@ -127,6 +53,80 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="bt_KeepShot">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>開始連續取像</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="bt_StopKeepShot">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>停止連續取像</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="bt_detection">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>150</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>50</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>檢測</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
@ -134,7 +134,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>2024</width>
|
<width>2182</width>
|
||||||
<height>22</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -4,12 +4,15 @@ import cv2
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
from pypylon import pylon
|
from pypylon import pylon
|
||||||
|
|
||||||
|
from read_ini import ConfigReader
|
||||||
|
|
||||||
class CameraProcess(multiprocessing.Process):
|
class CameraProcess(multiprocessing.Process):
|
||||||
""" 相機擷取獨立進程 """
|
""" 相機擷取獨立進程 """
|
||||||
def __init__(self, image_queue, exposure_time=20000):
|
def __init__(self, image_queue, exposure_time=20000):
|
||||||
super(CameraProcess, self).__init__()
|
super(CameraProcess, self).__init__()
|
||||||
self.image_queue = image_queue
|
self.image_queue = image_queue
|
||||||
self.exposure_time = exposure_time
|
self.config_reader = ConfigReader() # ✅ 創建 `ConfigReader` 物件
|
||||||
|
self.exposure_time = exposure_time if exposure_time is not None else self.config_reader.get_exposure_time()
|
||||||
self.running = multiprocessing.Value('b', True) # 控制進程是否運行
|
self.running = multiprocessing.Value('b', True) # 控制進程是否運行
|
||||||
self.camera = None
|
self.camera = None
|
||||||
|
|
||||||
@ -19,7 +22,7 @@ class CameraProcess(multiprocessing.Process):
|
|||||||
self.camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice())
|
self.camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice())
|
||||||
self.camera.Open()
|
self.camera.Open()
|
||||||
self.camera.ExposureTime.SetValue(float(self.exposure_time))
|
self.camera.ExposureTime.SetValue(float(self.exposure_time))
|
||||||
print("相機連線成功")
|
print(f"相機連線成功,曝光時間: {self.exposure_time} 微秒")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"相機連線失敗: {e}")
|
print(f"相機連線失敗: {e}")
|
||||||
@ -33,7 +36,7 @@ class CameraProcess(multiprocessing.Process):
|
|||||||
self.camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
|
self.camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
|
||||||
|
|
||||||
while self.running.value and self.camera.IsGrabbing():
|
while self.running.value and self.camera.IsGrabbing():
|
||||||
grab_result = self.camera.RetrieveResult(20000, pylon.TimeoutHandling_ThrowException)
|
grab_result = self.camera.RetrieveResult(5000, pylon.TimeoutHandling_ThrowException)
|
||||||
if grab_result.GrabSucceeded():
|
if grab_result.GrabSucceeded():
|
||||||
image = grab_result.Array # 取得影像數據
|
image = grab_result.Array # 取得影像數據
|
||||||
if not self.image_queue.full():
|
if not self.image_queue.full():
|
||||||
@ -46,7 +49,6 @@ class CameraProcess(multiprocessing.Process):
|
|||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
""" 停止相機擷取進程 """
|
""" 停止相機擷取進程 """
|
||||||
print("正在停止相機擷取...")
|
|
||||||
self.running.value = False # 設定為 False,讓 while 迴圈停止
|
self.running.value = False # 設定為 False,讓 while 迴圈停止
|
||||||
self.terminate() # 強制終止進程
|
self.terminate() # 強制終止進程
|
||||||
print("相機擷取進程已終止")
|
print("相機擷取進程已終止")
|
||||||
|
32
detection.py
32
detection.py
@ -4,18 +4,29 @@ import numpy as np
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
from PyQt5 import QtWidgets, QtGui, QtCore
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
from PyQt5.QtCore import QTimer
|
from PyQt5.QtCore import QTimer
|
||||||
|
|
||||||
from Detection_window import Ui_MainWindow
|
from Detection_window import Ui_MainWindow
|
||||||
from camera.camera_process import CameraProcess
|
from camera.camera_process import CameraProcess
|
||||||
|
from read_ini import ConfigReader
|
||||||
|
from log_handler import LogHandler
|
||||||
|
|
||||||
class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow):
|
class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(DetectionApp, self).__init__()
|
super(DetectionApp, self).__init__()
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
|
self.log_handler = LogHandler() # ✅ 建立 LogHandler 物件
|
||||||
|
self.log_handler.write_log("程式啟動") # ✅ 寫入 log: 程式啟動
|
||||||
|
|
||||||
|
# ✅ 讀取 `exposure_time`
|
||||||
|
self.config_reader = ConfigReader()
|
||||||
|
self.exposure_time = self.config_reader.get_exposure_time()
|
||||||
|
|
||||||
# ✅ 先初始化 image_queue,再啟動相機擷取
|
# ✅ 先初始化 image_queue,再啟動相機擷取
|
||||||
self.image_queue = multiprocessing.Queue(maxsize=1)
|
self.image_queue = multiprocessing.Queue(maxsize=1)
|
||||||
self.camera_process = None # 相機進程尚未啟動
|
self.camera_process = None # 相機進程尚未啟動
|
||||||
|
|
||||||
|
# ✅ 連接按鈕事件
|
||||||
self.bt_KeepShot.clicked.connect(self.KeepShot)
|
self.bt_KeepShot.clicked.connect(self.KeepShot)
|
||||||
self.bt_StopKeepShot.clicked.connect(self.StopKeepShot)
|
self.bt_StopKeepShot.clicked.connect(self.StopKeepShot)
|
||||||
|
|
||||||
@ -32,9 +43,11 @@ class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
# ✅ 重新建立 Queue,避免殘留影像影響新擷取
|
# ✅ 重新建立 Queue,避免殘留影像影響新擷取
|
||||||
self.image_queue = multiprocessing.Queue(maxsize=1)
|
self.image_queue = multiprocessing.Queue(maxsize=1)
|
||||||
|
|
||||||
# ✅ 確保 `CameraProcess` 是新的
|
# ✅ 使用 `exposure_time` 啟動相機
|
||||||
self.camera_process = CameraProcess(self.image_queue)
|
self.camera_process = CameraProcess(self.image_queue, exposure_time=self.exposure_time)
|
||||||
self.camera_process.start()
|
self.camera_process.start()
|
||||||
|
self.log_handler.write_log("相機啟動") # ✅ 寫入 log: 相機啟動
|
||||||
|
self.statusbar.showMessage(f"開始擷取影像 (曝光時間: {self.exposure_time} 微秒)")
|
||||||
else:
|
else:
|
||||||
print("相機已經在擷取")
|
print("相機已經在擷取")
|
||||||
|
|
||||||
@ -45,6 +58,7 @@ class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self.camera_process.join() # 等待進程完全結束
|
self.camera_process.join() # 等待進程完全結束
|
||||||
self.camera_process = None
|
self.camera_process = None
|
||||||
print("已停止影像擷取")
|
print("已停止影像擷取")
|
||||||
|
self.log_handler.write_log("相機停止") # ✅ 寫入 log: 相機停止
|
||||||
|
|
||||||
# ✅ 清空 Queue,確保新擷取不會讀取到舊影像
|
# ✅ 清空 Queue,確保新擷取不會讀取到舊影像
|
||||||
while not self.image_queue.empty():
|
while not self.image_queue.empty():
|
||||||
@ -69,12 +83,20 @@ class DetectionApp(QtWidgets.QMainWindow, Ui_MainWindow):
|
|||||||
self.view_origin.setPixmap(pixmap)
|
self.view_origin.setPixmap(pixmap)
|
||||||
|
|
||||||
def closeEvent(self, event):
|
def closeEvent(self, event):
|
||||||
""" 確保程式關閉時正確停止相機擷取進程 """
|
reply = QtWidgets.QMessageBox.question(
|
||||||
self.StopKeepShot() # 確保關閉程式時停止相機擷取
|
self, "確認", "確定要關閉應用程式嗎?",
|
||||||
event.accept() # ✅ 允許視窗關閉
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No
|
||||||
|
)
|
||||||
|
|
||||||
|
if reply == QtWidgets.QMessageBox.Yes:
|
||||||
|
self.StopKeepShot() # 停止相機
|
||||||
|
self.log_handler.write_log("程式關閉") # ✅ 寫入 log: 程式關閉
|
||||||
|
event.accept() # 允許視窗關閉
|
||||||
|
else:
|
||||||
|
event.ignore() # 阻止視窗關閉
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
multiprocessing.freeze_support() # 在 Windows 上執行 multiprocessing 需要這行
|
||||||
app = QtWidgets.QApplication(sys.argv)
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
window = DetectionApp()
|
window = DetectionApp()
|
||||||
window.show()
|
window.show()
|
||||||
|
34
log_handler.py
Normal file
34
log_handler.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
class LogHandler:
|
||||||
|
""" 日誌處理類別,負責寫入 log 檔案 """
|
||||||
|
|
||||||
|
def __init__(self, log_dir="logging"):
|
||||||
|
""" 初始化 log 系統 """
|
||||||
|
self.log_dir = log_dir
|
||||||
|
self.ensure_log_directory_exists()
|
||||||
|
self.log_file = self.get_log_filename()
|
||||||
|
|
||||||
|
def ensure_log_directory_exists(self):
|
||||||
|
""" 確保 logging 資料夾存在,如果不存在則建立 """
|
||||||
|
if not os.path.exists(self.log_dir):
|
||||||
|
os.makedirs(self.log_dir)
|
||||||
|
|
||||||
|
def get_log_filename(self):
|
||||||
|
""" 取得今日的 log 檔案名稱(YYYY-MM-DD.txt) """
|
||||||
|
today = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||||
|
return os.path.join(self.log_dir, f"{today}.txt")
|
||||||
|
|
||||||
|
def write_log(self, event):
|
||||||
|
""" 寫入 log 訊息 """
|
||||||
|
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
log_message = f"[{timestamp}] {event}\n"
|
||||||
|
|
||||||
|
# 確保 log 檔案是最新的(每天更新)
|
||||||
|
self.log_file = self.get_log_filename()
|
||||||
|
|
||||||
|
with open(self.log_file, "a", encoding="utf-8") as file:
|
||||||
|
file.write(log_message)
|
||||||
|
|
||||||
|
print(f"📄 [LOG] {log_message.strip()}") # 也在 console 顯示 log
|
18
logging/2025-03-10.txt
Normal file
18
logging/2025-03-10.txt
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[2025-03-10 17:50:57] 程式啟動
|
||||||
|
[2025-03-10 17:51:04] 相機啟動
|
||||||
|
[2025-03-10 17:51:22] 相機停止
|
||||||
|
[2025-03-10 17:51:33] 相機啟動
|
||||||
|
[2025-03-10 17:51:57] 相機停止
|
||||||
|
[2025-03-10 17:51:58] 相機啟動
|
||||||
|
[2025-03-10 17:52:04] 相機停止
|
||||||
|
[2025-03-10 17:52:13] 程式關閉
|
||||||
|
[2025-03-10 21:02:35] 程式啟動
|
||||||
|
[2025-03-10 21:02:44] 相機啟動
|
||||||
|
[2025-03-10 21:03:24] 相機停止
|
||||||
|
[2025-03-10 21:03:27] 程式關閉
|
||||||
|
[2025-03-10 21:04:15] 程式啟動
|
||||||
|
[2025-03-10 21:04:18] 相機啟動
|
||||||
|
[2025-03-10 21:04:29] 相機停止
|
||||||
|
[2025-03-10 21:04:32] 相機啟動
|
||||||
|
[2025-03-10 21:04:37] 相機停止
|
||||||
|
[2025-03-10 21:04:44] 程式關閉
|
BIN
model/best.pt
Normal file
BIN
model/best.pt
Normal file
Binary file not shown.
@ -1,2 +1,2 @@
|
|||||||
[Camera_Setting]
|
[Camera_Setting]
|
||||||
exposuretime_edge = 18122
|
exposuretime = 30000
|
||||||
|
25
read_ini.py
Normal file
25
read_ini.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import configparser
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigReader:
|
||||||
|
""" 用於讀取 parameter.ini 設定檔的類別 """
|
||||||
|
|
||||||
|
def __init__(self, ini_file="parameter.ini"):
|
||||||
|
""" 初始化並讀取 ini 檔案 """
|
||||||
|
self.ini_file = ini_file
|
||||||
|
self.config = configparser.ConfigParser()
|
||||||
|
self.read_config()
|
||||||
|
|
||||||
|
def read_config(self):
|
||||||
|
""" 讀取 ini 檔案內容 """
|
||||||
|
self.config.read(self.ini_file)
|
||||||
|
|
||||||
|
def get_exposure_time(self):
|
||||||
|
""" 取得曝光時間,如果讀取失敗則回傳預設值 5000 """
|
||||||
|
try:
|
||||||
|
exposure_time = int(self.config["Camera_Setting"]["exposuretime"])
|
||||||
|
print(f"讀取曝光時間: {exposure_time} 微秒")
|
||||||
|
return exposure_time
|
||||||
|
except Exception as e:
|
||||||
|
print(f"讀取 `parameter.ini` 失敗: {e}")
|
||||||
|
return 5000 # 預設曝光時間
|
Loading…
x
Reference in New Issue
Block a user