Pillow – то интересный проект, который позволяет легко и просто обрабатывать изображения с использованием средств Python. Основан на библиотеке изображений Python или PIL (сокращенно). Последний перестал обновляться еще в 2009 году, и поэтому команде разработчиков пришлось создать форк библиотеки, который используется в оригинальной Python 3.
- Как открыть картинку с помощью Pillow?
- Как получить данные о картинке с помощью Pillow
- Как обрезать картинки?
- Как поворачивать картинку?
- Как показать картинку в Tkinter?
- Как подгрузить картинку из URL в Pillow
- Как создается рисунок в Pillow?
- ImageFont – как писать текст на изображении?
- Что такое фильтры и как их использовать?
Как открыть картинку с помощью Pillow?
Pillow позволяет без лишних усилий изменять изображения. Но для начала необходимо его открыть. Это делается с помощью методов open() и show(). Последний применяется в целях отладки.
Посмотрите на этот код.
from PIL import Image image = Image.open('jelly.jpg') image.show()
В первой строчке импортируется модуль Image, а затем открывается изображение jelly.jpg с использованием метода open(). На Unix-системах этот метод создает временный файл, в котором и сохраняется изображение, а потом он открывается с помощью xv. Например, на Linux открытие картинки осуществляется с помощью ImageMagick. Если программа будет работать на Windows, она сначала сохранит картинку во временном файле формата BMP, а потом откроется изображение через приложение типа Paint.
Как получить данные о картинке с помощью Pillow
Pillow дает нам возможность получить детальные сведения о картинке. Давайте приведем пример.
>>> from PIL import Image >>> image = Image.open('jelly.jpg') >>> r, g, b = image.split() >>> histogram = image.histogram() [384761, 489777, 557209, 405004, 220701, 154786, 55807, 35806, 21901, 16242] >>> exif = image._getexif() exif {256: 1935, 257: 3411, 271: u'Panasonic', 272: u'DMC-LX7', 274: 1, 282: (180, 1), 283: (180, 1), 296: 2, 305: u'PaintShop Pro 14.00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 306: u'2016:08:21 07:54:57', 36867: u'2016:08:21 07:54:57', 36868: u'2016:08:21 07:54:57', 37121: '\x01\x02\x03\x00', 37122: (4, 1), 37381: (124, 128), 37383: 5, 37384: 0, 37385: 16, 37386: (47, 10), 40960: '0100', 40961: 1, 40962: 3968, 40963: 2232, 41495: 2, 41728: '\x03', 41729: '\x01', 41985: 0, 41986: 0, 41987: 0, 41988: (0, 10), 41989: 24, 41990: 0, 41991: 0, 41992: 0, 41993: 0, 41994: 0}
Здесь видно, как происходит извлечение значений RGB из файла картинки. Кроме этого, демонстрируется способ создания ее гистограммы.
Учтите, что в данном примере вывод несколько уменьшен, на деле он был большим.
Чтобы построить гистограмму, используется другая библиотека – matplotlib.
Указанный пример указывает на последовательность инструкций, которые необходимо прописать для извлечения данных EXIF. Снова же, здесь вывод уменьшен, поскольку он включает большое количество лишних данных.
Как обрезать картинки?
Pillow имеет весь необходимый инструментарий для обрезки изображений. Приведем фрагмент кода, демонстрирующего, как это работает.
from PIL import Image image = Image.open('jelly.jpg') cropped = image.crop((0, 80, 200, 400)) cropped.save('/path/to/photos/cropped_jelly.png')
Учтите, что здесь достаточно открыть картинку, а потом вызвать метод crop(). А в качестве его аргументов использовать координаты x1, y1, x2, y2 того, что требуется обрезать.
Верхняя левая точка – это пиксель 0. Соответственно, это первая точка. Вторая точка – это противоположный угол прямоугольника, по которому будет осуществляться обрезка.
Вот такой мы получаем результат на выходе. Вообще, это не совсем то, что требуется. Давайте попробуем получить «голову» медузы. Чтобы взять быстро верные координаты, воспользуйтесь графическим редактором, который имеет соответствующий функционал. Например, Gimp или Photoshop. С его помощью мы определяем координаты для обрезки, а потом используем их в качестве аргумента.
from PIL import Image image = Image.open('jelly.jpg') cropped = image.crop((177, 882, 1179, 1707)) cropped.save('/path/to/photos/cropped_jelly2.png')
О, так уже значительно лучше.
Приложение обрезает изображение, после чего обновленная версия сохраняется на диск. Фактически аргумент crop() только один, но представленный в четырех элементах. Это кортеж, который включает в себя координаты прямоугольника.
Как поворачивать картинку?
Для этого используется метод rotate(). Вот, как он работает.
from PIL import Image import sys try: tatras = Image.open("tatras.jpg") except IOError: print("Unable to load image") sys.exit(1) rotated = tatras.rotate(180) rotated.save('tatras_rotated.jpg')
Этот фрагмент кода поворачивает картинку на 180 градусов, а итоговый файл сохраняет в виде нового изображения на диск.
Как показать картинку в Tkinter?
А с помощью такого кода реализуется задача отобразить изображение в графическом интерфейсе приложения.
#!/usr/bin/python3 # -*- coding: utf-8 -*- from PIL import Image, ImageTk from tkinter import Tk from tkinter.ttk import Frame, Label import sys class Example(Frame): def __init__(self): super().__init__() self.loadImage() self.initUI() def loadImage(self): try: self.img = Image.open("tatrs.jpg") except IOError: print("Unable to load image") sys.exit(1) def initUI(self): self.master.title("Label") tatras = ImageTk.PhotoImage(self.img) label = Label(self, image=tatras) # reference must be stored label.image = tatras label.pack() self.pack() def setGeometry(self): w, h = self.img.size self.master.geometry(("%dx%d+300+300") % (w, h)) def main(): root = Tk() ex = Example() ex.setGeometry() root.mainloop() if __name__ == '__main__': main()
Приложение показывает изображение в виджет label тулкит от Tkinter.
from PIL import Image, ImageTk
ImageTk – имеет полную совместимость с Tkinter. Следовательно, возможно его использование в любом месте, где Tkinter ждет получения объекта с картинкой.
tatras = ImageTk.PhotoImage(self.img)
А этот фрагмент кода показывает непосредственно создание изображения.
label = Label(self, image=tatras)
Картинка передается label.
label.image = tatras
Чтобы не допустить накопления мусора, необходимо сохранять все отсылки на картинки.
w, h = self.img.size self.master.geometry(("%dx%d+300+300") % (w, h))
Параметры окна аналогичны параметрам картинки (речь идет конкретно о размерах).
Как подгрузить картинку из URL в Pillow
А теперь продемонстрируем фрагмент кода, в котором показывается, как получить картинку на основе ее URL-адреса.
from PIL import Image import requests import sys url = 'https://i.ytimg.com/vi/vEYsdh6uiS4/maxresdefault.jpg' try: resp = requests.get(url, stream=True).raw except requests.exceptions.RequestException as e: sys.exit(1) try: img = Image.open(resp) except IOError: print("Unable to open image") sys.exit(1) img.save('sid.jpg', 'jpeg')
Приложение, написанное с помощью этого кода, переходит по URL и сохраняет картинку на диск.
import requests
Нами используется библиотека requests, чтобы загрузить картинку.
resp = requests.get(url, stream=True).raw
Картинка читается в виде сырых данных.
img = Image.open(resp)
А здесь изображение создается из объекта response.
img.save('sid.jpg', 'jpeg')
И в результате картинка сохраняется.
Как создается рисунок в Pillow?
Возможности библиотеки Pillow распространяются куда дальше, чем на обработку изображений. Так, с ее помощью возможно создание 2D-графики. Это реализуется с использованием модуля ImageDraw. Нами могут создаваться как новые картинки, так и редактироваться уже существующие. Также возможно создание графики для веб-сайтов.
from PIL import Image, ImageDraw # Создаем белый квадрат img = Image.new('RGBA', (200, 200), 'white') idraw = ImageDraw.Draw(img) idraw.rectangle((10, 10, 100, 100), fill='blue') img.save('rectangle.png')
В качестве примера создадим новую картинку, на которой отображен голубой прямоугольник поверх белого фона.
img = Image.new('RGBA', (200, 200), 'white')
Далее создается картинка с режимом RGB (с альфа каналом), размером 200х200, а фоном белым.
idraw = ImageDraw.Draw(img)
После этого мы генерируем объект ImageDraw, на котором попробуем что-то нарисовать.
idraw.rectangle((10, 10, 100, 100), fill='blue')
С использованием метода rectangle() на площадки картинки, которая была нами сгенерирована таким способом, нами был отрисован голубой прямоугольник.
ImageFont – как писать текст на изображении?
А теперь приведем фрагмент кода, демонстрирующего написание текста на картинке.
from PIL import Image, ImageDraw, ImageFont import sys try: tatras = Image.open("tatras.jpg") except: print("Unable to load image") sys.exit(1) idraw = ImageDraw.Draw(tatras) text = "High Tatras" font = ImageFont.truetype("arial.ttf", size=18) idraw.text((10, 10), text, font=font) tatras.save('tatras_watermarked.png')
Мы сначала импортировали ImageDraw. Потом создали шрифт «Arial размером 18», а потом воспользовались методом text(), чтобы нанести текст. Цвет по умолчанию – белый.
Что такое фильтры и как их использовать?
Под фильтром подразумевается специальная модель для обработки картинки, которая применяется в целом ко всему изображению. Давайте рассмотрим несколько примеров, как возможно использование этого метода.
from PIL import ImageFilter from PIL import Image image = Image.open('jelly.jpg') blurred_jelly = image.filter(ImageFilter.BLUR) blurred_jelly.save('/path/to/photos/blurry_jelly.png')
Данная программа будет брать картинку, а потом размывать ее с помощью фильтра ImageFilter.BLUR. А потом метод save() позволяет нам сохранить итоговый результат. В результате, у нас получается такая фотография.
Тем не менее, как правило, у нас нет необходимости размывать картинку. Наоборот, необходимо увеличить резкость. Для этого используется фильтр ImageFilter.SHARPEN.
Есть еще один способ увеличения резкости картинок в Python. Это модуль ImageEnhance.
Также есть другие фильтры – DETAIL, EDGE_ENHANCE, EMBOSS, SMOOTH и другие. Настоятельно рекомендуется попробовать разные варианты и посмотреть, что будет получаться.