Как рисовать в питоне pil
На этом шаге мы рассмотрим основные методы, используемые для рисования фигур .
Чтобы на изображении можно было рисовать, необходимо создать экземпляр класса Draw , передав в конструктор класса ссылку на изображение. Прежде чем использовать класс, предварительно следует импортировать модуль ImageDraw . Пример создания экземпляра класса:
>>> from PIL import Image, ImageDraw >>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) # Создаем экземпляр класса
point (< Координаты >, fill=< Цвет >) — рисует точку. Нарисуем красную горизонтальную линию из нескольких точек:
>>> from PIL import Image, ImageDraw >>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) >>> for n in range(5, 31): draw.point( (n, 5), fill=(255, 0, 0) ) >>> img.show()
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) >>> draw.line ( (0, 0, 0, 300), fill=(0, 128, 0) ) >>> draw.line ( (297, 0, 297, 300), fill=(0, 128, 0), width=3 ) >>> img.show ()
rectangle(Координаты>[, fill=Цвет заливки>] [, outline=])
В параметре < Координаты >указываются координаты двух точек: левого верхнего и правого нижнего углов рисуемого прямоугольника. Нарисуем три прямоугольника: первый — с рамкой и заливкой, второй — только с заливкой, а третий — только с рамкой:
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) # Создаем экземпляр класса >>> draw.rectangle ( (10, 10, 30, 30), fill=(0, 0, 255), outline=(0, 0, 0) ) >>> draw.rectangle ( (40, 10, 60, 30), fill=(0, 0, 128)) >>> draw.rectangle ( (0, 0, 299, 299), outline=(0, 0, 0)) >>> img.show ()
polygon(Координаты>[, fill=Цвет заливки>][, outline=Цвет линии>] )
В параметре < Координаты >указывается кортеж с координатами трех и более точек: из каждой пары элементов этого списка первая задает горизонтальную координату, вторая — вертикальную. Точки соединяются линиями. Кроме того, проводится прямая линия между первой и последней точками. Пример:
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) # Создаем экземпляр класса >>> draw.polygon( (50, 50, 150, 150, 50, 150), outline=(0,0,0), fill=(255, 0, 0)) # Треугольник >>> draw.polygon ( (200, 200, 250, 200, 275, 250, 250, 300, 200, 300, 175, 250), fill=(255, 255, 0)) >>> img.show ()
ellipse(Координаты> [, fill=Цвет заливки>][, outline=Цвет линии>])
В параметре < Координаты >указывается кортеж с координатами верхнего левого и правого нижнего углов прямоугольника, в который необходимо вписать эллипс. Из каждой пары элементов этого кортежа первый задает горизонтальную координату, второй — вертикальную. Пример:
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) # Создаем экземпляр класса >>> draw.ellipse ( (100, 100, 200, 200), fill=(255, 255, 0)) >>> draw.ellipse ( (50, 170, 150, 300), outline=(0, 255, 255)) >>> img.show ()
arc (Координаты>, Начальный угол>, Конечный угол>, fill=Цвет линии>)
В параметре < Координаты >указываются координаты прямоугольника, в который необходимо вписать окружность. Второй и третий параметры задают начальный и конечный угол, между которыми будет отображена дуга. Угол, равный 0, расположен в крайней правой точке. Углы откладываются по часовой стрелке от 0 до 360 градусов. Линия рисуется по часовой стрелке. Пример:
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) >>> draw.arc ( (10, 10, 290, 290), 180, 0, fill=(255, 0, 0) ) >>> img.show ()
chord (Координаты>, Начальный угол>, Конечный угол>, [, fill=Цвет заливки>][, outline=Цвет линии>])
Метод chord () аналогичен методу arc () , но замыкает крайние точки дуги прямой линией. Пример:
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) >>> draw.chord ( (10, 10, 290, 290), 180, 0, fill=(255, 0, 0) ) >>> draw.chord ( (10, 10, 290, 290), -90, 0, fill=(255, 255, 0)) >>> img.show ()
pieslice (Координаты>, Начальный угол>, Конечный угол>, [, fill=Цвет заливки>][, outline=Цвет линии>])
Метод pieslice () аналогичен методу arc () , но замыкает крайние точки дуги с центром окружности. Пример:
>>> img = Image.new ("RGB", (300, 300), (255, 255, 255)) >>> draw = ImageDraw.Draw(img) >>> draw.pieslice ( (10, 10, 290, 290), -90, 0, fill="red") >>> img.show ()
Со следующего шага мы начнем знакомиться с библиотекой Wand .
Блог gigimon’а
Недавно потребовалось мне создавать картинку на лету. Решил спользовать библиотеку для питона PIL . Она поддерживает кучу форматов, а также множество цветовых систем ( RGB , RGBA и более простые). Итак, рассмотрим простейшее, как создать рисунок и что-либо на нем нарисовать.
Для начала, подключим нужные модули.
from PIL import Image, ImageDraw
Модуль Image управляет непосредственно источником изображения, позволяет создавать, сохранять, октрывать рисунок. А ImageDraw, отвечает непосредственно за рисование геометрических объектов.
Теперь создадим новый рисунок:
image = Image.new("RGBA", (320,320), (0,0,0,0))
Здесь, первый параметр это тип картинки, может быть: 1 (черно-белый), L (монохромный, оттенки серого), RGB , RGBA ( RGB с альфа каналом), CMYK , YCbCr, I (32 bit Integer pixels), F (32 bit Float pixels).
Второй параметр, это объект типа tuple задающий размер изображения.
Третий параметр, это непосредственно цвет, т.к. у нас RGBA , то запись (0,0,0,0) соответствует полной прозрачности.
После этого, чтобы нарисовать на нем что-либо, требуется создать объект ImageDraw и передать ему наш рисунок:
draw = ImageDraw.Draw(image)
Попробуем нарисовать красный эллипс:
draw. ellipse((10,10,300,300), fill="red", outline="red")
Здесь мы рсиуем эллипс, с координатами начальными: 10,10, и конечными: 300,300. Также, параметр fill задает цвет заливки, а outline — цвет контура. Помимо кодовых названий, можно использовать HTML запись, либо RGB (A) в виде tuple элемента.
Из доступных для рисования фигур доступны: кривая, линия, текст, вырезаный эллипс, точка, полигон.
После этого удалим draw и сохраним рисунок:
del draw image.save("/path/to/save/test.png", "PNG")
После этого мы получи .png файл, в котором будет красный круг на прозрачном фоне :

Вот, думаю для начального понимания поможет кому-нибудь.
Нашел краткую документацию по официальной документации.
Официальный сайт с документацией
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 в алгоритмах обработки изображения
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() # Выгружаем значения пикселей
Приступим
Обрабатывать изображения будем в формате RGB. Также PIL поддерживает работу с форматами 1, L, P, RGB, RGBA, CMYK, YCbCr, LAB, HSV, I, F.
Значения пикселя в изображении задаются в формате: (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 в алгоритмах обработки изображения
- Python
- Обработка изображений