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 чисел: координат углов новой картинки. Координаты отсчитываются с левого верхнего угла картинки:
Координаты нужно передать в таком порядке: слева, сверху, справа, снизу. Например, вы хотите отрезать 10 пикселей слева и 15 сверху:
from PIL import Image image = Image.open("example.jpg") coordinates = (10, 15, image.width, image.height) cropped = image.crop(coordinates) # Отрежется 10 пикселей слева и 15 сверху
Этот код отрезает 10 пикселей слева и 15 сверху. Самая правая координата — это и есть ширина картинки, а самая нижняя — высота, поэтому мы и использовали эти атрибуты картинки.
Разделить картинку на каналы
Картинки состоят из пикселей разных цветов. Каждый пиксель картинки в 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 чёрно-белые картинки.
Собрать картинку из каналов
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() сам подберёт новые координаты так, чтобы картинка поместилась в заданную область. Например, у вас есть картинка 800×1200 и вы хотите поместить её в рамку 1200×600, то результат метода будет 400×600, т.к. 400×600 как раз помещается в 1200×600:
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) # Получится картинка, сложенная из двух
Наложить со смещением
Отдельного метода для этого нет, но получается за счёт комбинации .crop() и Image.blend().
- Выберите картинку для эффекта. У нас это картинка wave.png с шириной в 1000 пикселей.
- Отрежьте от неё 200 пикселей слева. Получится wave_left.png шириной 800 пикселей.
- Возьмите исходную картинку wave.png и отрежьте от неё по 100 пикселей с обоих сторон: слева и справа. Получится wave_middle.png тоже шириной в 800 пикселей.
- Наложите wave_left.png на wave_middle.png с помощью Image.blend()
- Сохраните в файл то, что получилось. Это картинка смещённая влево.
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.
OpenCV — быстрый старт: начало работы с изображениями
Перевожу родной OpenCV-шный туториал. И он хорош! (Сложно сказать, чем не понравились те, что есть.)
Изначально туториал в виде ноутбука , поэтому что-то я убрал. А что-то добавил. В общем, это помесь перевода с пересказом.
Вступление
Эта записнушка поможет с первыми шагами в изучении обработки изображений и машинном зрении через OpenCV. Несколько простых примеров объяснят важные вещи! Рассмотрим:
- Как открыть изображение
- Проверить его атрибуты, вроде формы или типа данных в нём
- Матричное представление картинки в Numpy
- Цветные картинки и работу с каналами изображения
- Вывод изображения через matplotlib
- Сохранение изображений
Импортируем нужные библиотеки
import cv2 # собственно OpenCV import numpy as np # для работы с математикой import matplotlib.pyplot as plt # для вывода картинки
Открываем изображения в OpenCV
Картинкой пойдёт крошечная доска в шашечку, 18×18 пикселей:
OpenCV позволяет работать с разными форматами: JPG, PNG, и так далее. Можно загружать цветные и чб-картинки, изображения с альфа-каналом. Для загрузки воспользуйтесь функцией cv2.imread() .
cv2.imread() — синтаксис и аргументы
retval = cv2.imread( filename[, flags] )
retval : если картинка не загрузилась, в retval запишется None . Такое бывает при ошибке в имени/пути, или если изображение битое.
В функцию передаётся один обязательный аргумент и один необязательный флаг:
- filename : Может быть как относительным, так и абсолютным путём. Это обязательный аргумент.
- Flags : Флаги нужны для чтения изображения в определенном формате (например, в оттенках серого/цветном/с альфа-каналом). Необязательный аргумент! Значение по умолчанию cv2.IMREAD_COLOR или 1 : этот флаг загрузит изображение как цветное.
Перед примерами посмотрим на пару флагов:
- cv2.IMREAD_GRAYSCALE или 0 : Загружаем картинку как чёрно-белую
- cv2.IMREAD_COLOR или 1 : Флаг по умолчанию, загружает картинку как цветную, без альфа-канала.
- cv2.IMREAD_UNCHANGED или -1 : Загружает картинку в том виде, в котором она есть, включая альфу.
Флагов, конечно, больше.
Теперь посмотрим, что внутри шашечек:
# Читаем изображение как чёрно-белое cb_img = cv2.imread("checkerboard_18x18.png",0) # Печатаем что прочитали. Каждый пиксель есть элемент двумерного массива numpy. # Значение пикселей восьмибитное: [0,255] print(cb_img)

