将PIL Image转为numpy数组后图像错位失真,求问题排查与解决
问题分析与解决
问题出在图像维度顺序搞反了
PIL的Image.size返回的是**(宽度, 高度),但numpy存储图像的标准格式是(高度, 宽度, 通道数)**。你在reshape的时候写成了(pic.size[0], pic.size[1], 3),相当于把宽度当成了数组的行(高度方向),高度当成了数组的列(宽度方向),整个图像的行列完全颠倒。后续遍历像素时,i和j对应到了错误的位置,导致像素错位,最终出现对角线伪影。
两种修正方法
方法1:修正reshape的维度顺序
把reshape的参数改成(pic.size[1], pic.size[0], 3),让numpy数组的维度符合(高度, 宽度, 通道)的常规格式:
pic = Image.open("red.jpg") # 修正维度顺序:高度在前,宽度在后 img = np.array(pic.getdata()).reshape(pic.size[1], pic.size[0], 3) grayscale = avgcolors(img) plt.imshow(grayscale, cmap='gray') plt.show()
你的avgcolors函数逻辑本身没问题,只要输入矩阵维度正确,就能得到预期的灰色效果。
方法2:用numpy向量化操作替代循环(更高效)
嵌套循环处理像素效率极低,numpy支持直接对通道维度求均值,一行代码就能完成转换,还能避免循环可能带来的错误:
def avgcolors(img_matrix): # 对第三个维度(RGB通道)求均值,四舍五入后转整数 return np.round(np.mean(img_matrix, axis=2)).astype(int)
调用时同样要先修正reshape的维度,这种方式处理大图像的速度会快很多。
内容的提问来源于stack exchange,提问作者D. Brito
相关产品推荐
相关产品推荐

