Одна статья для понимания принципа аффинного преобразования и кода реализации Python.

компьютерное зрение
Одна статья для понимания принципа аффинного преобразования и кода реализации Python.

Аффинное преобразование изображений часто используется для улучшения данных компьютерного зрения. Аффинное преобразование, которое мы говорим, относится к преобразованию твердого тела, то есть две параллельные линии остаются параллельными после аффинного преобразования, в то время как преобразование перспективы не является преобразованием твердого тела. этой статьи. Обычно любое сочетание флипа, перемещения, поворота, масштабирования и шахматного преобразования является аффинным преобразованием. Аффинное преобразование можно выразить следующей формулой:

Угол поворота действует на a b d e, масштаб действует на a e, преобразование сдвига действует на b d, а смещение действует на c f, как показано на следующем рисунке:

1. Подробное объяснение cv2.getRotationMatrix2D

Функция cv2.getRotationMatrix2D opencv может получить матрицу преобразования вращения. Введите координаты центральной точки (centerX, centerY), угол поворота θ и коэффициент масштабирования 1 и задайте матрицу преобразования M:

[cosθsinθ(1cosθ)*centerX+sinθ*centerYsinθcosθ(1cosθ)*centerY+sinθ*centerX001]\left[ \begin{matrix} cosθ & -sinθ & (1 - cosθ) * centerX + sinθ * centerY \\ sinθ & cosθ & (1 - cosθ) * centerY + sinθ * centerX \\ 0 & 0 & 1 \end {матрица} \справа]

Как управляется эта матрица аффинного преобразования? Матрицу аффинного преобразования относительно легко рассуждать. Давайте сначала повернем точку на основе начала координат, как показано ниже, повернем точку V1 против часовой стрелки до точек V2, коэффициент масштабирования Сначала примем 1.

Угол a между линией, соединяющей точку V1 и начало координат, и горизонтальной линией равен a, а угол между линией, соединяющей точку V2, начало координат и горизонтальную линию, равен b=a+θ. Вычислите матрицу преобразования вращения: Напишите V1=(x1, y1), V2=(x2, y2)

image.png

Но обычно мы будем вращаться на основе центральной точки, если нам нужно повернуть вокруг какой-либо точки (tx, ty), мы можем
1. Сначала переместите точку вращения в начало координат
2. Затем выполните описанную выше операцию вращения.
3. Нажмите операцию, обратную 1, чтобы панорамировать назад.
Вы можете получить матрицу преобразования точкой, чтобы вращаться вокруг любой точки:

image.png

2. Варпафинная операция

2.1 Получение матрицы M для аффинного преобразования

Получите матрицу преобразования M и выполните преобразование M в каждой точке изображения, чтобы получить повернутое изображение.Этот шаг можно получить с помощью warpAffine из opencv. Однако из-за вышеперечисленных операций большое изображение потеряет информацию после поворота, как показано на следующем рисунке:

2.2 Разверните холст

Когда размер холста останется прежним, некоторые изображения будут превышены и не будут отображаться полностью, поэтому нам нужно расширить холст до: Новая высота состоит из двух синих линий на картинке:new_H=int(w∗abs(sin(radias(angle)))+h∗abs(cos(radias(angle))))

Новая ширина образована двумя красными линиями на картинке:new_W=int(h∗fabs(sin(radians(angle)))+w∗fabs(cos(radians(angle))))

Новое расширение холста основано на расширении верхнего левого угла исходного изображения. Итак, на матрице преобразования M мы можем настроить параметры перевода:

M[0,2]+=(new_W−w)/2

M[1,2]+=(new_H−h)/2

3. Код аффинного преобразования изображения

Говорить дешево, покажите мне код. Сразу к коду:

def affine_transform(image, angle, scale=1.0):
    h, w = image.shape[:2]
    center_x, center_y = width // 2, height // 2
    
    M = cv2.getRotationMatrix2D((center_x, center_y), angle, scale)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    
    new_h = int(h * cos + w * sin)
    new_w = int(h * sin + w * cos)
    M[0, 2] += (new_w − w) / 2
    M[0, 1] += (new_h − h) / 2
    
    new_image = cv2.warpAffine(image, M, (new_w, new_h))
    return new_image

4. Код одноточечного аффинного преобразования

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

def affine_points(points, center_x, center_y, h, w, scale=1.0):
    points = np.array(points, dtype=np.float32)
    points = np.hstack((points, np.ones((points.shape[0], 1))))
    
    M = cv2.getRotationMatrix2D((center_x, center_y), angle, scale)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    
    new_h = int(h * cos + w * sin)
    new_w = int(h * sin + w * cos)
    M[0, 2] += (new_w − w) / 2
    M[0, 1] += (new_h − h) / 2
    
    new_points = np.dot(M, points.T).T
    return new_points