Посмотрим атрибуты изображения
# вывод размера изображения (то есть, массива Numpy) print("Image size is ", cb_img.shape) # тип данных в изображении (то есть, в массиве Numpy) print("Data type of image is ", cb_img.dtype)
В ответ получим:
>>>Image size is (18, 18) >>>Data type of image is uint8
Что за uint8?
8-bit unsigned integer arrays!
Uint8 — стандартный способ отображения изображений, где пиксель описывается диапазоном от 0 до 255. Если это изображение в градациях серого, пиксель со значением 0 является черным, а пиксель со значением 255 — белым.
Есть и другие форматы, конечно.
В общем, работаeт всё, что работает с ndarray : .ndim , .itemsize , .fill() .
А теперь выведем картинку через matplotlib
# рисуем шашечки plt.imshow(cb_img) # выводим шашечки plt.show()

Прочитанная цветовая палитра и отображённая могут и не совпасть. Поэтому явно укажем цветовое пространство для вывода изображения:
# Поставим настройку color map plt.imshow(cb_img, cmap='gray')

Другой пример
Расплывчатые шашечки! Такие же, как в прошлый раз, но теперь с нечёткими гранями:
# Читаем картинку как чб cb_img_fuzzy = cv2.imread("checkerboard_fuzzy_18x18.jpg",0) # Печатаем массив print(cb_img_fuzzy) # Показываем картинку plt.imshow(cb_img_fuzzy,cmap='gray') plt.show()


Переходим к цвету
До этого момента мы говорили про чёрно-белые изображения, а теперь поговорим про цветные.
Подопытным кроликом будет лого колы:
Загружаем, проверяем размер и тип данных:
coke_img = cv2.imread("coca-cola-logo.png",1) print("Image size is ", coke_img.shape) print("Data type of image is ", coke_img.dtype)
В ответ получим:
>>>Image size is (700, 700, 3) >>>Data type of image is uint8
Размер картинки поменялся, потому как чб-изображение состоит из одного канала — от чёрного до белого, а цветное — из нескольких, например, трёх: RGB .
Выведем на экран уже известными манипуляциями:
plt.imshow(coke_img) plt.show()

Цвет лого явно отличается от того, что было. Matplotlib ожидает картинку в формате RGB, а OpenCV хранит их в формате BGR. То есть, для корректного отображения нам нужно поменять местами красный и синий каналы.
# ниже numpy-специфичная конструкция: # (:) — взять каждый элемент по порядку, # (::-1) — взять каждый элемент, но в обратном порядке. coke_img_channels_reversed = coke_img[:, :, ::-1] plt.imshow(coke_img_channels_reversed)

Разделение и объединение каналов
cv2.split() — разделит многоканальный массив на несколько одноканальных.
cv2.merge() — объединит массивы в один многоканальный. Массивы должны быть одинакового размера.
Проверим их на озере. В смысле, озером.

# Разбиваем картинку на каналы: B,G,R img_NZ_bgr = cv2.imread("New_Zealand_Lake.jpg",cv2.IMREAD_COLOR) b,g,r = cv2.split(img_NZ_bgr) # Отрисовываем их plt.figure(figsize=[20,5]) plt.subplot(141);plt.imshow(r,cmap='gray');plt.title("Red Channel") plt.subplot(142);plt.imshow(g,cmap='gray');plt.title("Green Channel") plt.subplot(143);plt.imshow(b,cmap='gray');plt.title("Blue Channel") # Собираем обратно в BGR imgMerged = cv2.merge((b,g,r)) # Выводим, что получилось plt.subplot(144);plt.imshow(imgMerged[. -1]);plt.title("Merged Output") plt.show()
точка с запятой в коде.
. не поощряется, но допускается. Помогает писать код в одну строку, а иногда это удобно!

