Pillow — работа с картинками

Pillow — самая популярная библиотека для работы с изображениями в Python. С помощью неё картинки можно открывать, вращать, накладывать фильтры и даже работать с отдельными пикселями.

Обзор

Импортируется библиотека так:

from PIL import Image

Pillow — улучшенная версия библиотеки PIL, поэтому импортируется она таким странным образом. В коде она будет называться PIL.

Далее попробуем что-нибудь сделать с картинкой:

from PIL import Image

image = Image.open("example.jpg")
rotated_image = image.rotate(45)
rotated_image.save("rotated.jpg")

Сначала открываем картинку с названием example.jpg и кладём её в переменную image. На следущей строке поворачиваем картинку на 45 градусов. Метод .rotate() не меняет картинку, а создаёт новую, поэтому положим её в переменную rotated_image. И в конце сохраняем повёрнутую картинку в новый файл rotated.jpg.

Атрибуты картинок

В Pillow есть новые типы данных: JpegImageFile, PngImageFile… Они позволяют хранить картинки прямо в переменных Python. У картинок есть несколько атрибутов, которые понадобятся вам в будущем:

  • format — формат данных картинки: jpeg, png
  • mode — цветовая модель картинки: CMYK, RGB, L — для чёрно-белых изображений.
  • width — ширина картинки в пикселях.
  • height — высота картинки в пикселях.
  • size — размер картинки в пикселях. Возвращает tuple: (ширина, высота).

Как их извлечь:

from PIL import Image

image = Image.open("example.jpg")
print(image.format)  # Выведет JPG
print(image.mode)  # Например, может вывести RGB

Открыть картинку

Для открытия картинки используется функция Image.open().

В качестве аргументов она принимает на вход путь до файла, который нужно открыть:

from PIL import Image

image = Image.open("example.jpg")

Сохранить картинку в файл

Для сохранения картинки есть метод .save().

В качестве аргументов он принимает:

  • Путь до файла, в который сохранить картинку.
  • Именованный необязательный параметр format, в котором передаётся формат сохраняемой картинки.
from PIL import Image

image = Image.open("example.jpg")
image.save("new.jpg")
image.save("another.jpg", format="JPEG")

В качестве результата появится 2 копии картинки: new.jpg и another.jpg.

Перевести картинку в другую цветовую модель

О цветовой модели вы можете прочитать в разделе Атрибуты. Чтобы поменять цветовую модель картинки, нужно воспользоваться методом .convert(). Он принимает на вход именной аргумент mode:

from PIL import Image

image = Image.open("example.jpg")
print(image.mode)  # Вывелось RGB
cmyk_image = image.convert("CMYK")
print(cmyk_image.mode)  # Вывелось CMYK
print(image.mode)  # Вывелось RGB

Заметим, что метод не меняет исходную картинку, а создаёт её копию с цветовой моделью CMYK. Поэтому мы положили её в отдельную переменную.

Обрезать картинку

За обрезание картинки отвечает метод .crop(). Он принимает на вход кортеж из 4 чисел: координат углов новой картинки. Координаты отсчитываются с левого верхнего угла картинки:

sample_text

Координаты нужно передать в таком порядке: слева, сверху, справа, снизу. Например, вы хотите отрезать 10 пикселей слева и 15 сверху:

sample_text

Пример:

from PIL import Image

image = Image.open("example.jpg")
coordinates = (10, 15, image.width, image.height)
cropped = image.crop(coordinates)  # Отрежется 10 пикселей слева и 15 сверху

Этот код отрезает 10 пикселей слева и 15 сверху. Самая правая координата — это и есть ширина картинки, а самая нижняя — высота, поэтому мы и использовали эти атрибуты картинки.

Разделить картинку на каналы

sample_text

Картинки состоят из пикселей разных цветов. Каждый пиксель картинки в RGB состоит из 3 значений: сколько в нём красного, сколько зелёного и сколько синего. А в цветовой схеме CMYK из четырёх: голубой, пурпурный, жёлтый и чёрный. Все значения от 0 до 255. 0 — нет такого цвета, а 255 — его очень-очень много.

На самом деле картинки хранят не по пикселям, а по каналам. RGB картинка хранится как 3 картинки: в первой в каждом пикселе число от 0 до 255, показывающее, сколько в нём красного. Во второй то же, только с зелёным, а в третьем — с синим.

