调整大小时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.shape
bytesPerLine = ch * w
qImg = 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图像打乱[重复]的主要内容,如果未能解决你的问题,请参考以下文章
当使用 OpenCV 完成图像加载和调整大小时,Resnet50 会产生不同的预测