Перевод в иные цветовые пространства
cv2.cvtColor() — преобразует изображение из одного цветового пространства в другое. В случае преобразования в RGB и из него порядок каналов надо указать явно: RGB или BGR. Формат цвета по умолчанию в OpenCV часто называют RGB, но на самом деле это BGR. Первый байт в стандартном 24-битном цветном изображении будет 8-битным синим компонентом, второй байт будет зеленым, а третий байт будет красным. Четвертый, пятый и шестой байты будут, соответственно, вторым пикселем — синий, зеленый, красный, и так до конца картинки.
Преобразование BGR в RGB
img_NZ_rgb = cv2.cvtColor(img_NZ_bgr, cv2.COLOR_BGR2RGB) plt.imshow(img_NZ_rgb) plt.show()
Преобразование в HSV
HSV — Hue, Saturation, Value — тон, насыщенность, значение.
img_hsv = cv2.cvtColor(img_NZ_bgr, cv2.COLOR_BGR2HSV) # Разобъём картинку на H,S,V каналы h,s,v = cv2.split(img_hsv) # Нарисуем и покажем их plt.figure(figsize=[20,5]) plt.subplot(141);plt.imshow(h,cmap='gray');plt.title("H Channel") plt.subplot(142);plt.imshow(s,cmap='gray');plt.title("S Channel") plt.subplot(143);plt.imshow(v,cmap='gray');plt.title("V Channel") plt.subplot(144);plt.imshow(img_NZ_rgb);plt.title("Original") plt.show()

Модификация отдельного канала
Хочется синий посиней? Есть решение!
img_NZ_bgr = cv2.imread("New_Zealand_Lake.jpg",cv2.IMREAD_COLOR) b,g,r = cv2.split(img_NZ_bgr) b = b+50 # осиняем plt.figure(figsize=[20,5]) plt.subplot(141);plt.imshow(r,cmap='gray');plt.title("Red Channel") plt.subplot(142);plt.imshow(g,cmap='gray');plt.title("Green Channel") plt.subplot(143);plt.imshow(b,cmap='gray');plt.title("Blue Channel") imgMerged = cv2.merge((r,g,b)) # в этот раз соберём сразу RGB plt.subplot(144);plt.imshow(imgMerged);plt.title("Merged Output") plt.show()

Сохранение изображений
Почти cv2.imread , только cv2.imwrite . Первым аргументом передаём путь и имя, вторым — изображение. Оба два обязательны. Расширение OpenCV подберёт, отталкиваясь от указанного в имени. Ещё можно докинуть параметров, и, например, указать качество JPG.
cv2.imwrite( filename, img[, params] )
Вот и всё! Первый маленький шажок к человеку-фотошопу пройден! До встречи в следующих сериях.
Инструменты для работы с изображениями в Python и Pillow

Автор телеграм-канала CODE BLOG Вадим Шванов написал для нас статью о работе с изображениями c использованием языка Python и Pillow. В ней он рассматривает основы работы с изображениями в Python, показывает, как создать фильтры для фотографий в библиотеке Pillow, преобразовать изображение в массив в библиотеке NumPy и использовать matplotlib для настраиваемого вывода результата на экран. Дочитайте до конца: там вы найдете ссылку на .ipynb-документ со всем используемым кодом, который вы сможете загрузить.
Кому это нужно?
- создание своего фоторедактора;
- создание масок для Instagram;
- анализ и распознавание образов в компьютерном зрении.

Освойте профессию
«Fullstack-разработчик на Python»
Fullstack-разработчик на Python
Fullstack-разработчики могут в одиночку сделать IT-проект от архитектуры до интерфейса. Их навыки востребованы у работодателей, особенно в стартапах. Научитесь программировать на Python и JavaScript и создавайте сервисы с нуля.

Профессия / 12 месяцев
Fullstack-разработчик на Python
Создавайте веб-проекты самостоятельно

