Аффинные преобразования

Содержание лекции:

1. Афинные преобразования

2. Виды афинных преобразований

3. Композиция афинных преобразований

4. Неафинные преобразования


Запись восьмого занятия можно посмотреть по ссылке

1. Аффинное преобразование

Это взаимооднозначное преобразование, при котором прямые линии переходят в прямые линии.

Особенности аффинного преобразования

Рассмотрим подробнее особенности аффинного преобразования:

  1. Каждой точке в соответствие ставится другая точка: нет таких точек, у которых не будет соответствия.

2. Разные точки переходят в разные точки: нет двух таких точек, которые переходят в одну и ту же точку.

3. Параллельные прямые переходят в параллельные: т. е. как ни крути, если две прямые на исходном изображении параллельные друг другу, то и на результирующем они будут параллельны.

4. Пересекающиеся прямые переходят в пересекающиеся: аналогично, если две прямые пересекаются на исходном изображении, то на результирующем они также будут пересекаться.

Матричное представление

Аффинное преобразование представляют в виде матрицы 3 на 3, далее рассмотрим примеры матриц для отдельных видов преобразований.

Особенности результата

  • В цифровом виде точки исходного изображения соответствуют координатам его пикселей.
  • В результате преобразования точки могут оказаться в промежутках между координатами пикселей результирующего изображения.
  • Для вычисления цвета новых пикселей используется интерполяция.

2. Виды аффинных преобразований

Изменение размера изображения по горизонтали и вертикали.

Сжатие/растяжение/scale

Преобразования сжатия и растяжения позволяют изменить размер изображения по горизонтали и вертикали.

Ниже изображены матрица такого преобразования и пример.

OpenCV: сжатие/растяжение

В OpenCV есть как простая функция для изменения размера изображения - cv2.resize, так есть функция, которая позволяет использовать заготовленную матрицу для выполнения преобразования - cv2.warpPerspective.

Обратите внимание, что для матрицы используется атрибут T, которые позволяет получить транспонированную матрицу. Изначально, то что выглядит строками в коде, является столбцами в получившейся матрице, так что необходимо её транспонировать, чтобы представление в коде соответствовало записи матрицы.

Функция resize:

result = cv2.resize(image, (width, height))

Функция warpPerspective:

M = numpy.float32([[x, 0, 0], [0, y, 0], [0, 0, 1]]).T

# T означает транспонирование

result = cv2.warpPerspective(image, M, (width, height))

Спецификация функции resize

Функция resize имеет два режима работы - один позволяет установить точный размер результирующего изображения, а второй позволяет изменить размер изображения в указанное число раз.

Помимо этого, функция resize принимает на вход способ выполнения интерполяции:

  1. cv2.INTER_NEAREST - ближайший сосед.
  2. cv2.INTER_LINEAR - линейная интерполяция, по умолчанию.
  3. cv2.INTER_AREA - масштаб с учётом площади пикселя, даёт плавное изображение при уменьшении размера.
  4. cv2.INTER_CUBIC - бикубическая интерполяция, учитываются соседи 4 * 4.
  5. cv2.INTER_LANCZOS4 - интерполяция Ланцоша, учитываются соседи 8 * 8.

resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst

src - исходное изображение

dsize - размер результирующего изображения

dst - результирующее изображение

fx, fy - коэффициенты сжатия/растяжения вместо dsize

Спецификация функции warpPerspective

Функция warpPerspective принимает на вход изображение, матрицу преобразования, размер результирующего изображения, т. е. его необходимо предварительно вычислить.

Также функция принимает флаги интерполяции и инверсии:

  1. INTER_LINEAR - линейная интерполяция.
  2. INTER_NEAREST - ближайший сосед.
  3. WARP_INVERSE_MAP - смена направления преобразования на dst -> src.

И функция принимает параметры для вычисления значений на границе:

  1. borderMode позволяет задать режим значений на границе: BORDER_CONSTANT - константное значение за границей или BORDER_REPLICATE - повторение за границей значения на границе.
  2. И borderValue - значение для BORDER_CONSTANT.

Перенос/translate

Следующее преобразование - перенос. Это перемещение изображения по горизонтали и вертикали. Это преобразование ещё называют параллельным переносом.

OpenCV: перенос

Для выполнения переноса также используется функция warpPerspective.

M = numpy.float32([

    [1, 0, 0],

    [0, 1, 0],

    [width / 2.0, height / 2.0, 1]

]).T

result = cv2.warpPerspective(image, M, (width, height))

Поворот/rotate

Поворот - это преобразование, которое позволяет повернуть изображение вокруг начала координат.

OpenCV: вращение

Для вращения также используется функция warpPerspective.

phi = math.pi / 4.0 # Угол вращения в радианах

M = numpy.float32([

    [math.cos(phi), math.sin(phi), 0],

    [-math.sin(phi), math.cos(phi), 0],

    [0, 0, 1]

])

