Python: PIL заменяет один цвет RGBA

Я уже рассмотрел этот вопрос: вопрос SO и, похоже, реализовал очень похожую технику для замены одного цвета, включая альфа-значения:

c = Image.open(f)
c = c.convert("RGBA")
w, h = c.size
cnt = 0
for px in c.getdata():
    c.putpixel((int(cnt % w), int(cnt / w)), (255, 0, 0, px[3]))                                                                                                      cnt += 1

Однако это очень медленно. Я нашел этот рецепт на interwebs, но до сих пор не использовал его: рецепт

Я пытаюсь сделать несколько изображений PNG, состоящих из одного цвета, белого. Каждый пиксель на 100% белый с различными альфа-значениями, включая альфа = 0. То, что я хочу сделать, - это в основном раскрасить изображение с новым цветом набора, например, # ff0000 < 00-ff > . Итак, мои стартовые и результирующие изображения будут выглядеть так, как если бы левая сторона была моим начальным изображением, а справа - мое конечное изображение (ПРИМЕЧАНИЕ: фон был изменен на светло-серый, чтобы вы могли видеть его, поскольку он на самом деле прозрачен, t видеть левые точки.)

alt text

Какой лучший способ сделать это?

Ответ 1

Если у вас есть numpy, он обеспечивает гораздо более быстрый способ работы с изображениями PIL.

например:.

import Image
import numpy as np

im = Image.open('test.png')
im = im.convert('RGBA')

data = np.array(im)   # "data" is a height x width x 4 numpy array
red, green, blue, alpha = data.T # Temporarily unpack the bands for readability

# Replace white with red... (leaves alpha values alone...)
white_areas = (red == 255) & (blue == 255) & (green == 255)
data[..., :-1][white_areas.T] = (255, 0, 0) # Transpose back needed

im2 = Image.fromarray(data)
im2.show()

Изменить: это медленный понедельник, поэтому я решил добавить несколько примеров:

Чтобы показать, что он оставляет только альфа-значения, здесь приведены результаты для версии вашего примера изображения с радиальным градиентом, применяемым к альфа-каналу:

Оригинал: alt text

Результат: alt text

Ответ 2

Глава онлайн-книги Pythonware PIL для Модуль изображения предусматривает, что putpixel() работает медленно и предполагает, что его можно ускорить путем вложения, Или в зависимости от версии PIL, вместо этого используйте load().

Ответ 3

Попробуйте это, в этом примере мы устанавливаем цвет в черный цвет, если цвет не белый.

#!/usr/bin/python
from PIL import Image
import sys

img = Image.open(sys.argv[1])
img = img.convert("RGBA")

pixdata = img.load()

# Clean the background noise, if color != white, then set to black.

for y in xrange(img.size[1]):
    for x in xrange(img.size[0]):
        if pixdata[x, y] == (255, 255, 255, 255):
            pixdata[x, y] = (0, 0, 0, 255)

вы можете использовать функцию выбора цвета в gimp для поглощения цвета и увидеть, что цвет rgba