Numpy 将Pillow图片对象和Numpy数组进行相互转换时维度变化的问题
在使用Python中的Pillow图片库和Numpy时,可能会遇到将Pillow图片对象和Numpy数组进行相互转换时维度变化的问题。本文将介绍在这个过程中可能出现的问题和解决方法。
阅读更多:Numpy 教程
PIL.Image与Numpy数组之间的转换
PIL.Image对象和Numpy数组之间可以相互转换,但是在进行转换时需要注意维度的转换。PIL.Image对象一般是二维或三维,Numpy数组可以是一维、二维、三维或多维。将PIL.Image对象转换成Numpy数组一般采用以下方式:
from PIL import Image
import numpy as np
img = Image.open('test.jpg')
img_array = np.array(img)
将Numpy数组转换成PIL.Image对象一般采用以下方式:
from PIL import Image
import numpy as np
img_array = np.array([[1,2,3],[4,5,6],[7,8,9]])
img = Image.fromarray(img_array)
需要注意的是,当PIL.Image对象是三维数组时,表示的是RGB图像,而Numpy数组的三维数组表示的是BGR图像,在进行转换时需要进行颜色通道的变换。
img = img[:, :, ::-1]
图片维度的变化
在进行PIL.Image对象和Numpy数组的相互转换过程中,可能会出现维度变化的问题。例如,将某个图像文件转换成PIL.Image对象后,对其进行缩放或者旋转等处理,再将其转换成Numpy数组,此时Numpy数组的维度与原始Numpy数组的维度不一定相同。
img = Image.open('test.jpg')
img = img.rotate(45)
img_array = np.array(img)
print(img_array.shape) #(414, 414, 3)
原始图像的维度是(480, 480, 3)
,经过旋转处理后,Numpy数组的维度变成了(414, 414, 3)
,因为旋转图片会导致图片失去一部分像素,所以图片的大小也会发生变化。如果需要将Numpy数组重新转换成PIL.Image对象,需要先将其进行reshape操作,使其维度恢复原来的维度。
img_array = np.reshape(img_array, (480, 480, 3))
new_img = Image.fromarray(img_array.astype(np.uint8))
new_img.show()
解决方案
在进行PIL.Image对象和Numpy数组的转换过程中,为避免出现维度变化的问题,可以采用如下的方法进行操作:
- 转换时指定图片的读入模式,默认为“L”(灰度图像),如果读取彩色图像需要指定模式为“RGB”或者“RGBA”,例如:
img = Image.open('test.jpg').convert('RGB')
- 在对图片进行变换之前,先将其转换成Numpy数组,这样在进行变换之后再将其转换成PIL.Image对象,维度不会发生变化,例如:
img_array = np.array(img)
img_array = img_array[:, :, ::-1] #将BGR图像转换成RGB图像
img_array = cv2.resize(img_array, (500, 500)) #将图片缩放至500x500
img = Image.fromarray(np.uint8(img_array))
- 在将Numpy数组转换成PIL.Image对象之前,通过reshape方法将其维度恢复成最初的维度,例如:
img_array = np.reshape(img_array, (480, 480, 3))
new_img = Image.fromarray(img_array.astype(np.uint8))
总结
PIL.Image对象和Numpy数组在进行相互转换时,需要注意维度的变化问题。在对PIL.Image对象进行变换时,可能会导致Numpy数组的维度发生变化,为了避免这种问题的出现,我们可以在转换时设置图片的读入模式、在变换之前先将其转换成Numpy数组进行处理,或者在将Numpy数组转换成PIL.Image对象之前将其维度恢复成最初的维度。通过这些方法,我们可以确保在进行PIL.Image对象和Numpy数组的相互转换时,维度不会发生变化,从而避免出现不必要的问题。