Преобразование изображения с использованием углов поворота-поворота (корректировка изображения)

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

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

Я пытаюсь сделать это через OpenCV (С++) и 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);

Что дает результат:

Image rotated 10 degrees about the Z-image axis

Если я попытаюсь повернуть изображение на ту же величину относительно осей X или Y, я получаю такие результаты:

R = R_z(10)*R_y(0)*R_x(10);

Image rotated 10 degrees about the X-image axis

Однако, если я поворачиваю на 10 градусов, делясь на какое-то огромное количество, он начинает выглядеть нормально. Но опять же, это результат, который не имеет ценности для исследований, что так всегда:

R = R_z(10)*R_y(0)*R_x(10/1000);

Image rotated 10/1000 degrees about the X-image axis

Может кто-нибудь, пожалуйста, помогите мне понять, почему вращение вокруг осей 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

Исходное изображение:

enter image description here

Измерения платформы камеры в кадре координат BODY:

Roll:     -10
Pitch:    -30
Yaw:      166 (angular deviation from north)

Из того, что я понимаю, угол Yaw не имеет прямого отношения к трансформации. Возможно, я ошибаюсь.

Дополнительная информация:

Я хотел бы указать, что среда, в которой будет использоваться установка, не содержит строк (океаническая фотография), которые могут быть надежно использованы в качестве ссылки (горизонт обычно не будет на картинке). Также квадрат в исходном изображении просто используется в качестве меры для проверки правильности преобразования и не будет присутствовать в реальном сценарии.

Ответы

Ответ 1

Итак, это то, что я закончил: я понял, что, если вы на самом деле не имеете дело с 3D-изображениями, выпрямление перспективы фотографии - это 2D-операция. Имея это в виду, я заменил значения оси z матрицы преобразования на нули и единицы и применил двумерное Аффинное преобразование к изображению.

Вращение исходного изображения (см. начальное сообщение) с измеренным значением Roll = -10 и Pitch = -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    ] 

Это подразумевает поворот платформы камеры к ориентации виртуальной камеры, где камера расположена над сценой, направленной вниз. Обратите внимание на значения, используемые для рулона и высоты тона в приведенной выше матрице.

Кроме того, если вы поворачиваете изображение так, чтобы оно выровнялось с заголовком платформы, можно было бы добавить вращение вокруг оси 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, выглядит следующим образом:

enter image description here

Полный код для этого преобразования, как показано выше, был:

% 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

Спасибо за поддержку, надеюсь, это кому-то поможет!

Ответ 2

Я думаю, что вы можете получить трансформацию таким образом:

1) Пусть у вас есть четыре 3d-точки A (-1, -1,0), B (1, -1,0), C (1,1,0) и D (-1,1,0). Вы можете взять любые 4 noncollinear точки. Они не связаны с изображением.

2) У вас есть матрица преобразования, поэтому вы можете установить свою камеру путем умножения точек на координаты матрицы преобразования. И вы получите 3d-координаты относительно положения/направления камеры.

3) Вам нужно получить проекцию ваших очков на плоскость экрана. Самый простой способ - использовать ортографическую проекцию (просто игнорировать координату глубины). На этом этапе у вас есть 2D проекции преобразованных точек.

4) Когда у вас есть 2 набора координат 2D-точек (набор из шага 1 без 3-й координаты и набор из шага 3), вы можете вычислить матрицу гомографии стандартным образом.

5) Примените обратное преобразование гомограхи к вашему изображению.

Ответ 4

Возможно, мой ответ неверен из-за моего неправильного понимания параметров камеры, но мне было интересно, является ли Yaw/Pitch/Roll относительно позиции вашего объекта. Я использовал формулу общие вращения, а мой код ниже (функции вращения 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)

Результат:

enter image description here

Это означает, что вам по-прежнему нужна операция вращения, чтобы получить правильное выравнивание в вашем уме (но, вероятно, не обязательно правильное положение в уме камеры). Поэтому я меняю R_rot = inv(R_rot); на R_rot = inv(R_rot)*R_x(-5)*R_y(25)*R_z(180);, и теперь он дал мне:

enter image description here

Выглядит лучше, чем вы хотите. Спасибо.

Ответ 5

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