#python #transparency #python-imaging-library #rgb #pixel
#python #прозрачность #python-imaging-library #rgb #пиксель
Вопрос:
Есть ли какой-либо способ использовать eval
функцию в PIL для обхода всех пикселей, проверяя, какое значение имеет каждый? Программа просматривает изображение, чтобы увидеть, соответствует ли каждый пиксель определенному цвету rgb, и если это так, то она преобразует этот пиксель в прозрачность. eval
функция в PIL, похоже, справится с этой задачей, но может ли моя функция, которая преобразует пиксели, проверить значение пикселя, на котором она включена? Заранее спасибо.
Ответ №1:
Обновлено: Ааа, я вижу, что ты хочешь сделать. Вот пример, использующий только PIL. Он преобразует все белые пиксели в красные с 50% альфа:
import Image
img = Image.open('stack.png').convert('RGBA')
width, _ = img.size
for i, px in enumerate(img.getdata()):
if px[:3] == (255, 255, 255):
y = i / width
x = i % width
img.putpixel((x, y), (255, 0, 0, 127))
img.save('stack-red.png')
Оригинальный ответ: Да, Image.eval()
функция позволяет вам передавать функцию, которая оценивает каждый пиксель, и позволяет вам определять новое значение пикселя:
import Image
img1 = Image.open('foo.png')
# replace dark pixels with black
img2 = Image.eval(img1, lambda px: 0 if px <= 64 else px)
Комментарии:
1. Новое значение пикселя? Хм, я не совсем понимаю эту функцию, извините… Что я могу извлечь из этого, так это то, что он проверяет, меньше ли пиксель 64, а затем, если да, преобразует его в ноль? Я прав? Если да, то как бы вы изменили значение пикселя с зеленого на зеленый? Как определяется «значение пикселя» для изображения?
2. Я добавил пример, который должен быть ближе к тому, что вы ищете.
3.Если возникает проблема с производительностью: не
putpixel
ли это намного медленнее, чем__setitem__
наimg.getdata()
объекте? Другими словами:d=img.getitem()
for i,px in enumerate(d):
...
d[i] = (255,0,0,127)
.4. Кроме того, похоже, что он не выполняет getitem, как сказал Пол. ошибка атрибута.
5. @samplebias Может быть, полезно упомянуть, что в Python 3.x
y = i / width
должно бытьy = i // width
.
Ответ №2:
Нет, eval
не будет передавать RGB-кортеж функции. Он отображает функцию по каждому диапазону. Однако вы могли бы обработать каждый бэнд с помощью eval
, а затем использовать ImageChops
операцию для логического объединения бэндов и получения маски, которая будет зависеть от пиксельного кортежа.
Кстати, это можно было бы сделать намного чище и эффективнее в NumPy, если вы так склонны..
import numpy as np
import Image
import ImageChops
im_and = ImageChops.lighter
im = Image.open('test.png')
a = np.array(im)
R,G,B,A = im.split()
color_matches = []
for level,band in zip((255,255,255), (R,G,B)):
b = Image.eval(band, lambda px: 255-(255*(px==level)))
color_matches.append(b)
r,g,b = color_matches
mask = im_and(r, im_and(g, b))
im.putalpha(mask)
im.save('test2.png')