А я справлюсь?
В инструкции используются простые операции, поэтому она подойдет для новичков — достаточно уметь немного кодить на Python.
Установка пакетов
NumPy и matplotlib можно установить с помощью пакетного менеджера pip, запустив следующие команды в терминале:
pip install numpy
pip install matplotlib
С Pillow сложнее: Python старше версии 3.6 поддерживает установку этого пакета через pip, а с другими версиями может возникнуть ошибка. Совместимость версий можно посмотреть тут.
Для этого примера в качестве среды разработки выбран Jupyter Notebook.
Начало работы
Импортируйте все необходимые модули и загрузите изображение в объект Python:

Как правило, NumPy импортируется с псевдонимом np, а matplotlib.pyplot — plt.
Загрузите изображение с помощью функции open() подмодуля Image:

Jupyter Notebook выводит изображения по их имени. Вот то самое изображение, путь к которому мы передали в функцию:

Далее мы создадим свою функцию, чтобы у нас была возможность добавить надпись над фотографией (заголовок) или изменить ее размер.
Вывод изображений с matplotlib
Это функция, которую мы будем использовать далее:

Она принимает два параметра: img — массив, который вы получили из исходной фотографии, и title — заголовок, который по умолчанию имеет значение None. Измените размеры фигуры на 6×6, чтобы сделать вывод изображения больше, и выведите его на экран. Также проверьте, был ли указан заголовок. Если нет — установите его с помощью функции title(). Выключите пометки на осях, указав ‘off’ в функции axis().

Станьте Fullstack-разработчик на Python и найдите стабильную работу
на удаленке
Как сделать изображение черно-белым
Здесь мы будем использовать метод convert() класса изображения PIL.
Функция выглядит просто:

Мы представили изображение в RGB-формате, то есть каждый пиксель имеет три значения: красный (R), зеленый (G) и синий (B). Оттенки серого получаются, когда все эти три значения равны. Есть известная формула яркости пикселя:

Но Pillow использует свои коэффициенты:

Изображение потеряло в качестве из-за того, что его растянули с помощью matplotlib.

Станьте Fullstack-разработчик на Python и найдите стабильную работу
на удаленке
Как переформатировать изображение в массив
Теперь мы будем использовать инструменты NumPy, поэтому желательно конвертировать изображение в np.array:

Конструктор массива принимает изображение в качестве аргумента и создает такой массив. Форму массива можно узнать с помощью поля shape.

224×225 — размеры нашего изображения. «3» появляется из-за того, что каждый пиксель представлен тремя значениями.
Как добавить фильтр «Негатив»
Значения цветов могут меняться от 0 до 255. Негатив — эффект инвертирования цветов. Достигается он просто: от 255 нужно отнять значение цвета. Так как все операции над массивом NumPy выполняются поэлементно, то мы отнимем от 255 текущий массив:

С помощью функции show() оценим результат:

Как отзеркалить изображение
Следующая задача — отражение изображения слева направо (т. е. правая и левая стороны изображения меняются местами). В NumPy есть функция fliplr. Про ее применение можно найти информацию здесь.
Передайте исходный массив в fliplr:

Этот фрагмент кода не изменяет массив, а возвращает новый, что нам и нужно. Оценим результат работы:

Как добавить эффект
Идея этого эффекта проста — нужно сделать изображение как можно синее. Для этого замените каждое третье «значение пикселя» на максимальное — 255.

Здесь нужно поменять сам массив, и, чтобы не потерять исходное изображение, скопируйте последовательность с помощью np.copy().
Другой вариант конструкции:

Весь код из статьи вы сможете найти в этом документе.
Обработка изображений с использованием OpenCV в Python

Познайте методы предварительного преобразований плоского изображения, такие как перемещение изображения, отражение, поворот, масштабирование, обрезка и нарезка с помощью библиотеки OpenCV в Python.
Введение ↑
По существу, трансформация изображения — это его отображение из одной системы координат в другою, она сопоставляет некоторые координаты точки (x, y) в одной системе с точкой координатами (x’, y’) в другой системе координат.

Например, если у нас есть точка с координатами (2, 3) в системе координате x \times y и мы строим ту же точку в системе координате u \times v , естественно, она будет выглядеть по-разному, как и показано на рисунке ниже:

