OpenCV Разложить матрицу проекции Неправильное направление угла Эйлера? - PullRequest
0 голосов
/ 24 января 2019

Ситуация: Я пытаюсь оценить позу головы. Я откалибровал свою камеру и получил матрицу камеры. У меня есть 3D-модель, которая соответствует точкам изображения. Я нахожу позу и получаю векторы вращения и перевода:

_, rvec, tvec = cv2.solvePnP(model_points, image_points, camera_matrix, dist_coeffs, flags=...)

Затем я получаю матрицу вращения из вектора вращения:

rotation_matrix, _ = cv2.Rodrigues(rvec)

Теперь я решил взглянуть на углы Эйлера. Я создаю матрицу проекции следующим образом:

projection_matrix = camera_matrix.dot(np.hstack((rotation_matrix, tvec)))

Итак, моя матрица проекции теперь 3х4. Затем я получаю углы Эйлера:

angles = cv2.decomposeProjectionMatrix(projection_matrix)[-1]

Проблема: Я нашел альтернативный способ получить углы Эйлера в этом посте ( Python Opencv SolvePnP выдает неправильный вектор перевода ), который, по мнению автора, должен давать тот же результат как мои углы (как это было для них):

 y_rot = math.asin(rotation_matrix[2][0])
 x_rot = math.acos(rotation_matrix[2][2]/math.cos(y_rot))
 z_rot = math.acos(rotation_matrix[0][0]/math.cos(y_rot))
 y_rot_angle = y_rot *(180/3.1415)
 x_rot_angle = x_rot *(180/3.1415)
 z_rot_angle = z_rot *(180/3.1415)

Что дают мои углы от разложенной проекционной матрицы:

[164.17979619 19.45087415 1.95279565]

Что дает другое решение:

[164.18463841290048, -19.451447820154847, 1.9528532437807946]

Скалярные значения одинаковы, но угол поворота по оси Y имеет другое направление. Мне было интересно - может, я что-то не так понял?

1 Ответ

0 голосов
/ 24 января 2019

Я не знаю точно, какая перестановка является вашей реализацией для получения eulerangles из матрицы, но она отличается от той, которую использует декомпозицияProjectionMatrix.это причина разных углов.

Как уже говорилось, углы Эйлера всегда зависят от порядка.Есть 12 различных перестановок.См. Углы Эйлера для получения дополнительной информации.

декомпозиция ProjectionMatrix из opencv использует порядок "XYZ" для своего представления угла Эйлера.

существуют различные библиотеки вращенияна пипи.Я использую для этого примера transforms3d.Я устанавливаю входные параметры вручную и матрицу вращения с помощью функции euler2mat пакета transforms3d.Я создаю матрицу вращения с XYZ-соглашением, например, угол крена (X): 90 °, шаг (Y): 45 °, рыскание (X): 180 °

from transforms3d import euler
from math import pi,radians
rotation_matrix = euler.euler2mat(radians(90), radians(45), 
    radians(180), 'sxyz')
tvec = np.zeros(3).reshape(1,3).T
camera_matrix = np.array([[1500,0,320],[0,1500,256],[0,0,1]])
projection_matrix = camera_matrix.dot(np.hstack((rotation_matrix, tvec)))
rot = cv2.decomposeProjectionMatrix(projection_matrix)

вращение_matrix (вход) и поворот[1] (выходные данные) одинаковы (но только с правильным порядком эйлера "sxyz"):

array([[-7.07106781e-01, -7.07106781e-01,  7.91668771e-17],
   [ 8.65956056e-17,  2.53632657e-17,  1.00000000e+00],
   [-7.07106781e-01,  7.07106781e-01,  4.32978028e-17]])

rot [-1]:

[[90.         ]
 [ 45.        ]
 [ 180.        ]]

естьеще несколько подводных камней с 3d вращениями.Например,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...