Преобразование изображения с использованием углов поворота-поворота (корректировка изображения)
Я работаю над приложением, где мне нужно исправить изображение, взятое с платформы мобильной камеры. Платформа измеряет углы поворота, высоты тона и угла поворота, и я хочу, чтобы это выглядело так, будто изображение берется из непосредственно выше, каким-то образом преобразуется из этой информации.
Другими словами, мне нужен идеальный квадрат, лежащий на земле, сфотографированный издалека с некоторой ориентацией камеры, который должен быть преобразован, чтобы квадрат был совершенно симметричным впоследствии.
Я пытаюсь сделать это через 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) Примените обратное преобразование гомограхи к вашему изображению.
Ответ 3
Вам нужно оценить гомографию. Для готового решения Matlab см. Функцию vgg_H_from_x_lin.m
из http://www.robots.ox.ac.uk/~vgg/hzbook/code/.
Для теории вникните в учебник Computer Vision, например, свободно доступный http://szeliski.org/Book/ или в главе 3 http://programmingcomputervision.com/downloads/ProgrammingComputerVision_CCdraft.pdf
Ответ 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
Есть ли способ восстановить углы сравнения начальных и конечных изображений? Из приведенного выше примера я понял, что углы были также входными данными для процесса.