调整大小时Python OpenCV图像混乱

时间:2019-04-25 04:22:48

标签: python opencv pyqt

我正在动态调整通过OpenCV从网络摄像头收到的图像帧的大小,但是它显示了失真的图像。

给出下面的代码和ui文件。 要调整大小,请按住鼠标右键并拖动。

此大小有效: enter image description here

但是这个大小不起作用:
enter image description here

我试图将分辨率设为偶数,例如如果分辨率为623x420,那么我会将其转换为624x420。这减少了加扰,但是对于某些大小仍然会发生。尝试添加等待键,但没有效果。 尝试使用视频文件而不是网络摄像头,结果是相同的。

import sys
from PyQt5 import QtWidgets, QtGui, QtCore
import cv2
from we import Ui_MainWindow

class MainWindow_exec(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        QtWidgets.QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.fps=24
        self.start_camera()
        self.rightClick=None
        self.x = 600
        self.y = 400

    def mousePressEvent(self, QMouseEvent):
        self.timer.stop()
        self.press = QMouseEvent.pos()

        if QMouseEvent.button() == QtCore.Qt.RightButton:
            self.rdragx = QMouseEvent.x()
            self.rdragy = QMouseEvent.y()        
            self.currentx = self.width()
            self.currenty = self.height()
            self.rightClick = True

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            globalPos = event.globalPos()
            self.move(globalPos-self.press)

        if self.rightClick == True:
            self.x = self.currentx + event.x() - self.rdragx
            self.y = self.currenty + event.y() - self.rdragy
            self.resize(self.x, self.y)
            self.label.setFixedSize(self.x, self.y)

    def mouseReleaseEvent(self, event):
        self.rightClick = False
        self.timer.start(1000./self.fps)

    def next_frame(self):
        ret, frame = self.cap.read()
        frame = cv2.resize(frame,(self.x,self.y ))
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
        pix = QtGui.QPixmap.fromImage(img)
        self.label.setPixmap(pix)

    def start_camera(self):
        self.cap = cv2.VideoCapture(0)
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.next_frame)
        self.timer.start(1000./self.fps)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow1 = MainWindow_exec()
    MainWindow1.show()
    sys.exit(app.exec_())

UI文件we.py

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(532, 353)
        MainWindow.setWindowOpacity(1.0)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setSpacing(0)
        self.gridLayout.setObjectName("gridLayout")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setStyleSheet("background:grey")
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)

        QtCore.QMetaObject.connectSlotsByName(MainWindow)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

问题在于QImage期望数据行被填充4字节。

将此添加到文件的开头

import numpy as np

def padded_row(row_size, padding=4):
    return (row_size + padding - 1) // padding * padding

在将边框传递给QImage之前,将边框添加到边框:

def next_frame(self):
    ret, frame = self.cap.read()
    frame = cv2.resize(frame,(self.x,self.y ))
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    padded_frame = np.zeros((padded_row(self.x * 3), self.y), 'u1')
    padded_frame[:self.x * 3, :] = frame
    frame = padded_frame

    img = QtGui.QImage(frame, frame.shape[1], frame.shape[0], QtGui.QImage.Format_RGB888)
    pix = QtGui.QPixmap.fromImage(img)
    self.label.setPixmap(pix)