网上很多从numpy(opencv在python中加载了图像,就是以numpy数组存储,相当于c++中的Mat)加载图像到QImage的方法,搜了好久都没有找到从QImage转存到numpy的方法。而我的一个应用需要用到这个功能,opencv无法在图像中写入汉子,所以我就通过Qimage进行了写入汉子处理,处理完成后需要转成numpy再通过opencv写入到video中。 弄了两天,好不容易发现了这篇,赶紧收藏并粘贴代码。原文https://blog.youkuaiyun.com/xjcvip007/article/details/53493290
代码如下:
def qimage2numpy(qimage, dtype='array'):
"""Convert QImage to numpy.ndarray. The dtype defaults to uint8
for QImage.Format_Indexed8 or `bgra_dtype` (i.e. a record array)
for 32bit color images. You can pass a different dtype to use, or
'array' to get a 3D uint8 array for color images."""
result_shape = (qimage.height(), qimage.width())
temp_shape = (qimage.height(),
qimage.bytesPerLine() * 8 / qimage.depth())
if qimage.format() in (QtGui.QImage.Format_ARGB32_Premultiplied,
QtGui.QImage.Format_ARGB32,
QtGui.QImage.Format_RGB32):
if dtype == 'rec':
dtype = QtGui.bgra_dtype
elif dtype == 'array':
dtype = np.uint8
result_shape += (4,)
temp_shape += (4,)
elif qimage.format() == QtGui.QImage.Format_Indexed8:
dtype = np.uint8
else:
raise ValueError("qimage2numpy only supports 32bit and 8bit images")
# FIXME: raise error if alignment does not match
buf = qimage.bits().asstring(qimage.numBytes())
result = np.frombuffer(buf, dtype).reshape(temp_shape)
if result_shape != temp_shape:
result = result[:, :result_shape[1]]
if qimage.format() == QtGui.QImage.Format_RGB32 and dtype == np.uint8:
result = result[..., :3]
result = result[:,:,::-1]
return result
先开始对pyqt5 qimage.bits()返回类型sip.voidptr object类型一直不知道怎么处理,这个是个指针呀,在python中怎么处理指针呢?上面是采用变换成字符串的模式,sip.voidptr object类型还有asarray()、getsize()、setsize()函数,下面就是利用setsize()函数直接返回原图片的数据区。但要注意Qimage内部是按照每个像素4个字节的方式组织数据的,即使最后一个alpha通道没有用,也用0xff来填充。掌握原理后,其实可以采取更简单的方法处理
ptr = qimg.constBits() ptr.setsize(qimg.byteCount()) mat = np.array(ptr).reshape( qimg.height(), qimg.width(), 4) # 注意这地方通道数一定要填4,否则出错 return mat