调整大小时Python OpenCV图像打乱[重复]

Posted

技术标签:

【中文标题】调整大小时Python OpenCV图像打乱[重复]【英文标题】:Python OpenCV image scrambles while resizing [duplicate] 【发布时间】:2019-04-25 04:22:48 【问题描述】:

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

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

这个尺寸有效:

但是这个尺寸不起作用:

我试图以偶数分辨率,比如如果分辨率是 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_())

【问题讨论】:

更改为def next_frame(self):ret, frame = self.cap.read()if ret:frame = cv2.resize(frame, (self.x,self.y ))frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)h, w, ch = frame.shapebytesPerLine = ch * wqImg = QtGui.QImage(frame.data, w, h, bytesPerLine, QtGui.QImage.Format_RGB888)self.label.setPixmap(QtGui.QPixmap.fromImage(qImg)) 我认为问题在于您用于渲染框架的库,而不是与 OpenCV 相关的内容。我可以为您提供的一个建议是尝试将您的帧转换为 BGRA。 你的转换方法不对,需要将bytesPerLine设置为第三个参数,还必须使用表示帧是否有效的变量ret。 如果你看不懂你在第一条评论中留下的代码,我已经在下面的链接中发布了格式化的代码::pastebin.com/A0Qxe95j @eyllanesc,您的解决方案非常完美。向 QImage 添加 byesPerLine 参数起到了神奇的作用。非常感谢。 【参考方案1】:

问题在于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)

【讨论】:

以上是关于调整大小时Python OpenCV图像打乱[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Python,调整文件夹中的图像大小[重复]

OpenCV:自动将窗口大小调整为显示的图像

当使用 OpenCV 完成图像加载和调整大小时,Resnet50 会产生不同的预测

调整图像类型“Mat”opencv C++的大小

调整在Python中使用Numpy和OpenCV绘制的多边形的大小

Python OpenCV3:OpenCV 几何变换