Python枕头从像素制作GIF

时间:2020-02-27 07:00:18

标签: python python-imaging-library gif

enter image description here

我有图像和蓝色像素列表。我想遍历蓝色像素,将它们更改为红色,并由此生成gif。因此,它一定是一条线,因此颜色从蓝色变为红色,但是出了点问题

im = Image.open(r"test2.png")
pixels = im.load()
images = []
blues = get_sorted_blues()  # See func below

for x, y in blues:
     ...:     pixels[x, y] = (255, 0, 0)
     ...:     images.append(im)

images[0].save('result.gif',
     ...:                save_all=True,
     ...:                append_images=images[1:],
     ...:                duration=100,
     ...:                loop=0)

def get_sorted_blues():
    ...:     blues = []
    ...:     for x in range(im.width):
    ...:         for y in range(im.height):
    ...:             if pixels[x, y] == (0, 0, 255):
    ...:                 blues.append([x, y])
    ...:     return sorted(blues)

result.gif它只是一条红线,没有任何动画

2 个答案:

答案 0 :(得分:1)

有很多方法可以使蓝色像素变成红色-并且在性能,可读性,可维护性方面,使用for循环在列表的后面。


这里是使用“颜色矩阵” 交换红色和蓝色通道的一个:

from PIL import Image

# Open image
im = Image.open('lines.png')

# Define color matrix to swap the red and blue channels
# This says:
# New red   = 0*old red + 0*old green + 1*old blue + 0offset
# New green = 0*old red + 1*old green + 0*old blue + 0offset
# New blue  = 1*old red + 0*old green + 0*old blue + 0offset
Matrix = ( 0, 0, 1, 0, 
           0, 1, 0, 0, 
           1, 0, 0, 0)    

# Apply matrix
result = im.convert("RGB", Matrix)

enter image description here

这比for循环快40倍。在我的机器上,这需要1.07毫秒,而使用for循环则需要40毫秒。


这里是一个使用Numpy查找蓝色像素并使它们变为红色的像素:

import numpy as np
from PIL import image

# Open image and make Numpy version
im = Image.open('lines.png')
na = np.array(im)

# Make all blue pixels red
na[ np.all(na[:,:]==[0,0,255], axis=2) ] = [255,0,0] 

# Convert back to PIL Image
result = Image.fromarray(na)

这大约是5毫秒,快了8倍。


这里是使用Numpy将RGB顺序反转为BGR的一种:

import numpy as np
from PIL import image

# Open image and make Numpy version
im = Image.open('lines.png')
na = np.array(im)

# Reverse channel ordering i.e. RGB -> BGR
BGR = na[...,::-1] 

# Convert back to PIL Image
result = Image.fromarray(BGR)

这大约是4.4毫秒,快9倍。


在这里,我们使用PIL将图像分成其组成的RGB通道,然后以相反的顺序合并回去:

from PIL import Image

# Open image
im = Image.open('lines.png')

# Split into R, G, B channels
R, G, B = im.split()

# Recombine in B, G, R order
result = Image.merge('RGB',(B,G,R))

这是371微秒的速度的将近100倍。

答案 1 :(得分:1)

所以问题是您没有使其动画化吗?

在循环中,您不断更新相同的Image并将相同的Image放入列表,这意味着最后,列表中的所有条目都指向相同的{{1} },全为红色。在for循环中,执行Image而不是images.append(im)