Python 视频流图像失真

Python 视频流图像失真,python,multithreading,opencv,pyqt,video-streaming,Python,Multithreading,Opencv,Pyqt,Video Streaming,我正在尝试使用OpenCV制作一个多摄像头视频流,并使用PyQt for GUI。代码在全高清模式下运行良好,但是当我改变显示器的分辨率时,流会变得失真。谁能告诉我为什么会这样 以下是供您参考的屏幕截图: 1920*1080屏幕截图(全高清) 1600*900屏幕截图 1366*768的屏幕截图 代码如下: from PyQt4 import QtCore, QtGui from threading import Thread from collections import deque f

我正在尝试使用OpenCV制作一个多摄像头视频流,并使用PyQt for GUI。代码在全高清模式下运行良好,但是当我改变显示器的分辨率时,流会变得失真。谁能告诉我为什么会这样

以下是供您参考的屏幕截图:

1920*1080屏幕截图(全高清)

1600*900屏幕截图

1366*768的屏幕截图

代码如下:

from PyQt4 import QtCore, QtGui
from threading import Thread
from collections import deque
from datetime import datetime
import time
import sys
import cv2
import imutils

class CameraWidget(QtGui.QWidget):

    def __init__(self, width, height, stream_link=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.screen_width = width
        self.screen_height = height
        self.maintain_aspect_ratio = aspect_ratio

        self.camera_stream_link = stream_link

        # Flag to check if camera is valid/working
        self.online = False
        self.capture = None
        self.video_frame = QtGui.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):
        """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:
            QtGui.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))

            # Convert to pixmap and set to video frame
            self.img = QtGui.QImage(self.frame, self.frame.shape[1], self.frame.shape[0], QtGui.QImage.Format_RGB888).rgbSwapped()
            self.pix = QtGui.QPixmap.fromImage(self.img)
            self.video_frame.setPixmap(self.pix)

    def get_video_frame(self):
        return self.video_frame
从PyQt4导入QtCore,QtGui
从线程导入线程
从集合导入deque
从日期时间导入日期时间
导入时间
导入系统
进口cv2
导入imutils
类CameraWidget(QtGui.QWidget):
定义初始值(自身、宽度、高度、流链接=0、纵横比=False、父项=None、定义大小=1):
超级(CameraWidget,self)。\u初始化\u(父级)
#初始化用于存储从流读取的帧的deque
self.deque=deque(maxlen=deque\u尺寸)
self.screen_width=宽度
self.screen\u height=高度
self.maintage\u aspect\u ratio=aspect\u ratio
self.camera\u stream\u link=流链接
#用于检查摄像机是否有效/工作的标志
self.online=False
self.capture=无
self.video_frame=QtGui.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_帧(自身):
“”“读取帧、调整大小并将图像转换为像素贴图”“”
尽管如此:
尝试:
如果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()
我找到了解决方案,齐玛格对故障负责

            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)

我找到了解决办法,齐玛格对这件事负责

            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)

那么,使用哪种方法来调整图像的大小:
imutils.resize
imutils.resize
?我以前没有使用PyQt,但我熟悉Qt。在我看来,框架的宽度和高度应该与UI相同。如果不是,您可以得到这样的结果。@ZdaR cv2.resize在这里使用,而不是imutils.resize,因为If条件是False@YunusTemurlenk如果是这种情况,那么为什么它在全高清模式下工作?那么使用哪种方法来调整图像的大小:
imutils.resize
imutils.resize
?我以前没有使用过PyQt,但现在使用了熟悉Qt。在我看来,框架的宽度和高度应该与UI相同。如果不是,您可以得到这样的结果。@ZdaR cv2.resize在这里使用,而不是imutils.resize,因为If条件是False@YunusTemurlenk如果是这样的话,为什么它在全高清下工作?