python
复制代码
import sys
import cv2
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QPushButton, QComboBox, QHBoxLayout, QSizePolicy
from PyQt5.QtCore import QTimer, Qt
from PyQt5.QtGui import QImage, QPixmap
class CameraApp(QWidget):
def __init__(self):
super().__init__()
# 初始化UI界面
self.setWindowTitle("摄像头实时画面")
self.setGeometry(100, 100, 800, 600)
# 设置窗口永远置顶
self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
# 设置窗口大小策略,允许自由调整
self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
self.setMinimumSize(400, 300) # 设置最小窗口尺寸,避免窗口缩得过小
# 设置布局
self.main_layout = QVBoxLayout()
self.controls_layout = QHBoxLayout()
# QLabel用于显示摄像头画面
self.label = QLabel(self)
self.label.setAlignment(Qt.AlignCenter) # 居中对齐
self.main_layout.addWidget(self.label)
# 摄像头选择下拉菜单
self.camera_selector = QComboBox(self)
self.available_cameras = self.get_available_cameras()
self.camera_selector.addItems(self.available_cameras)
self.camera_selector.currentIndexChanged.connect(self.change_camera)
self.controls_layout.addWidget(self.camera_selector)
# 添加关闭按钮
self.button = QPushButton('关闭摄像头', self)
self.button.clicked.connect(self.close_camera)
self.controls_layout.addWidget(self.button)
self.main_layout.addLayout(self.controls_layout)
self.setLayout(self.main_layout)
# 打开默认摄像头
self.capture = None
self.current_camera_index = 0
self.start_camera(self.current_camera_index)
# 定时器更新视频流
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_frame)
self.timer.start(30) # 每30ms更新一次画面
def get_available_cameras(self):
# 获取可用摄像头的列表
index = 0
available_cameras = []
while True:
cap = cv2.VideoCapture(index)
if not cap.read()[0]: # 没有更多的摄像头
break
available_cameras.append(f"Camera {index}")
cap.release()
index += 1
return available_cameras
def start_camera(self, camera_index):
# 开启选定的摄像头
if self.capture is not None:
self.capture.release() # 释放前一个摄像头
self.capture = cv2.VideoCapture(camera_index)
def change_camera(self, index):
# 切换摄像头
self.current_camera_index = index
self.start_camera(self.current_camera_index)
def update_frame(self):
if self.capture is not None and self.capture.isOpened():
ret, frame = self.capture.read()
if ret:
# 将OpenCV的BGR格式转换为RGB格式
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = frame.shape
bytes_per_line = ch * w
convert_to_Qt_format = QImage(frame.data, w, h, bytes_per_line, QImage.Format_RGB888)
# 动态调整图片大小,适应窗口的大小
scaled_image = convert_to_Qt_format.scaled(self.label.width(), self.label.height(), Qt.KeepAspectRatio)
self.label.setPixmap(QPixmap.fromImage(scaled_image))
def close_camera(self):
# 关闭摄像头
if self.capture is not None:
self.capture.release()
self.close()
def resizeEvent(self, event):
# 重写resizeEvent,当窗口大小改变时触发
if self.capture is not None and self.capture.isOpened():
self.update_frame() # 窗口大小变化时更新显示的画面
super().resizeEvent(event)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = CameraApp()
window.show()
sys.exit(app.exec_())