- Для чего неоходимо преобразовывать изображения?
- Перенос изображений
- Масштабирование изображения
- Сдвиг изображения
- Сдвиг в направление оси x
- Сдвиг в направление оси Y
Для чего неоходимо преобразовывать изображения? ↑
На изображении ниже геометрическое соотношение между комиксом и изображением справа основано на преобразовании подобия (поворот, перемещение и масштабирование). Если нам нужно обучить модель машинного обучения, которая находит этот комикс, то нам нужно ввести изображение в другой форме и под другим углом.

Методы преобразования изображений очень нам помогут на этапе предварительной обработки изображений в машинном обучении.
Изображение может быть представлено как матрица. Каждое значение в матрице — это цвет пикселя в определенной координате. Преобразование изображения может быть выполнено с использованием матричного умножения. В математике есть несколько матричных уравнений, которые можно использовать для выполнения определенных операций преобразования.
Перенос изображений ↑
Трансляция изображения или перенос — это прямолинейный сдвиг изображения из одного места в другое, поэтому сдвиг объекта называется переносом. Приведенное ниже матричное уравнение используется для переноса изображения:
\beginx’ \\ y’ \\ 1\end = \begin0 & 0 & b_x \\ 0 & 1 & b_y \\ 0 & 0 & 1 \end \beginx \\ y \\ 1\end

Значение b_x определяет, насколько изображение будет перемещено по оси x , а значение b_y определяет перемещение изображения по оси y :
Теперь, когда вы поняли перенос изображений, давайте взглянем на код Python. В OpenCV есть две встроенные функции для выполнения такого преобразований:
- cv2.warpPerspective , которая принимает в качестве входных данных матрицу преобразования (3×3).
- cv2.warpAffine принимает матрицу преобразования (2×3) в качестве входных данных.
Обе функции принимают три входных параметра:
- Входное изображение.
- Матрица трансформации.
- Кортеж высоты и ширины изображения.
В этом уроке будем использовать функцию cv2.warpPerspective() .
Приведенный ниже код считывает входное изображение (если вам важна точность, получите изображение из этого урока здесь и поместите его в текущий рабочий каталог), переносит и показывает:
import numpy as np import cv2 import matplotlib.pyplot as plt # читать входное изображение img = cv2.imread("chelyabinsk.jpg") # преобразовать из BGR в RGB, чтобы можно было построить график с помощью matplotlib img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # отключить оси x и y plt.axis('off') # показать изображение plt.imshow(img) plt.show() # получить форму изображения rows, cols, dim = img.shape # матрица преобразования для перевода M = np.float32([ [1, 0, 50], [0, 1, 50], [0, 0, 1] ]) # применяем перспективное преобразование к изображению translated_img = cv2.warpPerspective(img, M, (cols, rows)) # отключить оси x и y plt.axis('off') # показать получившееся изображение plt.imshow(translated_img) plt.show() # сохраняем получившееся изображение на диск plt.imsave("chelyabinsk_translated.jpg", translated_img)Обратите внимание, что мы используем plt.axis(‘off’) , поскольку мы не хотим выводить значения оси, и мы показываем изображение с помощью функции imshow() из matplotlib.
Также использована функцию plt.imsave() для локального сохранения изображения.

Исходное изображение:

Результат переноса:
Масштабирование изображения ↑
Масштабирование изображения એ — это процесс изменения размера цифрового изображения с сохранением пропорций. OpenCV имеет встроенную функцию cv2.resize() , но мы будем выполнять преобразование, используя умножение матриц, как и раньше. Матричное уравнение, используемое для масштабирования, показано ниже.
\beginx’ \\ y’ \\ 1\end = \beginS_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1 \end \beginx \\ y \\ 1\end

