PIL Проверяет пиксель, включен ли он с помощью функции eval

#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')