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

目录

  1. 前言
  2. 详细过程
    1. 1. 将QImage转换为字符串
    2. 2. 将字符串转换为Numpy array
    3. 3. 灰度处理 & 压缩

前言

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

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

详细过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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) 将图像数据转换成字符串。

参数是图像中字节数,字节数等于图像宽度 × 图像高度 × 通道数,即

需要注意的是通道数,查看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. 灰度处理 & 压缩