Получается 3 картинки. Но если взять какой-то цветовой канал отдельно от картинки, то она не будет знать, какой цвет ей показывать. У неё в каждом пикселе всего одно значение от 0 до 255. Поэтому она отображается как чёрно-белая. Если в пикселе хранится 0, то пиксель будет чёрный, а если 255 — белый. Чем больше число, тем светлее пиксель.

Метод .split() разбивает картинку на каналы. Работает так:

from PIL import Image

image = Image.open("example.jpg")
print(image.mode)  # Вернуло CMYK, значит канала 4
cyan, magenta, yellow, key_color = image.split()  # В переменные запишутся 4 чёрно-белые картинки.

Собрать картинку из каналов

sample_text

Pillow позволяет разделять картинку на каналы. Но так же позволяет и собирать её обратно. За это отвечает функция Image.merge(). Она принимает на вход 2 аргумента:

  • Цветовая модель будущей картинки
  • Кортеж из цветовых каналов. Если модель RGB, то первый канал будет покрашен в красный, второй в зелёный, третий в синий.

Пример:

from PIL import Image

image = Image.open("example.jpg")
print(image.mode)  # Вернуло CMYK, значит канала 4
cyan, magenta, yellow, key_color = image.split()  # В переменные запишутся 4 чёрно-белые картинки.
new_image = Image.merge("CMYK", (cyan, magenta, yellow, key_color))

new_image ничем не отличается от image, т.к. состоит из тех же каналов в том же порядке.

Покрасить цветовой канал

Pillow позволяет раскрашивать чёрно-белые картинки. За это отвечает функция ImageOps.colorize().

Она принимает 3 аргумента: Картинка, какой цвет показывать вместо чёрного и какой вместо белого. Пример:

from PIL import Image, ImageOps

image = Image.open("example.jpg")
colorized = ImageOps.colorize(image, black ="red", white ="yellow")

Код выше сделает из такой картинки:

Такую картинку:

Изменить размер картинки

Как работает thumbnail

Метод resize приводит картинку к желаемому размеру без сохранения пропорций. Картинка жмётся, становится некрасивой:

Метод thumbnail сохраняет пропорции:

Подробнее о thumbnail

С помощью метода .thumbnail() можно легко сделать миниатюру изображения. Миниатюра — уменьшенная версия картинки, с сохранением пропорций. На вход принимается кортеж с максимальными шириной и высотой. Метод .thumbnail() сам подберёт новые координаты так, чтобы картинка поместилась в заданную область. Например, у вас есть картинка 800x1200 и вы хотите поместить её в рамку 1200x600, то результат метода будет 400x600, т.к. 400x600 как раз помещается в 1200x600:

from PIL import Image

image = Image.open("example.jpg")
print(image.size)  # Вывелось (800, 1200)
image.thumbnail((1200, 600))  # Картинка теперь размера 400 на 600
print(image.size)  # Вывелось (400, 600)

Наложить картинки друг на друга

Функция Image.blend() создаёт новую картинку, накладывая одно изображение поверх другого. Для работы ему необходимы три аргумента:

  • Первая картинка.
  • Вторая картинка, того же размера, что и первая.
  • Коэффициент прозрачности.

Если прозрачность равна 0.5, то картинки смешаются в равных долях. Если коэффициент равен 1.0, то первая картинка станет полностью прозрачной и останется только вторая. Если 0.0, то наоборот. Прозрачность задаётся дробным числом через точку.

from PIL import Image

image1 = Image.open("image1.jpg")
image2 = Image.open("image2.jpg")
image3 = Image.blend(image1, image2, 0.5)  # Получится картинка, сложенная из двух

Наложить со смещением

sample_text

Отдельного метода для этого нет, но получается за счёт комбинации .crop() и Image.blend().

  1. Выберите картинку для эффекта. У нас это картинка wave.png с шириной в 1000 пикселей.
  2. Отрежьте от неё 200 пикселей слева. Получится wave_left.png шириной 800 пикселей.
  3. Возьмите исходную картинку wave.png и отрежьте от неё по 100 пикселей с обоих сторон: слева и справа. Получится wave_middle.png тоже шириной в 800 пикселей.
  4. Наложите wave_left.png на wave_middle.png с помощью Image.blend()
  5. Сохраните в файл то, что получилось. Это картинка смещённая влево.

Попробуйте бесплатные уроки по Python

Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.

Переходите на страницу учебных модулей «Девмана» и выбирайте тему.