将QImage转换为numpy array

最近在做手写体识别,需要将QT中手写的数字转换成像训练集一样图片。因此需要将QImage转换为numpy array。

前言

笔者使用的是PyQt,但是对QT和Python之间数据之间的转换不太熟悉。查了很长时间,也没有找到详细的说明,最后在stackoverflow中查到了转换方法,但是说的也不清楚。

终于,经过查阅QT的参考手册终于明白了转换过程。

详细过程

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

image = self.canvas_label.canvas.toImage()
size = image.size()
s = image.bits().asstring(size.width() * size.height() * image.depth() // 8)  # format 0xffRRGGBB

arr = np.fromstring(s, dtype=np.uint8).reshape((size.height(), size.width(), image.depth() // 8))

new_image = Image.fromarray(array)

# convert to gray
new_image.convert("L")
new_image.thumbnail((28, 28))
plt.imshow(new_image, cmap='gray')
plt.show()

1. 将QImage转换为字符串

笔者的原图是通过QPixmap绘制的一幅RGB图。之后将其转换为QImage。

通过s = image.bits().asstring(size.width() * size.height() * image.depth() // 8)将图像数据转换成字符串。

参数是图像中字节数,字节数等于图像宽度 × 图像高度 × 通道数,即 b y t e s = w i d t h ∗ h e i g h t ∗ c h a n n e l s bytes = width * height * channels bytes=widthheightchannels

需要注意的是通道数,查看QT的手册知道QT的RGB图像的格式是0xFFRRGGBB,其实就是将Alpha通道全部置为了0xFF。

之前以为只有3个通道,所以一直有问题。QImage.depth()可以返回图像深度的比特数,对于RGB图QImage.depth()返回值为32,所以整除8之后就是通道数。

2. 将字符串转换为Numpy array

之后使用np.fromstring()即可通过字符串构造numpy array。

到这里QImage转换为numpy array的任务就完成了。之后需要将原图进行灰度处理和压缩。

3. 灰度处理 & 压缩

  1. 使用Image.convert()可以进行格式转换,详细用法见https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.convert
  2. 使用Image.thumbnail()进行压缩,注意该方法只能进行压缩,不能放大,而且是等比例压缩。如果需要放大可以使用Image.resize()方法。

你可能感兴趣的:(Code)