这本质上是一个
单应性恢复问题。你所做的是,在一张图像中给出坐标,以及在另一张图像中对应的坐标,你正在尝试恢复用于将点从一个图像扭曲到另一个图像的组合平移和旋转矩阵。
您可以将旋转和平移组合成一个单矩阵,方法是将两个矩阵相乘。乘法就是将两个操作组合在一起。然后您会得到:
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
的比例尺是为了考虑单应性缩放和消失点。让我们执行此方程的矩阵向量乘法。我们可以忽略第三个元素,因为它对我们没有用(目前):
p_i*x_i' = h11*x_i + h12*y_i + h13
p_i*y_i' = h21*x_i + h22*y_i + h23
现在让我们来看第三个元素。我们知道。因此,将代入每个方程中,并重新排列以解出和,我们得到:
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'
现在你拥有的是每对唯一点的两个方程式。现在我们可以建立一个超定的方程组。对于每一对点,建立两个方程式。然后把它们放入矩阵形式中,即:
Ah = b
A将是一个系数矩阵,由第一幅图像的坐标构建而成,b将是第二幅图像的每一对点,h将是你要解决的参数。最终,你将解决这个线性方程组,以矩阵形式重新表述:
![enter image description here](https://istack.dev59.com/j66jX.webp)
你需要通过最小二乘法求解向量
h
。在MATLAB中,你可以这样做:
h = A \ b
给你的一个旁注:如果图像之间的移动确实只是旋转和平移,那么在解决参数后,h31和h32都将为零。然而,我总是喜欢做到周全,所以我仍然会解决h31和h32。
NB:此方法仅在您至少拥有4个唯一点对时才有效。因为要解决8个参数,并且每个点有2个方程式,A
必须至少具有8的秩,以便系统保持一致(如果您想在循环中加入一些线性代数术语)。如果您少于4个点,则无法解决此问题。
如果您需要一些MATLAB代码,请假设您的点存储在
sourcePoints
和
targetPoints
中。
sourcePoints
来自第一张图像,
targetPoints
来自第二张图像。显然,在两个图像之间应该有相同数量的点。假定
sourcePoints
和
targetPoints
都存储为
M x 2
矩阵。第一列包含您的
x
坐标,而第二列包含您的
y
坐标。
numPoints = size(sourcePoints, 1);
sourcePoints = double(sourcePoints);
targetPoints = double(targetPoints);
xSource = sourcePoints(:,1);
ySource = sourcePoints(:,2);
xTarget = targetPoints(:,1);
yTarget = targetPoints(:,2);
vec0 = zeros(numPoints, 1);
vec1 = ones(numPoints, 1);
xSourcexTarget = -xSource.*xTarget;
ySourcexTarget = -ySource.*xTarget;
xSourceyTarget = -xSource.*yTarget;
ySourceyTarget = -ySource.*yTarget;
A = [xSource ySource vec1 vec0 vec0 vec0 xSourcexTarget ySourcexTarget; ...
vec0 vec0 vec0 xSource ySource vec1 xSourceyTarget ySourceyTarget];
b = [xTarget; yTarget];
h = A \ b;
h(9) = 1;
hmatrix = reshape(h, 3, 3)';
一旦完成,您将得到一个合并的旋转和平移矩阵。如果您想要
x
和
y
的平移,则只需在
hmatrix
中选择第 3 列,第 1 和 2 行即可。然而,我们也可以使用
h
向量本身进行计算,因此 h13 将是第 3 个元素,h23 将是第 6 个元素。如果您想要旋转角度,则只需对第 1、2 行和第 1、2 列进行逆三角函数运算。对于
h
向量,这将是元素 1、2、4 和 5。由于这是最小二乘法求解的结果,因此选择哪些元素会有一些不一致。也许获取所有 4 个元素的角度然后做某种平均可能是获得良好整体角度的一种方式。无论如何,这是一个很好的起点。
参考资料
我之前通过Leow Wee Kheng的计算机视觉课程了解了单应性矩阵。我告诉你的内容是基于他的幻灯片http://www.comp.nus.edu.sg/~cs4243/lecture/camera.pdf。如果您想知道我从哪里获取这些材料,请查看第30-32张幻灯片。然而,MATLAB代码是我自己编写的 :)
M x 2
矩阵。第一列是你的x
值,第二列是你的y
值。我再次编辑了我的帖子以反映这一点。 - rayryengF = m * a;
。我知道F
,我知道a
,我需要找出m
。所有资料都告诉我要找到F
,但我需要找到m
。希望我能用我的蹩脚英语表达清楚我的问题。 - zkanocam
的。我不确定你还在哪里困惑。如果你完全按照我写的 MATLAB 代码,并将其调整到我所说的M x 2
矩阵上,你应该能够通过最小二乘法恢复变换矩阵。 - rayryengH = [-0.6433; -0.0509; 117.4432; -0.6699; 0.0484; 106.9079; -0.0059; 0.0003]
。为什么H(9)
是0而不是1? - zkanocaH(9)
为1,因此没有在矩阵中建模。你正在读的实际上是H(8) = 0.0003
!你还可以看到H(7) = -0.0059
。理论上这两个值应该都是零,但这是最小二乘法的缺点。它不能完全消除误差!你还可以看到你的x
和y
偏移分别为117.4432
和106.9079
。另外,使用H(1), H(2), H(4), H(5)
之一,并将其相应的反三角函数应用于获取你的角度。 - rayryeng