最近在做手寫體識別,需要將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)
將圖像數據轉換成字符串。
參數是圖像中字節數,字節數等於圖像寬度 × 圖像高度 × 通道數,即
需要注意的是通道數,查看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. 灰度處理 & 壓縮
- 使用
Image.convert()
可以進行格式轉換,詳細用法見https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.convert - 使用
Image.thumbnail()
進行壓縮,注意該方法只能進行壓縮,不能放大,而且是等比例壓縮。如果需要放大可以使用Image.resize()
方法。