【问题标题】:Convert numpy array to PySide QPixmap将 numpy 数组转换为 PySide QPixmap
【发布时间】:2012-03-20 20:01:03
【问题描述】:

我想将图像转换为 NumPy 数组到 PySide QPixmap,所以我可以显示它(编辑:在我的 PySide UI 中)。我已经找到了这个工具:qimage2ndarray,但它只适用于 PyQt4。我尝试对其进行更改以使其与 PySide 一起使用,但我必须更改该工具的 C 部分,而且我没有使用 C 的经验。我该怎么做或有其他选择吗?

【问题讨论】:

    标签: python numpy pyside


    【解决方案1】:

    另一种选择是只使用 PIL 库。

    >>> import numpy as np
    >>> import Image
    >>> im = Image.fromarray(np.random.randint(0,256,size=(100,100,3)).astype(np.uint8))
    >>> im.show()
    

    您可以查看http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html 处的 QPixmap 构造函数。

    看起来你应该可以直接在构造函数中使用 numpy 数组:

    类 PySide.QtGui.QImage(数据、宽度、高度、格式)

    格式参数是以下之一:http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html#PySide.QtGui.PySide.QtGui.QImage.Format

    因此,例如,您可以执行以下操作:

    >>> a = np.random.randint(0,256,size=(100,100,3)).astype(np.uint32)
    >>> b = (255 << 24 | a[:,:,0] << 16 | a[:,:,1] << 8 | a[:,:,2]).flatten() # pack RGB values
    >>> im = PySide.QtGui.QImage(b, 100, 100, PySide.QtGui.QImage.Format_RGB32)
    

    我没有安装 PySide,所以我没有对此进行测试。它可能不会按原样工作,但它可能会引导您朝着正确的方向前进。

    【讨论】:

    • 对不起,我忘了提。我想在我的 PySide UI 中显示图像,所以很遗憾我不能那样做。
    • 我将第二行更改为b = (255 &lt;&lt; 24 | a[:,:,0] &lt;&lt; 16 | a[:,:,1] &lt;&lt; 8 | a[:,:,2]),它起作用了。非常感谢!
    • 很好的解决方案!为了让它对我有用,我需要做一个小改动并使用 PySide.QtGui.QImage.Format_ARGB32。其余的都是一样的。
    • 关心解释b=... 行,我根本不明白...:为什么是255、24、16、8?我猜它与 2^8、2^4、2^3 有关,但 24 呢?还有一个解释会很好,谢谢!
    • 在这里发布了一个单独的问题并得到了很好的解释。不过谢谢! stackoverflow.com/questions/27872239/…
    【解决方案2】:

    如果您自己创建数据,例如使用 numpy,我认为最快的方法是直接访问 QImage。您可以从缓冲区对象 QImage.bits() 创建一个 ndarray,使用 numpy 方法做一些工作,并在完成后从 QImage 创建一个 QPixmap。您也可以通过这种方式读取或修改现有的 QImage。

    import numpy as np
    from PySide.QtGui import QImage
    
    img = QImage(30, 30, QImage.Format_RGB32)
    imgarr = np.ndarray(shape=(30,30), dtype=np.uint32, buffer=img.bits())
    
    # qt write, numpy read
    img.setPixel(0, 0, 5)
    print "%x" % imgarr[0,0]
    
    # numpy write, qt read
    imgarr[0,1] = 0xff000006
    print "%x" % img.pixel(1,0)
    

    确保数组不会比图像对象更长寿。如果需要,您可以使用更复杂的 dtype,例如用于单独访问 alpha、red、green 和 blue 位的记录数组(但要注意字节序)。

    如果没有使用 numpy 计算像素值的有效方法,您还可以使用 scipy.weave 内联一些对 img.bits() 指向的数组进行操作的 C/C++ 代码。

    如果您已经有一个 ARGB 格式的图像,那么按照之前的建议从数据创建 QImage 可能会更容易。

    【讨论】:

      【解决方案3】:

      除了@user545424 关于使用 PIL 的回答,如果你不想依赖 PIL,你可以直接从你的 np 数组手动构造你的 Image:

      width = 100
      height = 100
      data = np.random.randint(0,256,size=(width,height,3)).astype(np.uint8)
      
      img = QtGui.QImage(width, height, QtGui.QImage.Format_RGB32)
      for x in xrange(width):
          for y in xrange(height):
              img.setPixel(x, y, QtGui.QColor(*data[x][y]).rgb())
      
      pix = QtGui.QPixmap.fromImage(img)
      

      我敢肯定,使用 PIL,有一种方法可以将实际图像数据读入 QImage,但我会让 @user545424 解决该部分,因为它来自他的回答。 PIL自带ImageQt模块,方便直接转换Image -> QPixmap,可惜那是PyQt4 QPixmap,帮不上忙。

      【讨论】:

      • 谢谢,这行得通。但它需要大约 3 秒,这对我的应用程序来说太慢了。
      • @AntonS 也可以将ImageQtPySide 一起使用。您可以在import ImageQt 之前写sys.modules['PyQt4'] = PySide。示例代码:pastebin.com/DX2pbdpV。但我不知道什么更快。
      • 非常感谢!这行得通,但是 user545425s 代码要快一点,并且不依赖于 PIL
      • @AntonS:user545424 的回答确实取决于 PIL。你的意思是我的不需要 PIL?
      • 我的意思是第二部分,其中 rgb 值被移位,然后给 QImage()
      【解决方案4】:

      如果 user545424 的答案没有按预期工作:您在图像中看到伪影,那么我建议您将参数更改为

      PySide.QtGui.QImage.Format_ARGB32

      a = np.random.randint(0,256,size=(100,100,3)).astype(np.uint32)
      b = (255 << 24 | a[:,:,0] << 16 | a[:,:,1] << 8 | a[:,:,2]).flatten() # pack RGB values
      im = PySide.QtGui.QImage(b, 100, 100, PySide.QtGui.QImage.Format_ARGB32)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-12-14
        • 1970-01-01
        • 2016-03-17
        • 1970-01-01
        • 1970-01-01
        • 2013-05-01
        • 1970-01-01
        相关资源
        最近更新 更多