[Из песочницы] PIL на Python от простого к сложному
Чтобы дойти до сложных алгоритмов обработки, стоит проанализировать стандартные схемы, с чего я и предлагаю начать.
Для примеров обработки будет использоваться изображение с различным наборов цветов:
Для старта нам потребуется два модуля библиотеки:
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") #не забываем сохранить изображение
Инверсия
Инверсия получается путём вычета из 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))
Инверсия оттенка серого
Совмещая два предыдущих алгоритма можно написать следующий код:
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))
Выборочная инверсия оттенка серого
Для этого алгоритма нужно определить пороговое значение, которое я возьму за 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))
Заключение
В следующих статьях я хотел бы рассказать о том, как более локально подходить к фильтрации изображения, путём разделения его на области, а также показать интересные возможности DFS в алгоритмах обработки изображения