[Из песочницы] PIL на Python от простого к сложному

Чтобы дойти до сложных алгоритмов обработки, стоит проанализировать стандартные схемы, с чего я и предлагаю начать.

Для примеров обработки будет использоваться изображение с различным наборов цветов:

image

Для старта нам потребуется два модуля библиотеки:

from PIL import Image, ImageDraw 


Настроим инструменты для комфортной дальнейшей работы:

image = Image.open('test.jpg')  # Открываем изображение
draw = ImageDraw.Draw(image)  # Создаем инструмент для рисования
width = image.size[0]  # Определяем ширину
height = image.size[1]  # Определяем высоту
pix = image.load()  # Выгружаем значения пикселей


Приступим


PIL работает с изображениями в формате RGB.
Значения пикселя в изображении задаются в формате: (x, y),(red, green, blue), где x, y — координаты, а числовые значения RGB находятся в диапазоне от 0 до 255. То есть работаем с 8-битным изображением.

Оттенок серого


Серый оттенок появляется в случае равенства всех палитр цветов, поэтому нам нужно получить среднее арифметическое значение во всех трёх пунктах:


for x in range(width):
    for y in range(height):
       r = pix[x, y][0] #узнаём значение красного цвета пикселя
       g = pix[x, y][1] #зелёного
       b = pix[x, y][2] #синего
       sr = (r + g + b) // 3 #среднее значение
       draw.point((x, y), (sr, sr, sr)) #рисуем пиксель

image.save("result.jpg", "JPEG") #не забываем сохранить изображение


image

Инверсия


Инверсия получается путём вычета из 255 текущего цвета:


for x in range(width):
   for y in range(height):
      r = pix[x, y][0]
      g = pix[x, y][1]
      b = pix[x, y][2]
      draw.point((x, y), (255 - r, 255 - g, 255 - b))


image

Инверсия оттенка серого


Совмещая два предыдущих алгоритма можно написать следующий код:


for x in range(width):
    for y in range(height):
        r = pix[x, y][0]
        g = pix[x, y][1]
        b = pix[x, y][2]
        sr = (r + g + b) // 3
        draw.point((x, y), (255 - sr, 255 - sr, 255 - sr))


image

Выборочная инверсия оттенка серого


Для этого алгоритма нужно определить пороговое значение, которое я возьму за 100:

for x in range(width):
    for y in range(height):
        r = pix[x, y][0]
        g = pix[x, y][1]
        b = pix[x, y][2]
        if (r+g+b)>100: #если сумма значений больше 100 , то используем инверисю
            sr = (r + g + b) // 3
            draw.point((x, y), (255-sr, 255-sr, 255-sr))
        else: #иначе обычный оттенок серого
            sr = (r + g + b) // 3
            draw.point((x, y), (sr, sr, sr))


image

Заключение


В следующих статьях я хотел бы рассказать о том, как более локально подходить к фильтрации изображения, путём разделения его на области, а также показать интересные возможности DFS в алгоритмах обработки изображения

© Habrahabr.ru