将numpy数组转换为QImag时出现内存顺序行为问题

2024-09-30 12:11:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我在PyQt4中有一个简单的查看器,当从numpy数组(8位灰度)转换为要显示的QImage时,我有一些奇怪的行为。在我看来,当我试图从一个转置的数组构造一个QImage时,似乎有些事情正在变得混乱,即使内存顺序应该已经更新(也就是说,它不仅仅是一个具有不同步幅的视图)。在

下面是一个严重削减版本的查看器:

import numpy as np
from PyQt4 import QtGui

class SimpleViewer(QtGui.QMainWindow):

    def __init__(self, data, parent=None):
        super(SimpleViewer, self).__init__(parent=parent)

        hgt, wid = data.shape

        dmin = data.min()
        dmax = data.max()
        bdata = ((data - dmin)/(dmax - dmin)*255).astype(np.uint8)

        img = QtGui.QImage(bdata, wid, hgt, QtGui.QImage.Format_Indexed8)

        self.scene = QtGui.QGraphicsScene(0, 0, wid, hgt)
        self.px = self.scene.addPixmap(QtGui.QPixmap.fromImage(img))

        self.view = QtGui.QGraphicsView(self.scene)
        self.setCentralWidget(self.view)


if __name__ == "__main__":

    app = QtGui.QApplication.instance()
    if app is None:
        app = QtGui.QApplication(['python'])

    xx, yy = np.meshgrid(np.arange(-100,100), np.arange(350))
    zz = xx * np.cos(yy/350.*6*np.pi)

    viewer = SimpleViewer(zz)
    viewer.show()
    app.exec_()

现在,这会产生这样的结果,很好:

vertical-is-okay

但是,我需要查看我的真实图像,第一个维度是“x”,第二个维度是“y”,所以它需要被转置(加上一个y-flip,原点在左下角,但这超出了这里的范围)。在

如果我将hgt, wid = data.shape更改为wid, hgt = data.shape,而不做任何其他操作(这是错误的),我得到以下结果。这是有道理的,因为QImage只是在读记忆。在

bad-memory-order

但是,如果我还传入bdata.T.copy()而不是bdata,那么我预计数组将被转置,内存将被复制操作重新排序。但我得到的是:

problem

它离得太近了,但出于某种原因只差了一根头发。另外,我注意到,如果尺寸恰好是彼此的整数倍(例如200x100),那么结果就可以了。怎么回事?我是不是错过了一些非常愚蠢的事情?

我不知道这是PyQt问题还是numpy问题。。。转置后的数组使用matplotlib可以很好地绘制,但是matplotlib处理跨步,因此这可能没有任何意义。在

我在Python2.7和Python3.5中得到了相同的行为。PyQt4的版本是4.11.4,使用的是Qt版本4.8.7。Numpy版本是1.10.1。在


Tags: self版本numpyappdatanp数组parent
1条回答
网友
1楼 · 发布于 2024-09-30 12:11:46

这个问题源于QImage的创建。在

img = QtGui.QImage(bdata, wid, hgt, QtGui.QImage.Format_Indexed8)

您正在使用的构造函数的签名的documentation表示

... data must be 32-bit aligned, and each scanline of data in the image must also be 32-bit aligned.

如果您更改数组的维数,使其与32位对齐(例如使用xx, yy = np.meshgrid(np.arange(-128,128), np.arange(384))),则代码可以正常工作。在

要更正此问题而不需要每行32个字节的倍数,您需要对QImage使用稍微different constructor

^{pr2}$

在您的情况下,这很简单:

^{3}$

因为每个像素包含1个字节的信息。在

相关问题 更多 >

    热门问题