Python Подушка сделать GIF из пикселей - PullRequest
2 голосов
/ 27 февраля 2020

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 ]

1 голос
/ 28 февраля 2020

Итак, проблема в том, что вы не смогли сделать его анимированным?

В вашем l oop вы продолжаете обновлять тот же самый Image и помещаете тот же самый Image в список, что означает, что в конце все записи в списке указывают на один и тот же Image который весь красный. В for l oop вместо images.append(im) сделайте images.append(im.copy()).

1 голос
/ 27 февраля 2020

Есть много способов сделать синие пиксели красными - и использование for l oop далеко внизу списка с точки зрения производительности, удобочитаемости и удобства обслуживания.


Вот пример использования «Цветовой матрицы» для переключения красного и синего каналов:

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

Это примерно в 40 раз быстрее, чем for. На моем аппарате требуется 1,07 мс против 40 мс с использованием циклов for.


Вот пример использования 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)

Это примерно в 8 раз быстрее при 5 мс.


Вот один из них, использующий 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)

Это примерно в 9 раз быстрее при 4,4 мс.


Здесь мы используем 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))

Это примерно в 100 раз быстрее при 371 микросекунде.

...