如何用PyQt6显示Python OpenCV图像(Numpy数组)?

0 人关注

我试图用PyQt6来显示OpenCV图像(NumPy数组)。 以前的Qt版本(PyQt4和PyQt5)将NumPy数组转换为 QPixmap ,然后使用 QLabel 显示。 but this doesn't seem to work in PyQt6 .

当我试图显示它时,我得到一个扭曲的图像

from PyQt6.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QHBoxLayout, QGridLayout
from PyQt6.QtGui import QImage, QPixmap 
import sys
import cv2
class DisplayImageWidget(QWidget):
    def __init__(self):
        super(DisplayImageWidget, self).__init__()
        self.image = cv2.imread('2.png')
        self.convert = QImage(self.image, 400, 400, QImage.Format.Format_BGR888)
        self.frame = QLabel()
        self.frame.setPixmap(QPixmap.fromImage(self.convert))
        self.layout = QHBoxLayout(self)
        self.layout.addWidget(self.frame)
if __name__ == '__main__':
    app = QApplication([])
    main_window = QMainWindow()
    main_window.setWindowTitle('Video Frame Acquisition')
    main_window.setFixedSize(500, 500)
    central_widget = QWidget()
    main_layout = QGridLayout()
    central_widget.setLayout(main_layout)
    main_window.setCentralWidget(central_widget)
    display_image_widget = DisplayImageWidget()
    main_layout.addWidget(display_image_widget, 0, 0)
    main_window.show()
    sys.exit(app.exec())

我尝试了所有类型的different QtGui.QImage.Format types但我很确定Format_BGR888应该是正确的。图片正在显示,但我无法让它的格式正确。

python
numpy
opencv
pyqt
pyqt6
nathancy
nathancy
发布于 2022-06-08
1 个回答
nathancy
nathancy
发布于 2022-06-08
已采纳
0 人赞同

好吧,我找到了解决办法。事实证明,你必须传递图像的 width height ,而不是一个任意的尺寸。

self.convert = QImage(self.image, self.image.shape[1], self.image.shape[0], QImage.Format.Format_BGR888)

这解决了随机像素的问题,但由于某种原因,它仍然是倾斜的。

经过一些调查,发现有一个not well documented bytesPerLine(替换代码3】中的【步幅】参数.修复方法是添加strides[0]。该参数指定了某一行的图像像素所需的字节数。但我仍然不确定它的具体作用,因为对于其他图片,不添加额外的参数,图片也能正常显示。

self.convert = QImage(self.image, self.image.shape[1], self.image.shape[0], self.image.strides[0], QImage.Format.Format_BGR888)

Full working code

from PyQt6.QtWidgets import QApplication, QWidget, QMainWindow, QLabel, QHBoxLayout, QGridLayout
from PyQt6.QtGui import QImage, QPixmap 
import sys
import cv2
class DisplayImageWidget(QWidget):
    def __init__(self):
        super(DisplayImageWidget, self).__init__()
        self.image = cv2.imread('2.png')
        self.convert = QImage(self.image, self.image.shape[1], self.image.shape[0], self.image.strides[0], QImage.Format.Format_BGR888)
        self.frame = QLabel()
        self.frame.setPixmap(QPixmap.fromImage(self.convert))
        self.layout = QHBoxLayout(self)
        self.layout.addWidget(self.frame)
if __name__ == '__main__':
    app = QApplication([])
    main_window = QMainWindow()
    main_window.setWindowTitle('Video Frame Acquisition')
    main_window.setFixedSize(500, 500)
    central_widget = QWidget()
    main_layout = QGridLayout()
    central_widget.setLayout(main_layout)
    main_window.setCentralWidget(central_widget)
    display_image_widget = DisplayImageWidget()