本节讲如何从单一视角恢复出3D的场景信息,以及能够恢复3D信息需要哪些条件。
1. 基础知识
1.1 仿射变换与透视变换
2D平面中的仿射变换如下:
[x′y′1]=[A2×2t2×101][xy1]
\begin{bmatrix}
x' \\
y' \\
1
\end{bmatrix} = \begin{bmatrix}
A_{2\times 2} & t_{2\times 1} \\
0 & 1
\end{bmatrix} \begin{bmatrix}
x \\
y \\
1
\end{bmatrix}
x′y′1=[A2×20t2×11]xy1
类似地,在3D空间中,定义仿射变换
[x′y′z′1]=[A3×3t3×101][xyz1]
\begin{bmatrix}
x' \\
y' \\
z' \\
1
\end{bmatrix} = \begin{bmatrix}
A_{3\times 3} & t_{3\times 1} \\
0 & 1
\end{bmatrix} \begin{bmatrix}
x \\
y \\
z \\
1
\end{bmatrix}
x′y′z′1=[A3×30t3×11]xyz1
如果左下角不再是0,而是一个向量vvv,则称为透视变换:
[x′y′z′1]=[A3×3t3×1v3×1Tb][xyz1]
\begin{bmatrix}
x' \\
y' \\
z' \\
1
\end{bmatrix} = \begin{bmatrix}
A_{3\times 3} & t_{3\times 1} \\
v_{3\times1}^T & b
\end{bmatrix} \begin{bmatrix}
x \\
y \\
z \\
1
\end{bmatrix}
x′y′z′1=[A3×3v3×1Tt3×1b]xyz1
1.2 2D与3D平面点、线、面的表示
在2D平面中,一个直线可以表示为ax1+bx2+c=0ax_1 + bx_2 + c = 0ax1+bx2+c=0, 如果令
l=[abc],x=[x1x21]
l = \begin{bmatrix}
a \\
b \\
c
\end{bmatrix} , x =
\begin{bmatrix}
x_1 \\
x_2 \\
1
\end{bmatrix}
l=abc,x=x1x21
则直线上的点可以表示成lTx=0l^Tx = 0lTx=0. 注意这里xxx是齐次坐标表示。
那么对于直线lll和l′l'l′,两条直线的交点怎么表示?实际上就是二者的叉乘,即x=l×l′x = l \times l'x=l×l′.
证明:
xxx在lll上——lTx=lT(l×l′)l^Tx = l^T (l \times l')lTx=lT(l×l′), 向量的叉乘垂直于任一向量,因此lT(l×l′)=0l^T (l \times l')=0lT(l×l′)=0得证。
xxx在l′l'l′上同理。
在3D平面中,一般用直线的方向d=[a,b,c]Td = [a, b, c]^Td=[a,b,c]T代表直线。一个直线由一个已知点p0p_0p0和方向向量决定,可以写成参数方程形式:
P(t)=p0+td=[x0+ta,y0+tb,z0+tc]T
P(t) = p_0 + td = [x_0 + ta, y_0 + tb, z_0 + tc]^T
P(t)=p0+td=[x0+ta,y0+tb,z0+tc]T
判定一个点p=[x,y,z,1]p = [x, y, z, 1]p=[x,y,z,1]在平面上,假设平面的法向量为n=[a,b,c]n = [a, b, c]n=[a,b,c], 记Π=[a,b,c,d]\Pi = [a, b, c, d]Π=[a,b,c,d], 有Π⋅p=0\Pi\cdot p = 0Π⋅p=0.
判定一个线lll在平面上,有l⋅[a,b,c]=0l \cdot [a, b, c] = 0l⋅[a,b,c]=0, 且直线上至少一个点在平面上.
2. 无穷远点,线,面
2.1 2D平面的无穷远点与直线
我们定义两个平行线的交点为无穷远点。在形式上,无穷远点的齐次坐标肯定是满足如下形式
x=[x1x20]
x =
\begin{bmatrix}
x_1 \\
x_2 \\
0
\end{bmatrix}
x=x1x20
因为除以最后一个坐标0后,表示该点在无穷远处。
假设两个直线l=[a,b,c]T,l′=[a′,b′,c′]Tl = [a, b, c]^T, l' = [a', b', c']^Tl=[a,b,c]T,l′=[a′,b′,c′]T平行,说明ab=a′b′\frac{a}{b} = \frac{a'}{b'}ba=b′a′. 这两个直线的交点为
l×l′=det([ijkabca′b′c′])=[bc′−cb′−(ac′−a′c)ab′−a′b]=[bc′−cb′a′c−ac′0]
l \times l' = \det (\begin{bmatrix}
i && j && k \\
a && b && c \\
a' && b' && c'
\end{bmatrix}) = \begin{bmatrix}
bc' - cb' \\
-(ac' - a'c) \\
ab' - a'b
\end{bmatrix} = \begin{bmatrix}
bc' - cb' \\
a'c - ac' \\
0
\end{bmatrix}
l×l′=det(iaa′jbb′kcc′)=bc′−cb′−(ac′−a′c)ab′−a′b=bc′−cb′a′c−ac′0
所以也符合无穷远点的形式。
我们可以继续化简:
[bc′−cb′a′c−ac′0]=c′[b−a0]−c[b′−a′0]
\begin{bmatrix}
bc' - cb' \\
a'c - ac' \\
0
\end{bmatrix} = c'\begin{bmatrix}
b \\
-a \\
0
\end{bmatrix} - c \begin{bmatrix}
b' \\
-a' \\
0
\end{bmatrix}
bc′−cb′a′c−ac′0=c′b−a0−cb′−a′0
我们又知道ab=a′b′\frac{a}{b} = \frac{a'}{b'}ba=b′a′, 所以等号右边的两个向量其实是平行的,因此
[bc′−cb′a′c−ac′0]∝[b−a0]
\begin{bmatrix}
bc' - cb' \\
a'c - ac' \\
0
\end{bmatrix} \propto \begin{bmatrix}
b \\
-a \\
0
\end{bmatrix}
bc′−cb′a′c−ac′0∝b−a0
定理:所有无穷远点都汇集在一条线上,称为无穷远直线,这条直线为l=[0,0,1]Tl = [0, 0, 1]^Tl=[0,0,1]T
证明:
将x=[b,−a,0]Tx = [b, -a, 0]^Tx=[b,−a,0]T代入lTxl^TxlTx立即得到lTx=0l^Tx = 0lTx=0.
2.2 3D空间中的无穷远点、直线与平面
在3D空间中,类比2D空间可以得到,无穷远点应该具有以下形式:
x=[x1x2x30]
x =
\begin{bmatrix}
x_1 \\
x_2 \\
x_3 \\
0
\end{bmatrix}
x=x1x2x30
如果一个直线的方向向量为d=[a,b,c]Td = [a, b, c]^Td=[a,b,c]T, 那么该直线的无穷远点坐标为x=[a,b,c,0]Tx = [a, b, c, 0]^Tx=[a,b,c,0]T. 与这个直线平行的其他直线,交点也是同一个无穷远点。
说明:
直线上的点满足直线的参数方程:P(t)=p0+td=[x0+ta,y0+tb,z0+tc]TP(t) = p_0 + td = [x_0 + ta, y_0 + tb, z_0 + tc]^TP(t)=p0+td=[x0+ta,y0+tb,z0+tc]T, 写成齐次坐标形式就是[x0+ta,y0+tb,z0+tc,1]T[x_0 + ta, y_0 + tb, z_0 + tc, 1]^T[x0+ta,y0+tb,z0+tc,1]T.
我们把每个坐标都除以ttt,这并不改变点的实际坐标,得到[(x0+ta)/t,(y0+tb)/t,(z0+tc)/t,1/t]T[(x_0 + ta) / t, (y_0 + tb) / t, (z_0 + tc) / t, 1 / t]^T[(x0+ta)/t,(y0+tb)/t,(z0+tc)/t,1/t]T.
我们靠近无穷远点的形式,即令t→∞t \to \inftyt→∞, 得到[a,b,c,0]T[a, b, c, 0]^T[a,b,c,0]T. 所以,无穷远点坐标与p0p_0p0是无关了的,只与方向有关。
类似地,可以证明所有无穷远点都汇集在一个无穷远平面上,这个平面的法向量为n∞=[0,0,0,1]Tn_\infty = [0, 0, 0, 1]^Tn∞=[0,0,0,1]T.
证明:
将x=[x1,x2,x3,0]Tx = [x_1, x_2, x_3, 0]^Tx=[x1,x2,x3,0]T代入nTxn^TxnTx立即得到nTx=0n^Tx = 0nTx=0.
同样类比,两个平行平面,它们在无穷远处相交于一个公共线,叫做无穷远线。
可以这样理解:两个平面平行说明法向量n1=αn2n_1 = \alpha n_2n1=αn2, alphaalphaalpha为一常数。这可以解出法向量坐标之间的约束关系。按照类似2D平面的推导过程,一定存在一个(唯一)的直线lll满足lll既在n1n_1n1也在n2n_2n2.
3. 影消点和影消线
3.1 2D平面上无穷远点、线的变换
考虑透视变换H=[A2×2t2×1v2×1Tb]H = \begin{bmatrix}
A_{2\times 2} & t_{2\times 1} \\
v_{2\times1}^T & b
\end{bmatrix}H=[A2×2v2×1Tt2×1b], 我们看看无穷远点经过透视变换会映射成什么:
[Atvb][ab0]=[xyz]
\begin{bmatrix}
A & t \\
v & b
\end{bmatrix}\begin{bmatrix}
a \\
b \\
0
\end{bmatrix} = \begin{bmatrix}
x \\
y \\
z
\end{bmatrix}
[Avtb]ab0=xyz
足以见得z=av1+bv2z = av_1 + bv_2z=av1+bv2不一定等于0. 所以,无穷远点经过透视变换不一定是无穷远点了。
相反,考虑仿射变换H=[A2×2t2×101]H = \begin{bmatrix}
A_{2\times 2} & t_{2\times 1} \\
0 & 1
\end{bmatrix}H=[A2×20t2×11]
[At01][ab0]=[xyz]
\begin{bmatrix}
A & t \\
0 & 1
\end{bmatrix}\begin{bmatrix}
a \\
b \\
0
\end{bmatrix} = \begin{bmatrix}
x \\
y \\
z
\end{bmatrix}
[A0t1]ab0=xyz
足以见得z=0z =0z=0. 所以,无穷远点经过仿射变换一定是无穷远点。
对于直线lll,假设变换后直线为l′l'l′, 对于lll上的点xxx, 有lTx=0l^Tx = 0lTx=0, xxx变换后为x′=Hxx' = Hxx′=Hx, 变换后的x′x'x′肯定在l′l'l′上:
l′Tx′=0→l′T(Hx)=0
l'^Tx' = 0 \\
\to l'^T(Hx) = 0
l′Tx′=0→l′T(Hx)=0
对比得lT=(l′TH)→HTl′=l→l′=(HT)−1ll^T = (l'^T H) \to H^Tl' = l \to l' = (H^T)^{-1}llT=(l′TH)→HTl′=l→l′=(HT)−1l.
有了变换公式后,如果是透视变换:
([Atvb]T)−1[001]=[xyz]
(\begin{bmatrix}
A & t \\
v & b
\end{bmatrix} ^T)^{-1}\begin{bmatrix}
0 \\
0 \\
1
\end{bmatrix} = \begin{bmatrix}
x \\
y \\
z
\end{bmatrix}
([Avtb]T)−1001=xyz
显然x,yx, yx,y不一定为0. 所以无穷远线在透视变换下不一定能够保持。
如果是仿射变换:
([At01]T)−1[001]=[AT0−tTAT1][001]=[001]
(\begin{bmatrix}
A & t \\
0 & 1
\end{bmatrix} ^T)^{-1}\begin{bmatrix}
0 \\
0 \\
1
\end{bmatrix} =\begin{bmatrix}
A^T & 0 \\
-t^TA^T & 1
\end{bmatrix} \begin{bmatrix}
0 \\
0 \\
1
\end{bmatrix} = \begin{bmatrix}
0 \\
0 \\
1
\end{bmatrix}
([A0t1]T)−1001=[AT−tTAT01]001=001
所以无穷远线在仿射变换下一定能够保持。
3.2 影消点
**定义:**3D空间中的无穷远点,经过变换M=K[R,T]∈R3×4M = K[R, T] \in \mathbb{R}^{3 \times 4}M=K[R,T]∈R3×4的变换后,映射到像素平面上的点p=[p1,p2,p3]Tp = [p_1, p_2, p_3]^Tp=[p1,p2,p3]T. 经过上面的推导,对于一般的变换,无穷远点经过变换后往往不会再保持。所以,这个点ppp就被称为影消点:
我们从影消点还能得到什么信息?
影消点与直线方向:直线方向d=[a,b,c]Td = [a, b, c]^Td=[a,b,c]T(相机坐标系下)和影消点vvv的关系是v=Kdv = Kdv=Kd.
证明:
前面说明了这两个平行直线上无穷远点的齐次坐标是[a,b,c,0]T[a, b, c, 0]^T[a,b,c,0]T. 从相机坐标系到像素平面的映射为M=K[I,0]=[K,0]M = K[I, 0] = [K, 0]M=K[I,0]=[K,0], 所以有
v=Mp∞=K[a,b,c]Tv =Mp_\infty = K[a, b, c]^Tv=Mp∞=K[a,b,c]T.
从v=Kdv = Kdv=Kd立即得到(ddd是一个方向向量,模为1)
d=K−1v∣∣K−1v∣∣
d = \frac{K^{-1}v}{||K^{-1}v||}
d=∣∣K−1v∣∣K−1v
3.3 影消线
3D空间中,一个平面上的平行线交汇的无穷远点连起来在一条线上,即无穷远线。
根据前面的结论,无穷远线l∞l_\inftyl∞经过透视变换后,可以变换到像素平面上的直线lh=(HT)−1l∞l_h = (H^T)^{-1}l_\inftylh=(HT)−1l∞, 这个线称为影消线。
为什么同一个平面的所有无穷远点共线?
设平行线方向向量为[a,b,c][a, b, c][a,b,c], 则无穷远点齐次坐标[a,b,c,0][a, b, c, 0][a,b,c,0]. 平面参数为[A,B,C,D][A, B, C, D][A,B,C,D](即平面方程为Ax+By+Cz+D=0Ax +By + Cz +D = 0Ax+By+Cz+D=0).
代入得Aa+Bb+Cc=0Aa + Bb +Cc = 0Aa+Bb+Cc=0. 这实际上是2D平面上直线的方程(相当于2D平面齐次坐标为[a,b,c][a, b, c][a,b,c], 直线参数为A,B,CA, B, CA,B,C. 所以实际上,(齐次坐标的最后一个值为0使得这个方程)退化成了一条2D平面上的直线。这个线就是无穷远线。
影消线与平面法向量:
3D空间中一个平面π\piπ,其对应的无穷远线为l∞l_\inftyl∞, 映射到像素平面的影消线为lhl_hlh, 那么该平面的法向量为:
n=KTlh
n = K^Tl_h
n=KTlh
证明:
对于l∞l_\inftyl∞上的一个点PPP(PPP也在平面上),其投影到像素平面的坐标为p=K[I,0]Pp = K[I, 0]Pp=K[I,0]P, ppp在lhl_hlh上,所以
lhT(K[I,0]P)=0l_h^T(K[I, 0]P) = 0lhT(K[I,0]P)=0
同时,PPP在平面上,
ΠTP=0\Pi^TP = 0ΠTP=0, 其中Π=[A,B,C,D]T\Pi = [A, B, C, D]^TΠ=[A,B,C,D]T表示平面方程的系数,法向量n=[A,B,C]Tn = [A, B, C]^Tn=[A,B,C]T.
所以ΠT=lhT[K,0]\Pi^T = l_h^T[K, 0]ΠT=lhT[K,0], 对应地,nT=lTKn^T = l^T KnT=lTK. 也即n=KTlhn = K^Tl_hn=KTlh.
截止目前,我们得到了如下核心结论:
-
影消点、直线方向和内参的关系:
v=Kdv = Kdv=Kd 或者d=K−1v∣∣K−1v∣∣d = \frac{K^{-1}v}{||K^{-1}v||}d=∣∣K−1v∣∣K−1v
-
影消线,平面法向量和内参的关系:
n=KTlhn = K^Tl_hn=KTlh
3.4 3D重构
知道了前面的铺垫,我们现在开始重建3D场景。
为了估计相机的内参,我们还需要借助一个信息,即一个平面内两组平行线的夹角与影消点。
有两组平行线,方向向量分别为d1,d2d_1, d_2d1,d2. 在像素平面上的影消点为v1,v2v_1, v_2v1,v2:
在3D空间中,两组平行线的夹角为θ\thetaθ, 其也是方向向量的夹角。所以:
cosθ=d1⋅d2∣d1∣∣d2∣=(∣d∣=1)d1⋅d2
\cos \theta = \frac{d_1 \cdot d_2}{|d_1||d_2|} = (|d| = 1) d_1 \cdot d_2
cosθ=∣d1∣∣d2∣d1⋅d2=(∣d∣=1)d1⋅d2
借助我们前面知道的第一条信息,得到
cosθ=(K−1v1)T(K−1v1)TK−1v1K−1v2(K−1v2)TK−1v2=v1ωv2v1Tωv1v2Tωv2
\cos \theta = \frac{(K^{-1}v_1)^T}{\sqrt{(K^{-1}v_1)^TK^{-1}v_1}} \frac{K^{-1}v_2}{\sqrt{(K^{-1}v_2)^TK^{-1}v_2}} = \frac{v_1 \omega v_2}{\sqrt{v_1^T \omega v_1}\sqrt{v_2^T \omega v_2}}
cosθ=(K−1v1)TK−1v1(K−1v1)T(K−1v2)TK−1v2K−1v2=v1Tωv1v2Tωv2v1ωv2
其中ω=(K−1)TK−1\omega = (K^{-1})^T K^{-1}ω=(K−1)TK−1.
如果我们找在3D世界中 垂直的一组平行线(这里的一组指的是一对平行线d1d_1d1和一对平行线d2d_2d2),则cos为0,得到方程v1ωv2=0v_1 \omega v_2 = 0v1ωv2=0. 内参矩阵有5个自由度,所以需要5组方程(5组平行线)来解。
我们可以把KKK的表达式代入ω\omegaω, 可以发现ω\omegaω是一个对称矩阵,且有以下结论:
- ω12=0\omega_{12} = 0ω12=0, 说明像素零倾斜(即内参矩阵中的θ\thetaθ为90)。
- 如果ω11=ω22\omega_{11} = \omega_{22}ω11=ω22, 说明像素点的宽高比为1(方形像素, α=β\alpha = \betaα=β)。
不妨做这两个假设(像素零倾斜,且方形像素),这样ω\omegaω的自由度减少为3. 这样我们找三组平行线即可。
解出ω\omegaω后,就可以得到内参矩阵KKK.
得到KKK之后,根据像素平面的影消线,就可以得出对应平面的法向量n=KTlhn = K^Tl_hn=KTlh.
例子:
- 找三个平面,可以取绿色、红色和地面,在这三个平面中各找一组平行线(要垂直!满足cosθ=0\cos \theta = 0cosθ=0),并计算出像素平面的影消点。由此估计出内参矩阵KKK.
- 对于每个平面,找一组平行线画出影消线(像素平面),根据n=KTlhn = K^Tl_hn=KTlh重构出平面的法向量。但是不是所有的平面都能重建,比如这个人。