result = cv2.warpPerspective(image, M, (width, height))

3. Композиция аффинных преобразований

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

Для того, чтобы выполнить поворот вокруг указанной точки, используется композиция преобразований переноса и вращения.

Поговорим о композиции. Результатом композиции двух аффинных преобразований является также аффинное преобразование. Для выполнения композиции используется скалярное произведение двух матриц.

OpenCV: вращение

Посмотрим, как применить композицию для вращения вокруг указанной точки в OpenCV: для этого нужно собрать композицию из двух преобразований переноса и одного преобразования вращения.

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

Для выполнения скалярного произведения матриц в OpenCV есть функция dot.

Т. к. вращение вокруг координаты (0, 0) для вращения вокруг произвольной координаты (x, y) нужно дважды использовать перенос.

Для композиции преобразований используется скалярное произведение матриц - функция numpy.dot:

M = numpy.dot(numpy.dot(M1, M2), M3)

# M1 - перенос на (x, y)

# M2 - вращение

# M3 - перенос на (-x, -y)

OpenCV: warpAffine

Помимо функции warpPerspective в OpenCV есть функция warpAffine, которая заточена на ряд преобразований и принимает на вход матрицу другого размера. В частности, для генерации матрицы поворота можно использовать функцию getRotationMatrix2D. Предлагаю вам самостоятельно изучить отличия функции warpAffine от warpPerspective.

Более простой вариант для вращения - с помощью getRotationMatrix2D и warpAffine:

phi = math.pi / 4.0

M = cv2.getRotationMatrix2D((width / 2, height / 2), phi / math.pi * 180.0, 1.0)

result = cv2.warpAffine(image, M, (width, height))

Размер и вид матрицы на вход warpAffine отличается от размера для warpPerspective.

Сдвиг/shear

Сдвиг - смещение противоположных краёв изображения в разные стороны.

OpenCV: сдвиг

В OpenCV также выполняется с помощью warpPerspective.

M = numpy.float32([

    [1, y, 0],

    [x, 1, 0],

    [0, 0, 1]

]).T

result = cv2.warpPerspective(image, M, (width, height))

4. Неафинные преобразования

Особенности

  • Параллельные прямые переходят не обязательно в параллельные.
  • Прямые переходят не обязательно в прямые.

Виды неаффинных преобразований

  1. Изменение перспективы.
  2. И дисторсия и андисторсия.

Изменение перспективы

Изменение перспективы происходит путём сопоставления нескольких координат на одном изображении координанатам на другом.

OpenCV: изменение перспективы

В OpenCV можно сгенерировать матрицу для изменения перспективы на основе координат 4 точек с помощью функции getPerspectiveTransform.

А для применения матрицы используется уже знакомая нам функция warpPerspective.

Для получения матрицы используется функция getPerspectiveTransform:

pts1 = numpy.float32([[56, 65], [368, 52], [28, 387], [389, 390]])

pts2 = numpy.float32([[0, 0], [300, 0], [0, 300], [300, 300]])

M = cv2.getPerspectiveTransform(pts1, pts2)

result = cv2.warpPerspective(image, M, (300, 300))


Дисторсия/distortion

Дисторсия представляет собой появление выпуклости за счёт особенностей объектива камеры. Иначе её называют эффектом “рыбьего глаза”.

Андисторсия/undistortion

Андисторсия в свою очередь - это устранение дисторсии.

OpenCV: андисторсия

  1. В OpenCV для выполнения андисторсии используется изображение с шахматной доской и ряд функций:
  2. Для получения координат точек на шахматной доске используется функция cv2.findChessboardCorners.
  3. Для получения параметров колибровки используется функция cv2.calibrateCamera.
  4. Для получения оптимальной матрицы используется функция cv2.getOptimalNewCameraMatrix.
  5. Для андисторсии по полученным матрицам и параметрам используется функция cv2.undistort.


Практическое задание:
Применить вращение к 3-ем изображениям. 
Применить смещение к 3-ем изображениям.
Применить сдвиг к 3-ем изображениям.


Домашнее задание:
Применить к изображению 3 аффинных преобразования
Применить к изображению 3 комбинации из 2 аффинных преобразований

Новогодняя домашняя работа:

Решение 1 задачи выкладывать в соответствующую номеру лекции папку

Решение 2-4 задач выкладывать в папку:

  1. Сделать все, что не сделано ранее
  2. Применить вручную ядро свертки на изображение . Предоставить отчет по решению.
  3. Запрограммировать применение ядра свертки на изображение (2 задача). Предоставить код решения.
  4. Постараться улучшить качество 3-ех изображений (можно взять 2 изображения из материалов, и одно свое изображение). Предоставить изображения до-после + код для каждого изображения.


Завершить и продолжить  
Обсуждение

0 Комментарии