Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert numpy array to PySide QPixmap

I want to convert an image into a NumPy array to a PySide QPixmap, so I can display it (EDIT: in my PySide UI). I already found this tool: qimage2ndarray, but it only works for PyQt4. I tried to change it to get it working with PySide, but I would have to change the C part of the tool and I have no experience with C. How can I do this or are there any alternatives?

like image 357
AntonS Avatar asked Mar 20 '12 20:03

AntonS


3 Answers

One alternative is to just use PIL library.

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

You can look at the QPixmap constructor at http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html.

It looks like you should be able to use a numpy array directly in the constructor:

class PySide.QtGui.QImage(data, width, height, format)

where the format argument is one of these: http://www.pyside.org/docs/pyside/PySide/QtGui/QImage.html#PySide.QtGui.PySide.QtGui.QImage.Format.

So, for example you could do something like:

>>> 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)

I don't have PySide installed so I haven't tested this. Chances are it won't work as is, but it might guide you in the right direction.

like image 115
user545424 Avatar answered Oct 13 '22 03:10

user545424


If you create the data yourself, using numpy for example, I think the fastest method is to directly access a QImage. You can create a ndarray from the buffer object QImage.bits(), do some work using the numpy methods and create a QPixmap from QImage when you are done. You can also read or modify existing QImages that way.

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)

Be sure that the array does not outlive the image object. If you want, you can use a more sophisticated dtype, like a record array for individual access to the alpha, red, green and blue bits (beware of endianess though).

In case there is no efficient way to calculate the pixel values using numpy, you can also use scipy.weave to inline some C/C++ code that operates on the array img.bits() points to.

If you already have an image in ARGB format, creating the QImage from data as suggested before is probably easier.

like image 45
pwuertz Avatar answered Oct 13 '22 03:10

pwuertz


In addition to @user545424 answer about using PIL, if you didn't want to depend on PIL, you could manually construct your Image directly from your np array:

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)

I'm sure, using PIL, there is a way to read the actual image data into a QImage, but I will let @user545424 address that part since its from his answer. PIL comes with the ImageQt module which is convenient for directly converting an Image -> QPixmap, but unfortunately thats a PyQt4 QPixmap, which doesn't help you.

like image 2
jdi Avatar answered Oct 13 '22 04:10

jdi