матрица вращения в openCV

Я создаю матрицу вращения в python следующим образом:

import numpy as np
def make_rot(angle):
    cost = np.cos(np.deg2rad(angle))
    sint = np.sin(np.deg2rad(angle))
    rot = np.array([[cost, -sint, 0],
                   [sint, cost, 0],
                   [0, 0, 1]])
    return rot

Это определено на странице википедии здесь: http://en.wikipedia.org/wiki/Rotation_matrix

Я запускаю его с параметром угла как 45 градусов и получаю что-то вроде:

[[ 0.70710678 -0.70710678  0.        ]
 [ 0.70710678  0.70710678  0.        ]
 [ 0.          0.          1.        ]]

Теперь я использую OpenCV getRotationMatrix2D API следующим образом:

import cv2
M = cv2.getRotationMatrix2D((0, 0), 45, 1)

Матрица, которую я получаю, является обратной матрицей (транспонированная, поскольку это матрица вращения). Результат такой:

[[ 0.70710678  0.70710678  0.        ]
 [-0.70710678  0.70710678  0.        ]]

Как видите, все наоборот. Я не нашел в документации OpenCV ничего, что говорило бы об этом поведении.

Теперь я могу использовать эту матрицу в OpenCV и skimage для преобразования изображения следующим образом:

# openCV
M = cv2.getRotationMatrix2D((0, 0), 45, 1)
dst = cv2.warpAffine(image2, M, (coumns, rows))

# skimage
from skimage import transform as tf
tform = tf.AffineTransform(matrix=make_rot(45))
dst = tf.warp(image_2, tform)

Удивительно то, что результат от использования моей матрицы и матрицы OpenCV одинаковый.

У меня вопрос: почему OpenCV работает с обратным преобразованием? Мне интересно, это то, что они не упоминают в документации, или я как-то использую это неправильно.


person Luca    schedule 25.01.2015    source источник
comment
Должно зависеть от того, вращается ли он по часовой стрелке или против часовой стрелки ... openCV doc говорит, что он использует [cos sin; -sin cos] для вращения против часовой стрелки, но я не уверен, правильно ли это. Просто попробуйте, по часовой стрелке или против часовой стрелки, путем деформации или умножения точек; )   -  person Micka    schedule 26.01.2015
comment
Обратите внимание на эту часть википедии: примеры в этой статье относятся к активному вращению векторов против часовой стрелки в правой системе координат путем предварительного умножения. Если какой-либо из них изменяется (например, вращающиеся оси вместо векторов, т.е. пассивное преобразование), то следует использовать инверсию матрицы примера, которая точно совпадает с ее транспонированием. Так может быть, происхождение изображения (например, верхний левый или нижний левый) отличается в sci-kit и openCV?   -  person Micka    schedule 26.01.2015
comment
Это должно быть так. Я займусь расследованием.   -  person Luca    schedule 26.01.2015
comment
Получается, что функция деформации скимейджа ожидает обратного преобразования (от выходного изображения к входному). Я не уверен, почему это так. Это не проблема для аффинных преобразований, поскольку они биективны. Однако лучше использовать преобразование из входных координат в ›выходных координат.   -  person Luca    schedule 26.01.2015
comment
Чтобы предотвратить появление дыр в выходном изображении, лучше использовать обратное преобразование.   -  person lanpa    schedule 26.01.2015
comment
Инверсия обычно используется для деформации, чтобы получить значение для каждого дискретного пикселя целевого изображения, как уже говорилось в ланпе. openCV будет вычислять обратное во время деформации, если вы не установите флаг WARP_INVERSE_MAP. Если вы установите флаг WARP_INVERSE_MAP, тогда предполагается, что вы уже предоставили инверсию.   -  person Micka    schedule 26.01.2015
comment
Вы можете использовать skimage.transform.SimilarityTransform(angle=X) или просто skimage.transform.rotate(angle=X, resize=False)   -  person user2970139    schedule 27.01.2015


Ответы (1)


Я думаю, проблема в том, что в традиционной правой системе координат матрица вращения выглядит точно так же, как та, которую вы используете. В то время как в изображениях (а OpenCV работает с изображениями) начало координат находится в верхнем левом углу, ось X идет вправо (как обычно), но ось Y идет вниз, а не вверх, что означает, что система координат находится влево. -ручная и матрица вращения другая. Построим матрицу вращения в этой системе координат. Если обозначить A - линейное преобразование (в нашем случае поворот), то получим A (i) = (cos (угол), - sin (угол)), где i - базовый вектор, соответствующий оси x; A (j) = (sin (угол), cos (угол)), где j- - базовый вектор для оси y. Следовательно, матрица вращения выглядит точно так же, как в OpenCV: A (i) - ее первый столбец, A (j) n - второй.

person Khelina Fedorchuk    schedule 17.07.2018