Введение ↑
По существу, трансформация изображения — это его отображение из одной системы координат в другою, она сопоставляет некоторые координаты точки (x, y) в одной системе с точкой координатами (x', y') в другой системе координат.
Например, если у нас есть точка с координатами (2, 3) в системе координате x-y и мы строим ту же точку в системе координате u-v, естественно, она будет выглядеть по-разному, как и показано на рисунке ниже:
Содержание
Для чего неоходимо преобразовывать изображения? ↑
На изображении ниже геометрическое соотношение между комиксом и изображением справа основано на преобразовании подобия (поворот, перемещение и масштабирование). Если нам нужно обучить модель машинного обучения, которая находит этот комикс, то нам нужно ввести изображение в другой форме и под другим углом.
Методы преобразования изображений очень нам помогут на этапе предварительной обработки изображений в машинном обучении.
Изображение может быть представлено как матрица. Каждое значение в матрице — это цвет пикселя в определенной координате. Преобразование изображения может быть выполнено с использованием матричного умножения. Математики разработали несколько видов матриц, которые можно использовать для выполнения определенных операций преобразования.
Перенос изображений ↑
Трансляция изображения или перенос — это прямолинейный сдвиг изображения из одного места в другое, поэтому сдвиг объекта называется переносом. Приведенная ниже матрица используется для переноса изображения:
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}0 & 0 & B_x \\ 0 & 1 & B_y \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix}
Значение 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()
, но мы будем выполнять преобразование, используя умножение матриц, как и раньше. Матрица, используемая для масштабирования, показана ниже.
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}S_x & 0 & 0 \\ 0 & S_y & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix}
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, меняют свое положение в зависимости от коэффициента сдвига.
Матрица для сдвига показана на рисунке ниже:
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}sh_x & 0 & 0 \\ 0 & sh_y & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix}
Ниже приведен код, отвечающий за сдвиг:
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.
Матричные преобразования для отражения показаны ниже:
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}1 & 0 & 0 \\ 0 & -1 & rows \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix}
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}-1 & 0 & cols \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix}
Вот код 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 — угол поворота:
\begin{bmatrix}x' \\ y' \\ 1\end{bmatrix} = \begin{bmatrix}\cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix}x \\ y \\ 1\end{bmatrix}
Ниже приведен код 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 пиксель по обеим осям. Вот результат:
Заключение ↑
В этом уроке мы рассмотрели основы обработки и преобразования изображений, которые включают перенос изображения, масштабирование, сдвиг, отражение, поворот и обрезку.
Вы можете получить все коды здесь.
По материалам Image Transformations using OpenCV in Python