PNG转Numpy数组改通道值存图像报AttributeError、ValueError如何解决
问题修复方案
核心报错原因
你遇到的两个报错均由代码逻辑错误、维度处理错误导致:
AttributeError: 'tuple' object has no attribute 'astype':newPNG函数接收的入参是单通道数组,np.dstack处理后维度错误返回非法结构,调用astype失败ValueError: buffer is not large enough:传入Image.fromarray的数组维度和RGBA要求的「高×宽×4」不匹配,内存缓冲区大小不符合要求
代码存在的其他问题
- 缺少PIL库的Image导入声明
arrUpdate函数索引错误:将横坐标Dx误写为Dy,导致数组篡改、索引越界arrUpdate函数提前return:仅处理第一行像素就直接返回结果- 宽高获取逻辑完全颠倒:错误把通道数当成高度传入处理函数
- 步长逻辑错误:生成的步长为小于1的浮点数,无法对uint8类型的像素值产生修改效果,且像素调整方向和需求相反
- 单通道处理结果被覆盖:没有合并r、g、b、a四个通道就传入保存函数
- 输出文件名重复:所有生成的图片使用同一文件名,会被覆盖
- 0值处理逻辑错误:遇到0值直接终止当前行处理,而非跳过单个像素
修正后完整代码
import numpy as np import easygui import os from PIL import Image def arrUpdate(width, height, inc, arrPass): # 遍历所有像素 for dy in range(height): for dx in range(width): # 跳过0值像素 if arrPass[dy][dx] == 0: continue # 大于128下调,小于等于128上调 if int(arrPass[dy][dx]) > 128: arrPass[dy][dx] = np.clip(arrPass[dy][dx] - inc, 0, 255) else: arrPass[dy][dx] = np.clip(arrPass[dy][dx] + inc, 0, 255) return arrPass def newPNG(version, r_channel, g_channel, b_channel, a_channel, save_path, base_name): # 合并四个通道,维度为 高×宽×4 final_render = np.dstack([r_channel, g_channel, b_channel, a_channel]) new_img = Image.fromarray(final_render.astype('uint8'), 'RGBA') # 文件名增加版本号避免覆盖 final_path = os.path.join(save_path, f"{base_name}_v{version + 1}.png") new_img.save(final_path) print(f"Image {version + 1} Rendered") if __name__ == "__main__": fields = ["Original File Name:", "Number of versions: \n(1 - 10)"] field_return = easygui.multenterbox('Information Required', 'Auto Hue Shift', fields) if not field_return or len(field_return) < 2: print("Input cancelled\nExiting...") exit() file_name = field_return[0] file_name_str = str(file_name).strip() if '.png' in file_name_str.lower(): base_name = file_name_str.rsplit(".png", 1)[0] else: base_name = file_name_str file_name_str = f"{file_name_str}.png" try: itt = int(field_return[1]) except ValueError: print("Invalid number of versions\nExiting...") exit() cwd = os.getcwd() new_path = os.path.join(cwd, base_name) if not os.path.isdir(new_path): os.mkdir(new_path, 0o777) else: print('Directory already exists') # 读取图像拆分为四个通道 img = Image.open(file_name_str).convert('RGBA') arr = np.array(img).astype('uint8') r, g, b, a = arr[..., 0], arr[..., 1], arr[..., 2], arr[..., 3] # 计算步长,最小步长24 inc = max(24, int(255 / itt)) # 获取正确的宽高 height, width = arr.shape[:2] # 循环生成对应数量的图片 for version in range(itt): r = arrUpdate(width, height, inc, r) g = arrUpdate(width, height, inc, g) b = arrUpdate(width, height, inc, b) newPNG(version, r, g, b, a, new_path, base_name)
使用说明
- 运行前需要安装依赖:执行
pip install numpy easygui pillow安装所需库 - 输入的版本数建议在1-10之间,步长会自动按最小24的规则计算
- 生成的图片会保存在当前工作目录下和输入图片同名的文件夹中,自带版本号后缀不会覆盖
内容的提问来源于stack exchange,提问作者Jason Piedrasanta
相关产品推荐
相关产品推荐