S_x и S_y — коэффициенты масштабирования для оси x и оси y соответственно.
Приведенный ниже код отвечает за чтение того же изображения, определение матрицы преобразования для масштабирования и показывает получившееся изображение:
import numpy as np import cv2 import matplotlib.pyplot as plt # читать входное изображение img = cv2.imread("chelyabinsk.jpg") # преобразовать из BGR в RGB, чтобы можно было построить график с помощью matplotlib img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # отключить оси x и y plt.axis('off') # показать изображение plt.imshow(img) plt.show() # получить форму изображения rows, cols, dim = img.shape # матрица преобразования для масштабирования M = np.float32([ [1.5, 0 , 0], [0, 1.8, 0], [0, 0, 1] ]) # применяем перспективное преобразование к изображению scaled_img = cv2.warpPerspective(img,M,(cols*2,rows*2)) # отключить оси x и y plt.axis('off') # показать получившееся изображение plt.imshow(scaled_img) plt.show() # сохраняем получившееся изображение на диск plt.imsave("chelyabinsk_scaled.jpg", scaled_img)
Вот результат:
Обратите внимание, что вы можете легко удалить эти черные пиксели с помощью обрезки, но об этом в конце урока.
Скольжение изображения
Карта сдвига — это линейная карта, которая смещает каждую точку в фиксированном направлении, она заменяет каждую точку по горизонтали или вертикали определенным значением, пропорциональным ее координатам x или y , есть два типа эффектов сдвига.
Скольжение в направление оси x ↑

Когда сдвиг выполняется в направлении оси x , границы изображения, параллельные оси x , сохраняют свое положение, а края, параллельные оси y , меняют свое положение в зависимости от коэффициента сдвига:
Скольжение в направление оси Y ↑
Когда сдвиг выполняется в направлении оси y , границы изображения, параллельные оси y , сохраняют свое положение, а края, параллельные оси x , меняют свое положение в зависимости от коэффициента сдвига.
Матричное уравнение для скольжения показано ниже:
\beginx’ \\ y’ \\ 1\end = \beginsh_x & 0 & 0 \\ 0 & sh_y & 0 \\ 0 & 0 & 1 \end \beginx \\ y \\ 1\end
Ниже приведен код для скольжения:
import numpy as np import cv2 import matplotlib.pyplot as plt # читать входное изображение img = cv2.imread("chelyabinsk.jpg") # конвертировать из BGR в RGB, чтобы мы могли построить график с помощью matplotlib img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # отключить оси x и y plt.axis('off') # показать изображение plt.imshow(img) plt.show() # получить форму изображения rows, cols, dim = img.shape # матрицы преобразования для сдвига # сдвиг, примененный к оси x M = np.float32([ [1, 0.5, 0], [0, 1 , 0], [0, 0 , 1] ]) # сдвиг, примененный к оси Y # M = np.float32([ [1, 0, 0], # [0.5, 1, 0], # [0, 0, 1] ]) # применяем перспективное преобразование к изображению sheared_img = cv2.warpPerspective(img,M,(int(cols*1.5),int(rows*1.5))) # отключить оси x и y plt.axis('off') # show the resulting image plt.imshow(sheared_img) plt.show() # сохраняем получившееся изображение на диск plt.imsave("chelyabinsk_sheared.jpg", sheared_img)Первая матрица — это сдвиг, примененный к оси x , если вы хотите ось y , то закомментируйте первую матрицу и раскомментируйте вторую.

Скольжение изображения по оси x :

Скольжение изображения по оси y :
Отражение изображения ↑
Отражение изображения (или зеркальное отображение) переворачивает изображение как по вертикали, так и по горизонтали, это частный случай масштабирования. Для отражения по оси x мы устанавливаем значение S_y равным -1 , а S_x равным 1 и наоборот для отражения по оси y .
Матричные уравнения преобразования для отражения показаны ниже:
\beginx’ \\ y’ \\ 1\end = \begin1 & 0 & 0 \\ 0 & -1 & rows \\ 0 & 0 & 1 \end \beginx \\ y \\ 1\end
\beginx’ \\ y’ \\ 1\end = \begin-1 & 0 & cols \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end \beginx \\ y \\ 1\end
Вот вам для размышлений код Python:
import numpy as np import cv2 import matplotlib.pyplot as plt # read the input image img = cv2.imread("chelyabinsk.jpg") # convert from BGR to RGB so we can plot using matplotlib img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # disable x & y axis plt.axis('off') # show the image plt.imshow(img) plt.show() # get the image shape rows, cols, dim = img.shape # transformation matrix for x-axis reflection M = np.float32([ [1, 0, 0 ], [0, -1, rows], [0, 0, 1 ] ]) # transformation matrix for y-axis reflection # M = np.float32([ [-1, 0, cols], # [ 0, 1, 0 ], # [ 0, 0, 1 ] ]) # apply a perspective transformation to the image reflected_img = cv2.warpPerspective(img,M,(int(cols),int(rows))) # disable x & y axis plt.axis('off') # show the resulting image plt.imshow(reflected_img) plt.show() # save the resulting image to disk plt.imsave("chelyabinsk_reflected.jpg", reflected_img)Как и раньше, сначала будет переворот относительно ось x (вертикальное отображение). Если хотите, раскомментируйте вторую матрицу и закомментируйте первую, получите переворот относительно оси y (вертикальное отображение).

