Преобразование изображения с использованием углов крена-тангажа-рыскания (выпрямление изображения)
Я работаю над приложением, где мне нужно исправить изображение, взятое с платформы мобильной камеры. Платформа измеряет углы крена, тангажа и рыскания, и я хочу, чтобы это выглядело так, как будто изображение взято непосредственно сверху, каким-то преобразованием из этой информации.
Я пытался сделать это через OpenCV(C++) и Matlab, но мне кажется, что мне не хватает чего-то фундаментального о том, как это делается.
в Matlab я попробовал следующее:
%% Transform perspective
img = imread('my_favourite_image.jpg');
R = R_z(yaw_angle)*R_y(pitch_angle)*R_x(roll_angle);
tform = projective2d(R);
outputImage = imwarp(img,tform);
figure(1), imshow(outputImage);
где R_z/y / x-стандартные вращательные матрицы (реализованные с градусами).
для некоторого рыскания-вращения все работает просто отлично:
R = R_z(10)*R_y(0)*R_x(0);
что дает результат:
если я попытаюсь повернуть изображение на ту же сумму о X - или Y-осях, я получаю такие результаты:
R = R_z(10)*R_y(0)*R_x(10);
однако, если я вращаюсь на 10 градусов, разделенный на какое-то огромное число, он начинает выглядеть нормально. Но опять же, это результат, который не имеет никакого исследовательского значения, что так всегда:
R = R_z(10)*R_y(0)*R_x(10/1000);
может кто - нибудь, пожалуйста, помогите мне понять, почему вращение вокруг оси X или Y делает преобразование диким? Есть ли способ решить эту проблему без деление на случайное число и другие фокусы? Может быть, это можно решить с помощью каких-то параметров Эйлера? Любая помощь будет высоко ценится!
обновление: полная настройка и измерения
для полноты был добавлен полный тестовый код и начальное изображение, а также углы платформы Эйлера:
код:
%% Transform perspective
function [] = main()
img = imread('some_image.jpg');
R = R_z(0)*R_y(0)*R_x(10);
tform = projective2d(R);
outputImage = imwarp(img,tform);
figure(1), imshow(outputImage);
end
%% Matrix for Yaw-rotation about the Z-axis
function [R] = R_z(psi)
R = [cosd(psi) -sind(psi) 0;
sind(psi) cosd(psi) 0;
0 0 1];
end
%% Matrix for Pitch-rotation about the Y-axis
function [R] = R_y(theta)
R = [cosd(theta) 0 sind(theta);
0 1 0 ;
-sind(theta) 0 cosd(theta) ];
end
%% Matrix for Roll-rotation about the X-axis
function [R] = R_x(phi)
R = [1 0 0;
0 cosd(phi) -sind(phi);
0 sind(phi) cosd(phi)];
end
исходное изображение:
камера измерения платформы в координатной рамке кузова:
Roll: -10
Pitch: -30
Yaw: 166 (angular deviation from north)
из того, что я понимаю, угол рыскания не имеет прямого отношения к преобразованию. Однако я могу ошибаться.
дополнительная информация:
Я хотел бы указать, что среда, в которой будет использоваться настройка, не содержит линий (океаническая фотография), которые могут надежно использоваться в качестве ссылки (горизонт обычно не будет на картинке). Также квадрат в начальном изображение просто используется в качестве меры, чтобы увидеть, правильно ли преобразование, и не будет там в реальном сценарии.
4 ответов
Итак, это то, что я закончил: я понял, что если вы на самом деле не имеете дело с 3D-изображениями, исправление перспективы фотографии-это 2D-операция. Имея это в виду, Я заменил значения Z-оси матрицы преобразования нулями и единицами и применил 2D аффинное преобразование к изображению.
вращение исходного изображения (см. начальный пост) с измеренным креном = -10 и шагом = -30 было сделано следующим образом:
R_rotation = R_y(-60)*R_x(10);
R_2d = [ R_rot(1,1) R_rot(1,2) 0;
R_rot(2,1) R_rot(2,2) 0;
0 0 1 ]
Это подразумевает поворот платформы камеры к ориентации виртуальной камеры, где камера расположена над сценой, указывая прямо вниз. Обратите внимание на значения, используемые для roll и pitch в приведенной выше матрице.
кроме того, при повороте изображения так, чтобы оно было выровнено с заголовком платформы, может быть добавлено вращение вокруг оси z, давая:
R_rotation = R_y(-60)*R_x(10)*R_z(some_heading);
R_2d = [ R_rot(1,1) R_rot(1,2) 0;
R_rot(2,1) R_rot(2,2) 0;
0 0 1 ]
обратите внимание, что это не изменяет фактическое изображение - оно только вращает его.
в результате исходное изображение повернутый вокруг осей Y и X выглядит так:
полный код для этого преобразования, как показано выше, было:
% Load image
img = imread('initial_image.jpg');
% Full rotation matrix. Z-axis included, but not used.
R_rot = R_y(-60)*R_x(10)*R_z(0);
% Strip the values related to the Z-axis from R_rot
R_2d = [ R_rot(1,1) R_rot(1,2) 0;
R_rot(2,1) R_rot(2,2) 0;
0 0 1 ];
% Generate transformation matrix, and warp (matlab syntax)
tform = affine2d(R_2d);
outputImage = imwarp(img,tform);
% Display image
figure(1), imshow(outputImage);
%*** Rotation Matrix Functions ***%
%% Matrix for Yaw-rotation about the Z-axis
function [R] = R_z(psi)
R = [cosd(psi) -sind(psi) 0;
sind(psi) cosd(psi) 0;
0 0 1];
end
%% Matrix for Pitch-rotation about the Y-axis
function [R] = R_y(theta)
R = [cosd(theta) 0 sind(theta);
0 1 0 ;
-sind(theta) 0 cosd(theta) ];
end
%% Matrix for Roll-rotation about the X-axis
function [R] = R_x(phi)
R = [1 0 0;
0 cosd(phi) -sind(phi);
0 sind(phi) cosd(phi)];
end
Спасибо за поддержку, я надеюсь, что это помогает кто-то!
Я думаю, вы можете получить преобразование таким образом:
1) пусть у вас есть четыре 3d-точки A(-1,-1,0), B(1,-1,0), C(1,1,0) и D(-1,1,0). Можно взять любые 4 неколлинеарные точки. Они не связаны с образом.
2) у вас есть матрица преобразования, поэтому вы можете установить камеру, умножая координаты точек на матрицу преобразования. И вы получите 3d-координаты относительно положения/направления камеры.
3) вам нужно получить проекцию ваших точек на плоскость экрана. Самый простой способ - использовать ортографическую проекцию (просто игнорировать координату глубины). На этом этапе у вас есть 2D-проекции преобразованных точек.
4) Как только у вас есть 2 набора 2D-координат точек (набор из Шага 1 Без 3-й координаты и набор из Шага 3), Вы можете вычислить матрицу гомографии стандартным способом.
5) применить обратное преобразование homograhy в ваш образ.
вам нужно оценить гомографию. Готовое решение Matlab см. В разделе функция vgg_H_from_x_lin.m
от http://www.robots.ox.ac.uk / ~vgg/hzbook / code/ .
для теории копаться в учебник компьютерного зрения, например, тот, который доступен свободно на http://szeliski.org/Book/ или в главе 3http://programmingcomputervision.com/downloads/ProgrammingComputerVision_CCdraft.pdf
возможно, мой ответ неверен из-за моего неправильного понимания параметров камеры, но мне было интересно, является ли рыскание/шаг/крен относительно положения вашего объекта. Я использовал формулу общие поворотов, и мой код ниже (функций вращения R_x
, R_y
и R_z
были скопированы с ваших, я не вставлял их сюда)
close all
file='http://i.stack.imgur.com/m5e01.jpg'; % original image
I=imread(file);
R_rot = R_x(-10)*R_y(-30)*R_z(166);
R_rot = inv(R_rot);
R_2d = [ R_rot(1,1) R_rot(1,2) 0;
R_rot(2,1) R_rot(2,2) 0;
0 0 1 ];
T = maketform('affine',R_2d);
transformedI = imtransform(I,T);
figure, imshow(I), figure, imshow(transformedI)
результат:
это означает, что вам все еще нужны некоторые операция вращения, чтобы получить "правильное" выравнивание в вашем уме (но, вероятно, не нужно правильное положение в уме камеры).
Поэтому я меняюсь R_rot = inv(R_rot);
до R_rot = inv(R_rot)*R_x(-5)*R_y(25)*R_z(180);
, и теперь он дал мне:
выглядит лучше, как то, что вы хотите. Спасибо.