AP/camera/test.py
2025-03-07 12:01:16 +08:00

131 lines
4.6 KiB
Python

import sys
import numpy as np
import cv2
from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout, QPushButton
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QThread, pyqtSignal
from pypylon import pylon
class BaslerCameraThread(QThread):
"""相機影像擷取執行緒"""
frame_signal = pyqtSignal(np.ndarray) # 發送影像訊號
def __init__(self):
super().__init__()
self.running = True
self.camera = None
def run(self):
"""背景執行擷取 Basler 相機影像"""
try:
# 連接 Basler 相機
self.camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice())
self.camera.Open()
print("✅ 相機成功開啟!")
# 設定擷取策略
self.camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
# 設定影像格式轉換
converter = pylon.ImageFormatConverter()
converter.OutputPixelFormat = pylon.PixelType_BGR8packed
converter.OutputBitAlignment = pylon.OutputBitAlignment_MsbAligned
while self.running and self.camera.IsGrabbing():
grabResult = self.camera.RetrieveResult(500, pylon.TimeoutHandling_Return)
if grabResult is None:
print("⚠️ 無法獲取影像,可能相機未正常運行!")
elif grabResult.GrabSucceeded():
image = converter.Convert(grabResult)
frame = image.GetArray()
self.frame_signal.emit(frame) # 發送影像訊號
else:
print(f"❌ 擷取失敗!錯誤碼: {grabResult.GetErrorCode()}, 訊息: {grabResult.GetErrorDescription()}")
print("🛠️ 嘗試重新啟動相機...")
self.restart_camera() # 重新啟動相機
grabResult.Release()
except Exception as e:
print(f"🚨 Basler 相機錯誤: {e}")
def restart_camera(self):
"""重新啟動相機"""
if self.camera and self.camera.IsOpen():
self.camera.Close()
print("🔄 相機已關閉,嘗試重新啟動...")
self.camera = pylon.InstantCamera(pylon.TlFactory.GetInstance().CreateFirstDevice())
self.camera.Open()
print("✅ 相機重新啟動成功!")
self.camera.StartGrabbing(pylon.GrabStrategy_LatestImageOnly)
def stop(self):
"""停止影像擷取"""
self.running = False
if self.camera and self.camera.IsOpen():
self.camera.StopGrabbing()
self.camera.Close()
print("🔻 相機已關閉!")
class BaslerCameraApp(QWidget):
"""主視窗,顯示 Basler 相機畫面"""
def __init__(self):
super().__init__()
self.initUI()
self.camera_thread = BaslerCameraThread()
self.camera_thread.frame_signal.connect(self.update_frame)
def initUI(self):
self.setWindowTitle("Basler Camera Viewer")
self.setGeometry(100, 100, 800, 600)
self.image_label = QLabel(self)
self.image_label.setFixedSize(800, 600)
self.start_button = QPushButton("開始擷取", self)
self.start_button.clicked.connect(self.start_camera)
self.stop_button = QPushButton("停止擷取", self)
self.stop_button.clicked.connect(self.stop_camera)
layout = QVBoxLayout()
layout.addWidget(self.image_label)
layout.addWidget(self.start_button)
layout.addWidget(self.stop_button)
self.setLayout(layout)
def start_camera(self):
"""開始影像擷取"""
if not self.camera_thread.isRunning():
self.camera_thread.running = True
self.camera_thread.start()
print("▶️ 影像擷取開始!")
def stop_camera(self):
"""停止影像擷取"""
self.camera_thread.stop()
print("⏹️ 影像擷取停止!")
def update_frame(self, frame):
"""更新 UI 影像"""
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 轉換顏色格式
h, w, ch = frame.shape
bytes_per_line = ch * w
qt_image = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
pixmap = QPixmap.fromImage(qt_image)
self.image_label.setPixmap(pixmap)
def closeEvent(self, event):
"""視窗關閉時停止相機"""
self.camera_thread.stop()
event.accept()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = BaslerCameraApp()
window.show()
sys.exit(app.exec_())