Переворот изображения относительно оси X :

Переворот изображения относительно оси Y :
Поворот изображения ↑

Вращение — это понятие в математике, которое представляет собой движение определенного пространства, которое сохраняет хотя бы одну точку. Поворот изображения — это обычная процедура обработки изображений с приложениями для сопоставления, выравнивания и других алгоритмов на основе изображений, а также для увеличения данных, особенно когда речь идет о классификации изображений.
Матрица преобразования вращения показана на рисунке ниже, где \theta — угол поворота:
\beginx’ \\ y’ \\ 1\end = \begin\cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0\\ 0 & 0 & 1 \end \beginx \\ y \\ 1\end
Ниже приведен код Python для поворота изображения:
import numpy as np import cv2 import matplotlib.pyplot as plt # читать входное изображение img = cv2.imread("chelyabinsk.jpg") # преобразовать из BGR в RGB, чтобы можно было построить график с помощью matplotlib img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # отключить оси x и y plt.axis('off') # показать изображение plt.imshow(img) plt.show() # получить форму изображения rows, cols, dim = img.shape # угол от градуса до радиана angle = np.radians(10) # матрица преобразования для вращения M = np.float32([ [np.cos(angle), -(np.sin(angle)), 0], [np.sin(angle), np.cos(angle), 0], [0, 0, 1] ]) # применяем перспективное преобразование к изображению rotated_img = cv2.warpPerspective(img, M, (int(cols),int(rows))) # отключить оси x и y plt.axis('off') # показать получившееся изображение plt.imshow(rotated_img) plt.show() # сохраняем получившееся изображение на диск plt.imsave("chelyabinsk_rotated.jpg", rotated_img)
Вот и повернули изображение:
Оно было повернуто на 10° (np.radians(10)) , вы можете редактировать код по своему усмотрению!
Обрезка изображения ↑
Обрезка изображения — это удаление нежелательных внешних областей с изображения, многие из приведенных выше примеров включают черные пиксели, вы можете легко удалить их с помощью обрезки. Код ниже делает это:
import numpy as np import cv2 import matplotlib.pyplot as plt # читать входное изображение img = cv2.imread("chelyabinsk.jpg") # преобразовать из BGR в RGB, чтобы можно было построить график с помощью matplotlib img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # отключить оси x и y plt.axis('off') # показать изображение plt.imshow(img) plt.show() # получаем 200 пикселей от 100 до 300 по оси x и оси y # измените это, если хотите, просто убедитесь, что вы не превышаете столбцы и строки cropped_img = img[100:300, 100:300] # отключить оси x и y plt.axis('off') # показать получившееся изображение plt.imshow(cropped_img) plt.show() # сохраняем получившееся изображение на диск plt.imsave("chelyabinsk_cropped.jpg", cropped_img)
Поскольку OpenCV загружает изображение в виде массива numpy, то можно обрезать изображение, просто указав нужные индексы нарезки, в нашем случае мы решили получить изображение размером 200х200 пикселей, вырезанное из исходного с 100 по 300 пиксели по обеим осям. Вот результат:
Заключение ↑
В этом уроке мы рассмотрели основы обработки и преобразования изображений, которые включают перенос изображения, масштабирование, сдвиг, отражение, поворот и обрезку.
Вы можете получить все коды здесь .

Обработка изображений с использованием OpenCV в Python , опубликовано К ВВ, лицензия — Creative Commons Attribution-NonCommercial 4.0 International.
Респект и уважуха
