Python PyQt小部件的大小不断增加,并退出窗口
我已经用PyQt5编写了一个应用程序。我基本上是在显示一个摄像头提要(在本例中是我的网络摄像头),但问题是,在运行时帧大小不断增加,最终会从我的笔记本电脑屏幕上消失。我想不出是什么问题 谁能解释一下我做错了什么 下面是代码片段Python PyQt小部件的大小不断增加,并退出窗口,python,python-3.x,user-interface,pyqt,pyqt5,Python,Python 3.x,User Interface,Pyqt,Pyqt5,我已经用PyQt5编写了一个应用程序。我基本上是在显示一个摄像头提要(在本例中是我的网络摄像头),但问题是,在运行时帧大小不断增加,最终会从我的笔记本电脑屏幕上消失。我想不出是什么问题 谁能解释一下我做错了什么 下面是代码片段 from PyQt5 import QtCore, QtGui, QtWidgets from threading import Thread from collections import deque from datetime import datetime impo
from PyQt5 import QtCore, QtGui, QtWidgets
from threading import Thread
from collections import deque
from datetime import datetime
import time
import sys
import cv2
import imutils
class CameraWidget(QtWidgets.QWidget):
"""Independent camera feed
Uses threading to grab IP camera frames in the background
@param width - Width of the video frame
@param height - Height of the video frame
@param stream_link - IP/RTSP/Webcam link
@param aspect_ratio - Whether to maintain frame aspect ratio or force into fraame
"""
def __init__(self, width=0, height=0, aspect_ratio=False, parent=None, deque_size=1):
super(CameraWidget, self).__init__(parent)
# Initialize deque used to store frames read from the stream
self.deque = deque(maxlen=deque_size)
self.maintain_aspect_ratio = aspect_ratio
self.camera_stream_link = 0
# Flag to check if camera is valid/working
self.online = False
self.capture = None
self.video_frame = QtWidgets.QLabel()
self.load_network_stream()
# Start background frame grabbing
self.get_frame_thread = Thread(target=self.get_frame, args=())
self.get_frame_thread.daemon = True
self.get_frame_thread.start()
# Periodically set video frame to display
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.set_frame)
self.timer.start(.5)
print('Started camera: {}'.format(self.camera_stream_link))
def load_network_stream(self):
"""Verifies stream link and open new stream if valid"""
def load_network_stream_thread():
if self.verify_network_stream(self.camera_stream_link):
self.capture = cv2.VideoCapture(self.camera_stream_link)
self.online = True
self.load_stream_thread = Thread(target=load_network_stream_thread, args=())
self.load_stream_thread.daemon = True
self.load_stream_thread.start()
def verify_network_stream(self, link):
"""Attempts to receive a frame from given link"""
cap = cv2.VideoCapture(link)
if not cap.isOpened():
return False
cap.release()
return True
def get_frame(self):
# time.sleep(5)
"""Reads frame, resizes, and converts image to pixmap"""
while True:
try:
if self.capture.isOpened() and self.online:
# Read next frame from stream and insert into deque
status, frame = self.capture.read()
if status:
self.deque.append(frame)
else:
self.capture.release()
self.online = False
else:
# Attempt to reconnect
print('attempting to reconnect', self.camera_stream_link)
self.load_network_stream()
self.spin(2)
self.spin(.001)
except AttributeError:
pass
def spin(self, seconds):
"""Pause for set amount of seconds, replaces time.sleep so program doesnt stall"""
time_end = time.time() + seconds
while time.time() < time_end:
QtWidgets.QApplication.processEvents()
def set_frame(self):
"""Sets pixmap image to video frame"""
if not self.online:
self.spin(1)
return
if self.deque and self.online:
# Grab latest frame
frame = self.deque[-1]
# Keep frame aspect ratio
if self.maintain_aspect_ratio:
self.frame = imutils.resize(frame, width=self.screen_width)
# Force resize
else:
self.frame = cv2.resize(frame, (self.screen_width, self.screen_height))
self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
h, w, ch = self.frame.shape
bytesPerLine = ch * w
# Convert to pixmap and set to video frame
self.img = QtGui.QImage(self.frame, w, h, bytesPerLine, QtGui.QImage.Format_RGB888)
self.pix = QtGui.QPixmap.fromImage(self.img)
self.video_frame.setPixmap(self.pix)
def set_frame_params(self, width, height):
self.screen_width = width
self.screen_height = height
def get_video_frame(self):
self.video_frame.setScaledContents(True)
return self.video_frame
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
# Middle frame
self.mid_frame = QtWidgets.QFrame()
self.mid_frame.setStyleSheet("background-color: rgb(153, 187, 255)")
self.camera = CameraWidget()
# Create camera widgets
print('Creating Camera Widgets...')
self.video_frame = self.camera.get_video_frame()
self.mid_layout = QtWidgets.QHBoxLayout()
self.mid_layout.addWidget(self.video_frame)
self.mid_frame.setLayout(self.mid_layout)
self.widget = QtWidgets.QWidget()
self.layout = QtWidgets.QVBoxLayout()
self.layout.addWidget(self.mid_frame)
self.layout.setContentsMargins(0,0,0,0)
self.layout.setSpacing(0)
self.widget.setLayout(self.layout)
self.setCentralWidget(self.widget)
def event(self, e):
if e.type() in (QtCore.QEvent.Show, QtCore.QEvent.Resize):
print("resize ", self.mid_frame.width(), self.mid_frame.height())
self.camera.set_frame_params(self.mid_frame.width()-10, self.mid_frame.height()-10)
return QtWidgets.QMainWindow.event(self, e)
if __name__ == '__main__':
# Create main application window
app = QtWidgets.QApplication([])
app.setStyle(QtWidgets.QStyleFactory.create("Cleanlooks"))
w = MainWindow()
w.showMaximized()
sys.exit(app.exec_())
从PyQt5导入QtCore、QtGui、qtwidget
从线程导入线程
从集合导入deque
从日期时间导入日期时间
导入时间
导入系统
进口cv2
导入imutils
类CameraWidget(QtWidgets.QWidget):
独立摄像机馈送
使用线程在背景中捕获IP摄像头帧
@param width—视频帧的宽度
@param height—视频帧的高度
@参数流链接-IP/RTSP/Webcam链接
@参数纵横比-是保持帧纵横比还是强制进入帧
"""
定义初始值(自,宽度=0,高度=0,纵横比=False,父项=None,定义大小=1):
超级(CameraWidget,self)。\u初始化\u(父级)
#初始化用于存储从流读取的帧的deque
self.deque=deque(maxlen=deque\u尺寸)
self.maintage\u aspect\u ratio=aspect\u ratio
self.camera\u stream\u link=0
#用于检查摄像机是否有效/工作的标志
self.online=False
self.capture=无
self.video_frame=qtwidts.QLabel()
self.load\u网络\u流()
#开始背景帧抓取
self.get\u frame\u thread=thread(target=self.get\u frame,args=())
self.get\u frame\u thread.daemon=True
self.get\u frame\u thread.start()
#定期设置要显示的视频帧
self.timer=QtCore.QTimer()
self.timer.timeout.connect(self.set\u帧)
self.timer.start(.5)
打印('Started camera:{}'。格式(self.camera\u stream\u link))
def加载网络流(自):
“”“验证流链接并打开新流(如果有效)”
def load_network_stream_thread():
如果自验证网络流(自摄像机流链接):
self.capture=cv2.VideoCapture(self.camera\u stream\u链接)
self.online=True
self.load\u stream\u thread=thread(target=load\u network\u stream\u thread,args=())
self.load\u stream\u thread.daemon=True
self.load\u stream\u thread.start()
def验证网络流(自身、链路):
“”“尝试从给定链接接收帧”“”
cap=cv2.视频捕获(链接)
如果不是cap.ISOPEND():
返回错误
第1章释放()
返回真值
def get_帧(自身):
#时间。睡眠(5)
“”“读取帧、调整大小并将图像转换为像素贴图”“”
尽管如此:
尝试:
如果self.capture.isOpened()和self.online:
#从流中读取下一帧并插入到deque中
状态,frame=self.capture.read()
如果状态:
self.deque.append(框架)
其他:
self.capture.release()
self.online=False
其他:
#尝试重新连接
打印('尝试重新连接',self.camera\u stream\u link)
self.load\u网络\u流()
自转(2)
自转(.001)
除属性错误外:
通过
def旋转(自身,秒):
“”“暂停设置的秒数,替换时间。休眠,使程序不会暂停”“”
time_end=time.time()+秒
while time.time()