首页 > 解决方案 > 使用 PIL.putdata() 和 For 循环将修改后的图像附加到新列表的问题

问题描述

我有一个图像,我想制作 5 个副本。

import PIL
from PIL import Image

image=Image.open("image.gif")
image=image.convert('RGB')
images=[]
for i in range(1, 6):
    images.append(image)

在对 RGB 波段中每种颜色的强度进行一些更改后,我想将此数据加载到这 5 张图片上(“RGB_band”列表中的每个项目都是一个包含不同像素修改的元组,每个元组彼此都是唯一的)。

RGB_band= [modification_1,modification_2,modification_3, modification_4, modification_5]

new_images=[] #loop to load new pixel information onto the pictures and append to a new list.
for i in range(len(images)):
    images[i].putdata(RGB_band[i])
    new_images.append(images[i])

我期望“new_images”列表中的每个图像都具有不同的颜色强度(即第一张图像应该显示来自 modify_1 的像素数据,第二张图像显示来自 modify_2 的像素数据等),但是“new_images”列表中的所有 5 张图像都是列表“图像”中的原始图像(未修改)。但是,在“For”循环期间,如果我这样:

for i in range(len(images)):
    images[i].putdata(RGB_band[i])
    new_images.append(images[i])
    new_images[i].show()

然后在每次迭代期间显示的图像具有正确的颜色(即以 5 种不同颜色显示的 5 张图像)

谁能告诉我问题是什么?我在“For”循环中尝试了不同的东西,但“new_images”列表中的图像仍然相同。

标签: for-loopimage-processingpython-imaging-library

解决方案


我不知道您要做什么,但我认为您没有意识到 Python 对象需要被复制才能成为具有自己分配内存的唯一对象。

比较一下,列表中的每个图像都与其他项目共享内存:

image=Image.open("image.png").convert('RGB') 
images=[]
for i in range(1, 6):
    images.append(image) 

如果您现在查看列表 - 特别是右侧的地址,您可以看到它们都是一样的:

print(images)

[<PIL.Image.Image image mode=RGB size=1000x300 at 0x1084C3C10>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x1084C3C10>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x1084C3C10>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x1084C3C10>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x1084C3C10>]

如果我们检查它们是否共享内存:

print(images[0] is images[4])
True

现在,当我复制每个图像时看看这个,它是一个具有自己数据的唯一副本:

Uimages=[]
for i in range(1, 6):
    Uimages.append(image.copy()) 

现在查看列表,发现地址不同:

print(Images)
[<PIL.Image.Image image mode=RGB size=1000x300 at 0x108797790>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x108797F50>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x1087973D0>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x108797510>,
 <PIL.Image.Image image mode=RGB size=1000x300 at 0x1084DB450>]

并检查它们是否是同一个对象:

print(Uimages[0] is Uimages[4])
False

一般来说,如果您开始将图像视为像素列表,您可能已经出错了。它效率低下且缓慢。考虑使用 Numpy 或 OpenCV 并使用矢量化代码。


推荐阅读