我有两张图片,其中一张是原始图片,第二张是转换图片。
我必须找出使用3x3变换矩阵旋转了多少度转换图像。另外,我需要找到从原点翻译的距离。
两个图像都被灰度化并保存在矩阵变量中。它们的大小相同[350 500]
。
我找到了一些像this这样的讲义。
讲义说我应该使用以下矩阵公式进行轮换:
对于翻译矩阵,给出了公式:
一切都很好。但有两个问题:
x'
,y'
值,但我已经获得了x
,x'
,y
,y'
个值。我需要找到旋转角度(theta)和t
x
和t
y
。x
,x'
,y
,y'
的等效性。我有以下代码:
rotationMatrix = [ cos(theta) sin(theta) 0 ; ...
-sin(theta) cos(theta) 0 ; ...
0 0 1];
translationMatrix = [ 1 0 tx; ...
0 1 ty; ...
0 0 1];
但正如您所看到的,tx,ty,theta变量在使用之前未定义。如何计算theta
,t
x
和t
y
?
PS:禁止使用图像处理工具箱功能。
答案 0 :(得分:7)
这基本上是homography recovery问题。您正在做的是在一个图像中给出坐标,在另一个图像中给出相应的坐标,您正在尝试恢复用于将点从一个图像扭曲到另一个图像的组合平移和旋转矩阵。 / p>
通过将两个矩阵相乘,您基本上可以将旋转和平移组合成单个矩阵。乘法只是将两个操作合成在一起。你会得到:
H = [cos(theta) -sin(theta) tx]
[sin(theta) cos(theta) ty]
[ 0 0 1]
这背后的想法是通过最小化每对点之间的最小二乘误差来找到参数。
基本上,您想要找到的是以下关系:
xi_after = H*xi_before
H
是将坐标从一个图像映射到另一个图像所需的组合旋转和平移矩阵。 H
也是一个3 x 3矩阵,并且知道右下方(第3行,第3列)为1,它使事情变得更容易。此外,假设您的点位于增强坐标系中,我们基本上希望找到从第一张图像(x_i, y_i)
到另一张(x_i', y_i')
的每对坐标的这种关系:
[p_i*x_i'] [h11 h12 h13] [x_i]
[p_i*y_i'] = [h21 h22 h23] * [y_i]
[ p_i ] [h31 h32 1 ] [ 1 ]
p_i
的比例是考虑单应缩放和消失点。让我们执行这个等式的矩阵向量乘法。我们可以忽略第3个元素,因为它对我们没用(现在):
p_i*x_i' = h11*x_i + h12*y_i + h13
p_i*y_i' = h21*x_i + h22*y_i + h23
现在让我们来看看第3个元素。我们知道p_i = h31*x_i + h32*y_i + 1
。因此,将p_i
替换为每个等式,并重新排列以求解x_i'
和y_i'
,我们得到:
x_i' = h11*x_i + h12*y_i + h13 - h31*x_i*x_i' - h32*y_i*x_i'
y_i' = h21*x_i + h22*y_i + h23 - h31*x_i*y_i' - h32*y_i*y_i'
现在你所拥有的是每个独特点对的两个方程式。我们现在能做的是建立一个过度确定的方程组。拿出每一对并从中构建两个方程式。然后你将它变成矩阵形式,即:
啊= b
A
将是使用来自第一个图像的坐标从每组方程构建的系数矩阵,b
将是第二个图像的每对点和{{ 1}}将是您要解决的参数。最终,你终于解决了以矩阵形式重新表述的线性方程组:
你可以求解可以通过最小二乘法执行的向量h
。在MATLAB中,您可以通过以下方式完成此操作:
h
给你的旁注:如果图像之间的移动真的只是旋转和平移,那么在我们求解参数后h31和h32都将为零。但是,我总是喜欢彻底,所以无论如何我会解决h31和h32。
注意:此方法仅在您具有至少 4 唯一点数时才有效。因为要解决8个参数,并且每个点有2个方程,h = A \ b;
必须至少具有8的等级才能使系统保持一致(如果你想在一些线性代数术语中使用循环)。如果你的积分少于4分,你将无法解决这个问题。
如果您需要一些MATLAB代码,我们假设您的积分存储在A
和sourcePoints
中。 targetPoints
来自第一张图片,sourcePoints
来自第二张图片。显然,两个图像之间应该有相同数量的点。假设targetPoints
和sourcePoints
都存储为targetPoints
矩阵。第一列包含M x 2
个坐标,而第二列包含x
个坐标。
y
完成后,您将拥有一个组合的旋转和平移矩阵。如果您想要numPoints = size(sourcePoints, 1);
%// Cast data to double to be sure
sourcePoints = double(sourcePoints);
targetPoints = double(targetPoints);
%//Extract relevant data
xSource = sourcePoints(:,1);
ySource = sourcePoints(:,2);
xTarget = targetPoints(:,1);
yTarget = targetPoints(:,2);
%//Create helper vectors
vec0 = zeros(numPoints, 1);
vec1 = ones(numPoints, 1);
xSourcexTarget = -xSource.*xTarget;
ySourcexTarget = -ySource.*xTarget;
xSourceyTarget = -xSource.*yTarget;
ySourceyTarget = -ySource.*yTarget;
%//Build matrix
A = [xSource ySource vec1 vec0 vec0 vec0 xSourcexTarget ySourcexTarget; ...
vec0 vec0 vec0 xSource ySource vec1 xSourceyTarget ySourceyTarget];
%//Build RHS vector
b = [xTarget; yTarget];
%//Solve homography by least squares
h = A \ b;
%// Reshape to a 3 x 3 matrix (optional)
%// Must transpose as reshape is performed
%// in column major format
h(9) = 1; %// Add in that h33 is 1 before we reshape
hmatrix = reshape(h, 3, 3)';
和x
翻译,只需在y
中选择第3列第1行和第2行。但是,我们也可以使用hmatrix
本身的向量,因此h13将是元素3,而h23将是元素编号6.如果你想要旋转角度,只需将相应的反三角函数用于行对于h
向量,这将是元素1,2,4和5.根据您选择的元素,将会有一些不一致,因为这是通过最小二乘解决的。获得良好整体角度的一种方法可能是找到所有4个元素的角度然后做某种平均值。无论哪种方式,这都是一个很好的起点。
我不久前通过Leow Wee Kheng的计算机视觉课程学习了单应性。我告诉你的是基于他的幻灯片:http://www.comp.nus.edu.sg/~cs4243/lecture/camera.pdf。如果您想知道我从哪里取出这些材料,请查看幻灯片30-32。但是,我自己编写的MATLAB代码:)