Как рисовать в питоне pil
Перейти к содержимому

Как рисовать в питоне pil

  • автор:

Как рисовать в питоне 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 от простого к сложному

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

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

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 в алгоритмах обработки изображения

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() # Выгружаем значения пикселей

Приступим

Обрабатывать изображения будем в формате 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") #не забываем сохранить изображение 

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 в алгоритмах обработки изображения

  • Python
  • Обработка изображений

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *