3D-2D: PnP
PnP(perspective-n-Point) 是求解3D到2D点对运动的方法。 它描述了当我们知道 n n n个3D空间点以及它们的投影位置时候,如何估计相机所在位姿。 2D-2D的对极几何方法需要八个或八个以上的点对(以八点法为例),且存在着初始化、纯旋转和尺度的问题。如果两张图像中,其中一张特征点的3D位置已知,那么最少只需三个点对(需要至少一个额外点验证结果)就可以估计相机运动。特征点的3D位置可以由三角化,或者由RGB-D相机的深度图确定。因此,在双目或RGB-D的视觉里程计中,我们可以直接使用 PnP估计相机运动。 而在单目视觉里程计中,必须先进行初始化,然后才能使用PnP。
PnP问题有很多种求解方法,例如用三对点估计位姿的P3P,直接线性变换(DLT),EPnP (EPnPEficient PnP), UPnP等等。此外,还能用非线性优化的方式,构建最小二乘问题并迭代求解,也就是万金油式的Bundle Adjustment。
(1) 直接线性变换(DLT)
考虑某个空间点
P
P
P, 它的齐次坐标
P
=
(
X
,
Y
,
Z
,
1
)
T
P=(X,Y,Z,1)^T
P=(X,Y,Z,1)T。在图像
I
1
I_1
I1中,投影到特征点
x
1
=
(
u
1
,
v
1
,
1
)
T
x_1=(u_1,v_1,1)^T
x1=(u1,v1,1)T(以归一化平面齐次坐标表示)。此时相机的位姿
R
,
t
R,t
R,t是未知的。与单应矩阵的求解类似,我们定义增广矩阵
[
R
∣
t
]
[R|t]
[R∣t]为一个3x4的矩阵,包含了旋转和平移信息,其展开信息如下:
s
(
u
1
v
1
1
)
=
(
t
1
t
2
t
3
t
4
t
5
t
6
t
7
t
8
t
9
t
10
t
11
t
12
)
(
X
Y
Z
1
)
s\biggl( \begin{matrix} u_1\\ v_1 \\ 1 \end{matrix} \biggl) = \biggl( \begin{aligned} &t_1 \quad t_2 \quad t_3 \quad t_4\\ &t_5 \quad t_6 \quad t_7 \quad t_8 \\ &t_9 \quad t_{10} \quad t_{11} \quad t_{12} \end{aligned} \biggl) \biggl( \begin{matrix} X \\ Y \\ Z\\ 1 \end{matrix} \biggl)
s(u1v11)=(t1t2t3t4t5t6t7t8t9t10t11t12)(XYZ1)
用最后一行把
s
s
s消去,得到两个约束:
u
1
=
t
1
X
+
t
2
Y
+
t
3
Z
+
t
4
t
9
X
+
t
10
Y
+
t
11
Z
+
t
12
u_1 = \frac{t_1X + t_2Y + t_3Z + t_4}{t_9X+t_{10}Y + t_{11}Z + t_{12}}
u1=t9X+t10Y+t11Z+t12t1X+t2Y+t3Z+t4
v 1 = t 5 X + t 6 Y + t 7 Z + t s t 9 X + t 10 Y + t 11 Z + t 12 v_1 = \frac{t_5X + t_6Y + t_7Z + t_s}{t_9X + t_{10}Y + t_{11}Z + t_{12}} v1=t9X+t10Y+t11Z+t12t5X+t6Y+t7Z+ts
为了简化表示,定义
T
T
T:
t
1
=
(
t
1
,
t
2
,
t
3
,
t
4
)
T
,
t
2
=
(
t
5
,
t
6
,
t
7
,
t
8
)
T
,
t
3
=
(
t
9
,
t
10
,
t
11
,
t
12
)
T
t_1=(t_1, t_2, t_3, t_4)^T, \quad t_2 = (t_5, t_6, t_7, t_8)^T, \quad t_3=(t_9,t_{10}, t_{11}, t_{12})^T
t1=(t1,t2,t3,t4)T,t2=(t5,t6,t7,t8)T,t3=(t9,t10,t11,t12)T
于是有:
t
1
T
P
−
t
3
T
P
u
1
=
0
t_1^TP - t_3^TPu_1 = 0
t1TP−t3TPu1=0
和
t 2 T P − t 3 T P v 1 = 0 t_2^TP -t_3^TPv_1 = 0 t2TP−t3TPv1=0
请注意
t
t
t是待求变量,可以看到每个特征点提供了两个关于
t
t
t的线性约束。假设一共有
N
N
N个特征点,可以列出线性方程:
由于 t t t一共有12维,因此最少通过六对匹配点,即可实现矩阵 T T T的线性求解。这种方法就是直接线性变换(Direct Linear Transform, DLT)。当匹配点大于六对时候,可以使用SVD等方法对超定方程求最小二乘解。
在DLT求解中,我们直接将 T T T矩阵看成了12个未知数,忽略了它们之间的联系。因为旋转矩阵 R ∈ S O ( 3 ) R \in SO(3) R∈SO(3),用DLT求出的解不一定满足该约束,它是一个一般矩阵。平移向量比较好办,它属于向量空间。对于旋转矩阵 R R R,我们必须针对DLT估计的 T T T的左边3x3的矩阵块,寻找一个最好的旋转矩阵对它进行近似。这可以由QR分解完成,相当于把结果从矩阵空间重新投影到 S E ( 3 ) SE(3) SE(3)流形上,转换成旋转和平移两部分。
(2) P3P
P3P是另一种解PnP的方法。它仅使用三对匹配点,对数据要求较少。
P3P需要利用给定的三个点的几何关系。它的输入数据为三对3D-2D匹配点。记3D点为A,B,C,2D点为a,b,c,其中小写字母代表的点为大写字母在相机成像平面上的投影。此外,P3P还需要使用一对验证点,以从可能的解出选出正确的那一 个(类似于对极几何情形)。记验证点对为D-d,相机光心为
O
O
O。我们知道的是A, B, C在世界坐标系中的坐标,而不是 在相机坐标系中的坐标。一旦3D点在相机坐标系 下的坐标能够算出, 我们就得到了3D-3D的对应点,把PnP问题转换为了ICP问题。 上图可以看出:
△
O
a
b
−
△
O
A
B
,
△
O
b
c
−
△
O
B
C
,
△
O
a
c
−
△
O
A
C
\triangle Oab - \triangle OAB, \quad \triangle Obc - \triangle OBC, \triangle Oac - \triangle OAC
△Oab−△OAB,△Obc−△OBC,△Oac−△OAC
考虑第一组
△
O
a
b
−
△
O
A
B
\triangle Oab - \triangle OAB
△Oab−△OAB的关系。利用余弦定理,可得:
O
A
2
+
O
B
2
−
2
O
A
⋅
O
B
⋅
c
o
s
⟨
a
,
b
⟩
=
A
B
2
OA^2+OB^2-2OA \cdot OB \cdot cos \lang a,b \rang =AB^2
OA2+OB2−2OA⋅OB⋅cos⟨a,b⟩=AB2
对于其他两个三角形有类似的性质,可得:
O
A
2
+
O
B
2
−
2
O
A
⋅
O
B
⋅
c
o
s
⟨
a
,
b
⟩
=
A
B
2
O
B
2
+
O
C
2
−
2
O
B
⋅
O
C
⋅
c
o
s
⟨
b
,
c
⟩
=
B
C
2
O
A
2
+
O
C
2
−
2
O
A
⋅
O
C
⋅
c
o
s
⟨
a
,
c
⟩
=
A
C
2
OA^2 + OB^2 - 2OA \cdot OB \cdot cos\lang a,b \rang = AB^2 \\ OB^2 + OC^2 - 2OB \cdot OC \cdot cos \lang b,c \rang = BC^2 \\ OA^2 + OC^2 - 2OA \cdot OC \cdot cos \lang a,c \rang = AC^2
OA2+OB2−2OA⋅OB⋅cos⟨a,b⟩=AB2OB2+OC2−2OB⋅OC⋅cos⟨b,c⟩=BC2OA2+OC2−2OA⋅OC⋅cos⟨a,c⟩=AC2
对于上面三式子全体除以
O
C
2
OC^2
OC2,并且记
x
=
O
A
/
O
C
,
y
=
O
B
/
O
C
x=OA/OC, \quad y=OB/OC
x=OA/OC,y=OB/OC得到:
x
2
+
y
2
−
2
x
y
c
o
s
⟨
a
,
b
⟩
=
A
B
2
/
O
C
2
y
2
+
1
2
−
2
y
c
o
s
⟨
b
,
c
⟩
=
B
C
2
/
O
C
2
x
2
+
1
2
−
2
x
c
o
s
⟨
a
,
c
⟩
=
A
C
2
/
O
C
2
x^2+y^2-2xycos\lang a,b \rang = AB^2/OC^2 \\ y^2+1^2-2ycos \lang b,c \rang = BC^2/OC^2 \\ x^2+1^2-2xcos \lang a,c \rang = AC^2/OC^2
x2+y2−2xycos⟨a,b⟩=AB2/OC2y2+12−2ycos⟨b,c⟩=BC2/OC2x2+12−2xcos⟨a,c⟩=AC2/OC2
记
v
=
A
B
2
/
O
C
2
,
u
v
=
B
C
2
/
O
C
2
,
w
v
=
A
C
2
/
O
C
2
v=AB^2/OC^2, uv=BC^2/OC^2, wv=AC^2/OC^2
v=AB2/OC2,uv=BC2/OC2,wv=AC2/OC2,可得:
x
2
+
y
2
−
2
x
y
c
o
s
⟨
a
,
b
⟩
−
v
=
0
y
2
+
1
2
−
2
y
c
o
s
⟨
b
,
c
⟩
−
u
v
=
0
x
2
+
1
2
−
2
x
c
o
s
⟨
a
,
c
⟩
−
w
v
=
0
x^2+y^2-2xycos\lang a,b \rang - v = 0 \\ y^2+1^2-2ycos \lang b,c \rang - uv=0 \\ x^2+1^2-2xcos \lang a,c \rang - wv=0
x2+y2−2xycos⟨a,b⟩−v=0y2+12−2ycos⟨b,c⟩−uv=0x2+12−2xcos⟨a,c⟩−wv=0
我们可以把第一个式子中的
v
v
v放到等式一边,并代入第2,3两式子1,得:
(
1
−
u
)
y
2
−
u
x
2
−
c
o
s
⟨
b
,
c
⟩
y
+
2
u
x
y
c
o
s
⟨
a
,
b
⟩
+
1
=
0
(
1
−
w
)
x
2
−
w
y
2
−
c
o
s
⟨
a
,
c
⟩
x
+
2
w
x
y
c
o
s
⟨
a
,
b
⟩
+
1
=
0
(1-u)y^2-ux^2-cos \lang b,c \rang y + 2uxycos \lang a,b \rang + 1=0 \\ (1-w)x^2-wy^2-cos \lang a,c \rang x + 2wxycos \lang a,b \rang + 1=0
(1−u)y2−ux2−cos⟨b,c⟩y+2uxycos⟨a,b⟩+1=0(1−w)x2−wy2−cos⟨a,c⟩x+2wxycos⟨a,b⟩+1=0
由于我们知道2D点的图像位置,三个余弦角 c o s ⟨ a , b ⟩ , c o s ⟨ b , c ⟩ , c o s ⟨ a , c ⟩ cos\lang a, b\rang, cos\lang b, c\rang, cos\lang a, c\rang cos⟨a,b⟩,cos⟨b,c⟩,cos⟨a,c⟩是已知的。同时, u = B C 2 / A B 2 , w = A C 2 / A B 2 u = BC^2 / AB^2 , w = A C^2 / A B^2 u=BC2/AB2,w=AC2/AB2 可以通过 A, B, C 在世界坐标系下的坐标算出,变换到相机坐标系下之后,并不改变这个比值。该式中的 x , y x, y x,y是未知的,随着相机移动会发生变化。 因此,该方程组是关于 x , y x, y x,y的一个二元二次方程(多项式方程)。解析地求解该方程组是一个复杂的过程,需要用吴消元法。
P3P也存在着一些问题:
- P3P只利用三个点的信息。当给定的配对点多于3组时候,难以利用更多的信息。
- 如果3D点或者2D点受到噪声影响,或者存在误匹配,则算法失效。
在SLAM当中,通常的做法是先使用P3P/EPnP等方法估计相机位姿,然后构建最 小二乘优化问题对估计值进行调整(Bundle Adjustment)。
(3) Bundle Adjustment
除了使用线性方法之外,我们可以把PnP问题构建成一个定义于李代数上的非线性最小二乘问题。前面说的线性方法,往往是先求相机位姿,再求空间点位置,非线性优化则是把它们都看成优化变量,放在一起优化。在PnP中,这个Bundle Adjustment问题,是一个最小化重投影误差(Reprojection error)的问题。
考虑
n
n
n个三维空间点
P
P
P和它的投影
p
p
p,我们希望计算相机的位姿
R
,
t
R,t
R,t,它的李代数为
ϵ
\epsilon
ϵ。假设某空间点的坐标为
P
i
=
[
X
i
,
Y
i
,
Z
i
]
T
P_i=[X_i,Y_i,Z_i]^T
Pi=[Xi,Yi,Zi]T,其投影的像素坐标为
u
i
=
[
u
i
,
v
i
]
T
u_i=[u_i,v_i]^T
ui=[ui,vi]T。根据第五讲内容,可得:
s
i
[
u
i
v
i
1
]
=
K
T
[
X
i
Y
i
Z
i
1
]
s_i \biggl [\begin{matrix} u_i \\v_i \\ 1 \end{matrix} \biggl] = KT \biggl [\begin{matrix} X_i \\Y_i \\Z_i \\ 1 \end{matrix} \biggl]
si[uivi1]=KT[XiYiZi1]
其中
T
T
T用李代数表示,可得:
s
i
[
u
i
v
i
1
]
=
K
e
x
p
(
ϵ
∧
)
[
X
i
Y
i
Z
i
1
]
s_i \biggl [\begin{matrix} u_i \\v_i \\ 1 \end{matrix} \biggl] = Kexp(\epsilon^{\land}) \biggl [\begin{matrix} X_i \\Y_i \\Z_i \\ 1 \end{matrix} \biggl]
si[uivi1]=Kexp(ϵ∧)[XiYiZi1]
写成矩阵的形式就是:
s
i
u
i
=
K
e
x
p
(
ϵ
∧
)
P
i
s_iu_i=Kexp(\epsilon^{\land})P_i
siui=Kexp(ϵ∧)Pi
现在,由于相机位姿未知以及观测点的噪声,该等式存在一个误差。因此,我们把误差求和,构建最小二乘问题,然后寻找最好的相机位姿,使它最小化:
ϵ ∗ = arg min ϵ 1 2 ∑ i = 1 n ∣ ∣ u i − 1 s i K e x p ( ϵ ∧ ) P i ∣ ∣ 2 2 \epsilon^*=\argmin_{\epsilon}\frac{1}{2}\sum_{i=1}^n||u_i - \frac{1}{s_i}Kexp(\epsilon^{\land})P_i||_2^2 ϵ∗=ϵargmin21i=1∑n∣∣ui−si1Kexp(ϵ∧)Pi∣∣22
该问题的误差项,是将像素坐(标观测到的投影位置)与3D点按照当前估计的位姿进行投影得到的位置相比较得到的误差,所以称之为重投影误差。
使用齐次坐标时,这个误差有3维。不过,由于u最后一维为1,该维度的误差一直为零,因而我们更多时候使用非齐次坐标,于是误差就只有2维了。
我们通过特征匹配,知道了 p 1 p_1 p1和 p 2 p_2 p2是同一个空间点 P P P的投影,但是我们不知道相机的位姿。在初始值中,P的投影 p ^ 2 \hat{p}_2 p^2与实际的 p 2 p_2 p2之间有一定的距离。于是我们调整相机的位姿,使得这个距离变小。不过,由于这个调整需要考虑很多个点,所以最后每个点的误差通常都不会精确为零。 使用李代数,可以构建无约束的优化问题,很方便地通过 G-N, L-M 等优化算法进行求解。在使用 G-N 和 L-M 之前,我们需要知道每个误差项关于优化变量的导数,也就是线性化:
e ( x + Δ x ) ≈ e ( x ) + J Δ x e(x+\Delta x) \approx e(x) + J\Delta x e(x+Δx)≈e(x)+JΔx
这里的 J J J的形式是值得讨论的,甚至可以说是关键所在。现在,当 e e e为像素坐标误差(2维), x x x为相机位姿(6维)时, J J J将是一个2 × 6的矩阵。我们来推导 J J J的形式。
首先,记变换到相机坐标系下的空间点坐标为
P
′
P'
P′,并且把它的前三维取出来:
P
′
=
(
e
x
p
(
ϵ
∧
)
P
)
1
:
3
=
[
X
′
,
Y
′
,
Z
′
]
T
P'=(exp(\epsilon^{\land})P)_{1:3}=[X',Y',Z']^T
P′=(exp(ϵ∧)P)1:3=[X′,Y′,Z′]T
注意:
e
x
p
(
ϵ
∧
)
P
i
exp(\epsilon^{\land})P_i
exp(ϵ∧)Pi结果是4 × 1的,而它左侧的
K
K
K是3 × 3的,所以必须把
e
x
p
(
ϵ
∧
)
P
i
exp(\epsilon^{\land})P_i
exp(ϵ∧)Pi的前三维取出来,变成三维的非齐次坐标。
那么相机投影模型相对于
P
′
P'
P′为:
s
u
=
K
P
′
su=KP'
su=KP′
展开为:
[
s
u
s
v
s
]
=
[
f
x
0
c
x
0
f
y
c
y
0
0
1
]
[
X
′
Y
′
Z
′
]
\biggl [\begin{aligned} su \\ sv \\s \end{aligned} \biggl]=\biggl[ \begin{matrix} f_x \quad 0 \quad c_x \\ 0 \quad f_y \quad c_y \\ 0 \quad 0 \quad 1 \end{matrix} \biggl] \biggl[ \begin{matrix} X' \\ Y' \\ Z' \end{matrix}\biggl]
[susvs]=[fx0cx0fycy001][X′Y′Z′]
利用第三行消去
s
s
s(实际上就是
P
′
P'
P′的距离),得:
u
=
f
x
X
′
Z
′
+
c
x
,
v
=
f
y
Y
′
Z
′
+
c
y
u=f_x \frac{X'}{Z'} + c_x, \quad v = f_y \frac{Y'}{Z'} + c_y
u=fxZ′X′+cx,v=fyZ′Y′+cy
当我们求误差时,可以把这里的
u
,
v
u, v
u,v与实际的测量值比较,求差。我们对
ϵ
∧
\epsilon^{\land}
ϵ∧左乘扰动量
δ
ϵ
\delta \epsilon
δϵ,然后考虑
e
e
e的变化关于扰动量的导数。利用链式法则,可以写出:
∂
e
∂
δ
ϵ
=
lim
δ
ϵ
→
0
e
(
δ
ϵ
⊕
ϵ
)
δ
ϵ
=
∂
e
∂
P
′
∂
P
′
∂
δ
ϵ
\frac{\partial e}{\partial \delta \epsilon} = \lim_{\delta \epsilon \rightarrow 0} \frac{e(\delta \epsilon \oplus \epsilon)}{\delta \epsilon} = \frac{\partial e}{\partial P'}\frac{\partial P'}{\partial \delta \epsilon}
∂δϵ∂e=δϵ→0limδϵe(δϵ⊕ϵ)=∂P′∂e∂δϵ∂P′
这里的
⊕
\oplus
⊕指的是李代数上的左乘扰动。第一项是误差关于投影点的导数。我们进一步得到:
∂
e
∂
P
′
=
−
[
∂
u
∂
X
′
∂
u
∂
Y
′
∂
u
∂
Z
′
∂
v
∂
X
′
∂
v
∂
Y
′
∂
v
∂
Z
′
]
=
−
[
f
x
Z
′
0
−
f
x
X
′
Z
′
2
0
f
y
Z
′
−
f
y
Y
′
Z
′
2
]
\frac{\partial e}{\partial P'}=-\biggl[ \begin{matrix} \frac{\partial u}{\partial X'} \quad \frac{\partial u}{\partial Y'} \quad \frac{\partial u}{\partial Z'} \\ \frac{\partial v}{\partial X'} \quad \frac{\partial v}{\partial Y'} \quad \frac{\partial v}{\partial Z'} \end{matrix} \biggl] = -\biggl[ \begin{matrix} \frac{f_x}{Z'} \quad 0 \quad -\frac{f_x X'}{{Z'}^2} \\ 0 \quad \frac{f_y}{Z'} \quad -\frac{f_y Y'}{{Z'}^2} \end{matrix} \biggl]
∂P′∂e=−[∂X′∂u∂Y′∂u∂Z′∂u∂X′∂v∂Y′∂v∂Z′∂v]=−[Z′fx0−Z′2fxX′0Z′fy−Z′2fyY′]
而第二项为变换后的点关于李代数的导数,进一步可得:
∂
(
T
P
)
∂
δ
ϵ
=
(
T
P
)
⊙
=
[
I
−
P
′
∧
0
T
0
T
]
\frac{\partial (TP)}{\partial \delta \epsilon} = (TP)^{\odot}=\biggl[\begin{matrix} I \quad -P'^{\land} \\ 0^T \quad 0^T \end{matrix}\biggl]
∂δϵ∂(TP)=(TP)⊙=[I−P′∧0T0T]
而在
P
′
P'
P′的定义中,我们取出了前三维,于是得:
∂
P
′
∂
δ
ϵ
=
[
I
,
−
P
′
∧
]
\frac{\partial P'}{\partial \delta \epsilon} = [I, -P'^{\land}]
∂δϵ∂P′=[I,−P′∧]
將这两项相乘,就得到了
2
×
6
2 \times 6
2×6的雅可比矩阵:
∂
e
∂
δ
ϵ
=
−
[
f
x
Z
′
0
−
f
x
X
′
Z
′
2
−
f
x
X
′
Y
′
Z
′
2
f
x
+
f
x
X
2
Z
′
2
−
f
x
Y
′
Z
′
0
f
y
Z
′
−
f
y
Y
′
Z
′
2
−
f
y
−
f
y
Y
′
2
Z
′
2
f
y
X
′
Y
′
Z
′
2
f
y
X
′
Z
′
]
\frac{\partial e}{\partial \delta \epsilon} = -\biggl[\begin{matrix} \frac{f_x}{Z'} \quad 0 \quad -\frac{f_x X'}{Z'^2} \quad -\frac{f_x X'Y'}{Z'^2} f_x + \frac{f_x X^2}{Z'^2} \quad -\frac{f_x Y'}{Z'} \\ 0 \quad \frac{f_y}{Z'} \quad -\frac{f_y Y'}{Z'^2} \quad -f_y-\frac{f_yY'^2}{Z'^2} \quad \frac{f_yX'Y'}{Z'^2} \quad \frac{f_yX'}{Z'} \end{matrix} \biggl]
∂δϵ∂e=−[Z′fx0−Z′2fxX′−Z′2fxX′Y′fx+Z′2fxX2−Z′fxY′0Z′fy−Z′2fyY′−fy−Z′2fyY′2Z′2fyX′Y′Z′fyX′]
这个雅可比矩阵描述了重投影误差关于相机位姿李代数的一阶变化关系。保留了前面的负号,因为这是由于误差是由观测值减预测值定义的。
另一方面,除了优化位姿,我们还希望优化特征点的空间位置。需要讨论
e
e
e关于空间点
P
P
P的导数。仍然利用链式法则:
∂
e
∂
P
=
∂
e
∂
P
′
∂
P
′
∂
P
\frac{\partial e}{\partial P} = \frac{\partial e}{\partial P'}\frac{\partial P'}{\partial P}
∂P∂e=∂P′∂e∂P∂P′
第一项前面推导了,第二项,根据定义:
P
′
=
e
x
p
(
ϵ
∧
)
P
=
R
P
+
t
P'=exp(\epsilon^{\land})P =RP + t
P′=exp(ϵ∧)P=RP+t
我们发现
P
′
P'
P′对P求导后只剩下
R
R
R。于是:
∂
e
∂
P
=
−
[
f
x
Z
′
0
−
f
x
X
′
Z
′
2
0
f
y
Z
′
−
f
y
Y
′
Z
′
2
]
R
\frac{\partial e}{\partial P} = -\biggl[ \begin{matrix} \frac{f_x}{Z'} \quad 0 \quad -\frac{f_xX'}{Z'^2} \\ 0 \quad \frac{f_y}{Z'} \quad -\frac{f_yY'}{Z'^2} \end{matrix}\biggl]R
∂P∂e=−[Z′fx0−Z′2fxX′0Z′fy−Z′2fyY′]R
于是,我们推导了观测相机方程关于相机位姿与特征点的两个导数矩阵。它们十分重要,能够在优化过程中提供重要的梯度方向,指导优化的迭代。