Reputation: 6080
I am currently switching from PyQt to PySide.
With PyQt I converted QImage
to a Numpy.Array
using this code that I found on SO:
def convertQImageToMat(incomingImage):
''' Converts a QImage into an opencv MAT format '''
incomingImage = incomingImage.convertToFormat(4)
width = incomingImage.width()
height = incomingImage.height()
ptr = incomingImage.bits()
ptr.setsize(incomingImage.byteCount())
arr = np.array(ptr).reshape(height, width, 4) # Copies the data
return arr
However ptr.setsize(incomingImage.byteCount())
does not work with PySide as this is part of the void*
support of PyQt.
My Question is: How can I convert a QImage to a Numpy.Array
using PySide.
EDIT:
Version Info
> Windows 7 (64Bit)
> Python 2.7
> PySide Version 1.2.1
> Qt Version 4.8.5
Upvotes: 12
Views: 12578
Reputation: 7065
I have to admit, all of the previous answers fail horribly when dealing with images that don't necessarily have an alpha, much less an even amount of channels (say a compressed grayscale that only stores the single channel). I just had to invent this workaround for myself, and this code works (I'm pretty sure for any image).
def QImageToCvMat(incomingImage):
''' Converts a QImage into an opencv/numpy MAT format '''
ba = QByteArray()
buff = QBuffer(ba)
# Essentially open up a "RAM" file
buff.open(QIODevice.ReadWrite)
# Store a PNG formatted file into the "RAM" File
incomingImage.save(buff, "PNG")
# Convert the now PNG contents into a numpy array of bytes
fBytes = np.asarray(bytearray(ba.data())), dtype=np.uint8)
# Let OpenCV "decode" the bytes in RAM as a PNG
return cv2.imdecode(fBytes, cv.IMREAD_COLOR)
Upvotes: 2
Reputation: 2771
For me the solution with constBits()
did not work, but the following worked:
def QImageToCvMat(incomingImage):
''' Converts a QImage into an opencv MAT format '''
incomingImage = incomingImage.convertToFormat(QtGui.QImage.Format.Format_RGBA8888)
width = incomingImage.width()
height = incomingImage.height()
ptr = incomingImage.bits()
ptr.setsize(height * width * 4)
arr = np.frombuffer(ptr, np.uint8).reshape((height, width, 4))
return arr
Upvotes: 7
Reputation: 6080
The trick is to use QImage.constBits()
as suggested by @Henry Gomersall. The code I use now is:
def QImageToCvMat(self,incomingImage):
''' Converts a QImage into an opencv MAT format '''
incomingImage = incomingImage.convertToFormat(QtGui.QImage.Format.Format_RGB32)
width = incomingImage.width()
height = incomingImage.height()
ptr = incomingImage.constBits()
arr = np.array(ptr).reshape(height, width, 4) # Copies the data
return arr
Upvotes: 3
Reputation: 8692
PySide doesn't seem to offer a bits
method. How about using constBits to get the pointer to the array?
Upvotes: 3