详细的世界坐标转屏幕坐标及投影矩阵的推导

投影矩阵网上推导一大堆,怎么构建矩阵,怎么运用透视除法等都有说,但说清楚为什么这样做的貌似不多。我现在尝试用矩阵乘法的本质去说明投影矩阵是怎么推导的。

以下向量统一用列向量表示法。

1.坐标转换 

坐标的表达形式(Fundamentals of Computer Graphics, 4th page 135)

看上图,p在世界坐标系下的坐标值有两种表示法:

p=o+x_{p}x+y_{p}y           

 p=e+u_{p}u+v_{p}v  

其中:

(x_{p},y_{p})=(2.5,0.9)

(u_{p},v_{p})=(0.5,-0.7)

u,v是e坐标系下的标准正交基。

从图中可以看到,p在o坐标系下的坐标是(2.5,0.9),在e坐标系下是(0.5,-0.7)。

但按上面两个公式,算出来的值都是(2.5,0.9)。

我们把 p=e+u_{p}u+v_{p}v 的方程化为矩阵:

从矩阵可以看出(x,y)->(u,v)的转换关系。如下式:

那么,e坐标系下的坐标可由下式求的:

\begin{bmatrix} u_{p}\\ v_{p}\\ 1 \end{bmatrix}= {\begin{bmatrix} u &v &e \\ 0 & 0& 1 \end{bmatrix}}^{-1}p_{xy}

由于[u v]是正交矩阵,所以有:

\begin{bmatrix} u &v \end{bmatrix}^{-1} =\begin{bmatrix} u &v \end{bmatrix}^{t} =\begin{bmatrix} u^{t}\\ v^{t} \end{bmatrix}

\begin{bmatrix} u_{p}\\ v_{p}\\ 1 \end{bmatrix}= \begin{bmatrix} x_{u} &y_{u} &0 \\ x_{v} & y_{v} & 0\\ 0 &0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 &-x_{e} \\ 0 & 1 &-y_{e} \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_{p}\\ y_{p}\\ 1 \end{bmatrix}

说了这么多,目的是为了引出下面的推导,世界坐标转到摄像机空间坐标

上式可写为:

\begin{bmatrix} u_{p}\\ v_{p}\\ 1 \end{bmatrix}= \begin{bmatrix} u^t &0 \\ v^t & 0\\ 0 & 1 \end{bmatrix} \begin{bmatrix} 1 & 0 &-x_{e} \\ 0 & 1 &-y_{e} \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x_{p}\\ y_{p}\\ 1 \end{bmatrix}

2.摄像机矩阵推导

先明确一点:这里说的摄像机矩阵是指世界空间到摄像机的矩阵

摄像机空间的三个基分别是向量right,up,look,世界空间中的位置是P。以R表示摄像机right向量,U表示up向量,V表示look向量,我们的目的是把R,U,V三个向量分别转换到x,y,z向量。

由于这个向量比较难转换,我们换种思路,把x,y,z轴转到RUV的矩阵是:

R_{view}^{-1} = \begin{bmatrix} R_{x} & U_{x} & V_{x} & 0\\R_{y} & U_{y} & V_{y} & 0\\ R_{z} & U_{z} & V_{z} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

由于该矩阵是正交矩阵,那么有

R_{view} = (R_{view}^{-1})^{t} = \begin{bmatrix} R^t & 0\\ U^t & 0\\ V^t & 0\\ 0 & 1 \end{bmatrix} =\begin{bmatrix} R_{x} & R_{y} & R_{z} & 0\\U_{x} & U_{y} & U_{z} & 0\\ V_{x} & V_{y} & V_{z} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

回想一下,在空间中绕一点P旋转,是不是,可以看成先把P移到原点,然后旋转,再移动回P点上。

而摄像机空间,是把摄像机的坐标移动到原点,再把各个轴旋转到xyz轴上。

假设摄像机世界坐标是P,矩阵如下:

T_{view} = \begin{bmatrix} 1 & 0 & 0 & -P_{x}\\ 0 & 1 & 0 & -P_{y}\\ 0 & 0 & 1 &-P_{z} \\0 &0 &0 & 1 \end{bmatrix}

把两个矩阵相乘得到最后的lookup矩阵C:

C= R_{view}\times T_{view} = \begin{bmatrix} R_{x} & R_{y} & R_{z} & 0\\U_{x} & U_{y} & U_{z} & 0\\ V_{x} & V_{y} & V_{z} & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \quad \times \quad \begin{bmatrix} 1 & 0 & 0 & -P_{x}\\ 0 & 1 & 0 & -P_{y}\\ 0 & 0 & 1 &-P_{z} \\0 &0 &0 & 1 \end{bmatrix} \quad=\quad \begin{bmatrix} R_{x} & R_{y} & R_{z} & -P\cdot R\\U_{x} & U_{y} & U_{z} & -P\cdot U\\ V_{x} & V_{y} & V_{z} & -P\cdot V\\ 0 & 0 & 0 & 1 \end{bmatrix}

这里解释了为何LookUp矩阵的平移项是-P·R而不是-P,因为是矩阵相乘的结果。

摄像机空间转换矩阵推导完毕后,下一步是从摄像机空间转到投影空间。

3.正交投影矩阵的推导

我一直在想一个问题,能否用线性代数的投影矩阵来推导出正交投投影矩阵?

根据线性代数的投影矩阵推导公式,假设向量v在平面A[a1 a2]上的投影向量是p,则p可表示为下式:

p=x_{1}a_{1}+x_{2}a_{2}= \begin{bmatrix} a_{1} & a_{2} \end{bmatrix} \times $$ \begin{bmatrix} x_{1} & x_{2} \end{bmatrix} = Ax

其中a1,a2是平面的线性组合向量。这里有个限制:A必须是列空间,即A所在的空间一定包含零点

假设向量v投影到A空间后得到p,我们要求的矩阵是:Pv = p中的P

再有向量r = v - p,则向量r垂直平面A,即向量r与a1和a2都垂直。得到如下式子:

{a_{1}}^{T}\cdot r = 0

{a_{2}}^{T}\cdot r = 0

以上两式组合得:

\begin{bmatrix} a_{1}^{T} \\ a_{2}^{T} \end{bmatrix} $$\times $$ \begin{bmatrix} r \end{bmatrix} = \begin{bmatrix} 0 \end{bmatrix}

把r = v - p,p=Ax代入上式得

\\ \begin{bmatrix} a_{1}^{T} \\ a_{2}^{T} \end{bmatrix} \times \begin{bmatrix} v - Ax \end{bmatrix} = \begin{bmatrix} 0 \end{bmatrix} \\A^{T} \times [v-Ax] = [0]

简写成

\\ A^{T}v - A^{T}Ax=0 \\ A^{T}Ax =A^{T}v \\ x=\left( A^{T}A \right)^{-1}A^{T}v

Ax=p,两边乘以A得

\\ A^{T}v - A^{T}Ax=0 \\ A^{T}Ax =A^{T}v \\ x=\left( A^{T}A \right)^{-1}A^{T}v \\ Ax=A\left( A^{T}A \right)^{-1}A^{T}v \quad \Rightarrow \quad p = A\left( A^{T}A \right)^{-1}A^{T}v

即得投影矩阵 

P=A\left( A^{T}A \right)^{-1}A^{T}

更详细的性质与推导可以看线性代数投影矩阵的相关参考。

下面详细说出相机正交投影推导:

A是XOY平面,v是空间中一点。

A= $$ \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 0 & 0 \\ 0 & 0 \end{bmatrix}

P=A\left( A^{T}A \right)^{-1}A^{T} =$$ \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 \end{bmatrix}

 

然后要把投影坐标映射到NDC空间。NDC是一个归一化的盒子,z范围0-1,x,y都是-1到1,我手动画图来说明。

屏幕x轴的映射关系是

y=\frac{2}{w}x -1  其中w是屏幕映射区域的宽

同理屏幕y轴的映射关系是

y=\frac{2}{h}x -1  其中h是屏幕映射区域的高

现在我们把w换成r-l,把h换成t-b,r是投影区域的右X坐标,l是左X坐标,t和b同理。

\\ y=\frac{2}{r-l}x+(-\frac{r+l}{r-l}) \\ y=\frac{2}{t-b}x+(-\frac{t+b}{t-b})

z轴的映射关系如下:

求得映射方程如下:

y=\frac{1}{far-near}x+\frac{near}{near-far}

最后得到投影矩阵O:

O= $$ \begin{bmatrix} 2/(r-l) & 0 & 0 & -(r+l)/(r-l) \\ 0 & 2/(t-b) & 0 & -(t+b)/(t-b)\\ 0 & 0 & 1/(far-near) & near/(near-far) \\ 0 & 0 & 0 & 1 \end{bmatrix}

我们看到,P怎么变换也不能变换到O,这是为什么呢?

个人理解:P的行列式是0,没有逆矩阵,意味着你无法知道原来的Z的位置。因为线性代数中的投影矩阵是降维操作,而图形学中的投影是一个线性方程变换。

===============================

看了闫令琪的图形学中的推导,是我看过最好最直观的。

简单来说,正交投影就是把长方体的盒子,转换到中心为0的标准正方体[-1, 1]³。

这里是把z的n和f变换到-1到1中,和上面的[0,1]不一样

上图来源于闫令琪的教程,注意,我这里是左手坐标系,把图修正了。

长方体的平移距离是\left ( -(l+r)/2, -(t+l)/2,-(n+l)/2 \right ),矩阵表示为:

O_{t} = \begin{bmatrix} 1 & 0 & 0 & -(l+r)/2 \\ 0 & 1 & 0 & -(t+b)/2\\ 0 & 0 & 1 & -(n+f)/2\\ 0 & 0 & 0 & 1 \end{bmatrix}

Scale就更简单了,l到r缩放到-1到1,缩放因子就是2 / (r - l),其他同理。

O_s= \begin{bmatrix} 2/(r-l) & 0 & 0 & 0\\ 0 & 2/(t-b) & 0 & 0\\ 0 & 0 & 2/(f-n) & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

正交投影矩阵是:

O = O_s\times O_t = \begin{bmatrix} 2/(r-l) & 0 & 0 & -(l+r)/(r-l)\\ 0 & 2/(t-b) & 0 & -(t+b)/(t-b)\\ 0 & 0 & 2/(f-n) & (n+f)/(n-f)\\ 0 & 0 & 0 & 1 \end{bmatrix}

4.透视投影的推导

参考闫令琪的教程,透视投影就是先把Frustum变换到一个box,然后再进行正交投影的过程。

先看这个连接,https://sites.cs.ucsb.edu/~lingqi/teaching/resources/GAMES101_Lecture_04.pdf

后面我再在这里写过程,并把闫令琪留给我们的问题写出来。

首先,齐次坐标的表示:

(x, y, z, 1),(wx, wy, wz, w != 0),(xz, yz, z², z != 0)均表示同一个点。

下一步,如何把frustum变换到正交投影的box?

侧视图:

y和y'的转换可写成:y' = \frac{y}{z}nx'=\frac{x}{z}n

那么我们要找到一个矩阵,可以把(x, y, z, 1)变换到坐标(x', y', ?, 1) = (yn/z, xn/z, ? 1) = (yn, xn, ? z)

一矩阵乘法的形式表示:

M_{persp\rightarrow ortho} \times \begin{pmatrix} x\\ y\\ z\\ 1 \end{pmatrix} = \begin{pmatrix} nx\\ ny\\ ?\\ z \end{pmatrix}

根据矩阵乘法,row_1 \cdot (x, y, z, 1) = nx,row1 = (n, 0, 0, 0),row2和row4也是如此

M_{persp\rightarrow ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ ? & ? & ? & ?\\ 0 & 0 & 1 & 0 \end{bmatrix}

关键第三行如何求?

但z = n时,经过该矩阵M_{persp\rightarrow ortho}的转换后仍然是n

\begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ ? & ? & ? & ?\\ 0 & 0 & 1 & 0 \end{bmatrix} \times \begin{bmatrix} x\\ y\\ n\\ 1 \end{bmatrix} = \begin{bmatrix} nx/z\\ ny/z\\ n\\ 1 \end{bmatrix} = \begin{bmatrix} nx\\ ny\\ n^2\\ n \end{bmatrix}

点乘法则:

\begin{bmatrix} 0 & 0 & A & B \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ n\\ 1 \end{bmatrix} = n^2 \quad \Rightarrow An + B = n^2

当z = f时,仍然按上面的法则推导

\begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ ? & ? & ? & ?\\ 0 & 0 & 1 & 0 \end{bmatrix} \times \begin{bmatrix} x\\ y\\ f\\ 1 \end{bmatrix} = \begin{bmatrix} nx/z\\ ny/z\\ f\\ 1 \end{bmatrix} =\begin{bmatrix} nx\\ ny\\ f^2\\ f \end{bmatrix}

\begin{bmatrix} 0 & 0 & A & B \end{bmatrix} \cdot \begin{bmatrix} x\\ y\\ f\\ 1 \end{bmatrix} = f^2 \quad \Rightarrow Af + B = f^2

解方程组求A,B得:

A = n + f

B = -nf

M_{persp\rightarrow ortho} = \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{bmatrix}

最后投影矩阵:

M_{persp} = M_{ortho} \times M_{persp\rightarrow ortho} \\ = \begin{bmatrix} 2/(r-l) & 0 & 0 & -(l+r)/(r-l)\\ 0 & 2/(t-b) & 0 & -(t+b)/(t-b)\\ 0 & 0 & 2/(f-n) & (n+f)/(n-f)\\ 0 & 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} n & 0 & 0 & 0\\ 0 & n & 0 & 0\\ 0 & 0 & n+f & -nf\\ 0 & 0 & 1 & 0 \end{bmatrix} \\ = \begin{bmatrix} 2n/(r-l) & 0 & -(l+r)/(r-l) & 0\\ 0 & 2n/(t-b) & -(t+b)/(t-b) & 0\\ 0 & 0 & 2(n+f)/(f-n) & -2nf/(f-n)\\ 0 & 0 & 1 & 0 \end{bmatrix}

另一种方式的投影矩阵

假设摄像机坐标本来就已经在原点,l + r = 0,t + b=0。

并且r - l = width,t - b = height

投影矩阵可以写成:

M_{persp} = \begin{bmatrix} 2n/width & 0 & 0 & 0\\ 0 & 2n/height & 0 & 0\\ 0 & 0 & 2(n+f)/(f-n) & -2nf/(f-n)\\ 0 & 0 & 1 & 0 \end{bmatrix}

摄像机垂直方向的视角是fov,如下图:

再看下面的式子:

tan(\frac{fov}{2}) = \frac{height}{2n} \\ n = \frac{height}{2tan(\frac{fov}{2})} \\ aspect = \frac{width}{height}

投影矩阵可以最后写成:

M_{persp} = \begin{bmatrix} \frac{1}{tan(fov/2)aspect} & 0 & 0 & 0\\ 0 & \frac{1}{tan(fov/2)} & 0 & 0\\ 0 & 0 & 2(n+f)/(f-n) & -2nf/(f-n)\\ 0 & 0 & 1 & 0 \end{bmatrix}

如果正交投影中,变换到一个在z是0-1的box,只需要修改Ot和Os矩阵:

O_{t} = \begin{bmatrix} 1 & 0 & 0 & -(l+r)/2 \\ 0 & 1 & 0 & -(t+b)/2\\ 0 & 0 & 1 & -n\\ 0 & 0 & 0 & 1 \end{bmatrix}

O_s= \begin{bmatrix} 2/(r-l) & 0 & 0 & 0\\ 0 & 2/(t-b) & 0 & 0\\ 0 & 0 & 1/(f-n) & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}

O = O_s\times O_t = \begin{bmatrix} 2/(r-l) & 0 & 0 & -(l+r)/(r-l)\\ 0 & 2/(t-b) & 0 & -(t+b)/(t-b)\\ 0 & 0 & 1/(f-n) & n/(n-f)\\ 0 & 0 & 0 & 1 \end{bmatrix}

这种情况下的投影矩阵可写成:

M_{persp} = \begin{bmatrix} \frac{1}{tan(fov/2)aspect} & 0 & 0 & 0\\ 0 & \frac{1}{tan(fov/2)} & 0 & 0\\ 0 & 0 & f/(f-n) & -nf/(f-n)\\ 0 & 0 & 1 & 0 \end{bmatrix}

看一下z的变化:

{z}' = \frac{fz}{(f-n)z} - \frac{nf}{(f-n)z} = \frac{zf - nf}{(f-n)z}

函数图大概是这样:

横轴是z,纵轴是z'(0,1)。

5.NDC坐标到屏幕坐标的转换

NDC中x是-1到1,y也是-1到1,而窗口大小分别是width和height。

下面是NDC的坐标与屏幕坐标的映射关系:

        

对应方程分别是:

x_{screen}=\frac{width}{2}x+\frac{width}{2}

y_{screen}=-\frac{height}{2}y+\frac{height}{2}

屏幕空间的z是0-1之间,我假设这里的NDC的z也是0-1,(opengl是-1,1),z对应的变换如下:

z_{screen}=z

z_{screen}=\frac{1}{2}z+\frac{1}{2} \qquad (opengl)

因此得到NDC到屏幕坐标的矩阵S。

S= \begin{bmatrix} width/2 & 0 & 0 & width/2 \\ -height/2 & 0 & 0 & height/2 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0\end{bmatrix}

S_{opengl}= \begin{bmatrix} width/2 & 0 & 0 & width/2 \\ -height/2 & 0 & 0 & height/2 \\ 0 & 0 & 0.5 & 0.5 \\ 0 & 0 & 0 & 0\end{bmatrix}

做后屏幕坐标就是:

P_{screen} = S \times P_{NDC}

所以,世界坐标到屏幕坐标的最后映射关系是:

P_{screen} = S \times O \times C\times P_{world}

 

  • 12
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
透视投影变换矩阵的推导过程如下: 假设有一个三维点 $(X,Y,Z)$,它在相机坐标系中的坐标为 $(X_c,Y_c,Z_c)$。相机坐标系的原点为相机位置,$Z_c$ 轴指向相机朝向的反方向,$X_c$ 和 $Y_c$ 轴分别与相机的右方向和下方向对齐。 为了把相机坐标系中的点映射到图像平面上,我们需要进行透视投影变换。首先,我们将相机坐标系中的点换为齐次坐标 $(X_c,Y_c,Z_c,1)$。然后,我们将它乘以一个投影矩阵 $P$,得到一个新的齐次坐标 $(u,v,w,1)$: $$ \begin{bmatrix} u \\ v \\ w \\ 1 \\ \end{bmatrix} = P \cdot \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ 1 \\ \end{bmatrix} $$ 其中,$u$ 和 $v$ 分别表示图像平面上的坐标,$w$ 用来进行透视除法,保证 $u$ 和 $v$ 的值在图像平面上。 投影矩阵 $P$ 可以分解为相机内参矩阵 $K$ 和相机外参矩阵 $[R|t]$ 的乘积: $$ P = K [R|t] $$ 其中,$K$ 是一个 $3 \times 3$ 的矩阵,包含了相机的内部参数,如焦距、主点等。$[R|t]$ 是一个 $3 \times 4$ 的矩阵,包含了相机的外部参数,如相机的旋和平移。 为了推导 $P$ 的具体形式,我们可以先考虑一个简单的情况:相机坐标系的原点与图像平面重合,且相机的朝向与图像平面平行。这种情况下,投影矩阵可以表示为: $$ P = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} $$ 其中,$f$ 是焦距,表示相机到图像平面的距离。 当相机坐标系的原点和图像平面不重合时,我们可以使用相机外参矩阵 $[R|t]$ 来把相机坐标系的原点变换到图像平面上。具体来说,我们可以将相机坐标系的原点变换为 $(X_c',Y_c',Z_c')$,其中 $(X_c',Y_c',0)$ 是图像平面上的点。这个变换可以表示为: $$ \begin{bmatrix} X_c' \\ Y_c' \\ Z_c' \\ 1 \\ \end{bmatrix} = [R|t] \cdot \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \\ \end{bmatrix} $$ 然后,我们可以把 $(X,Y,Z)$ 变换为 $(X',Y',Z')$,其中 $(X',Y')$ 是图像平面上的坐标。这个变换可以表示为: $$ \begin{bmatrix} X' \\ Y' \\ Z' \\ 1 \\ \end{bmatrix} = [R|t] \cdot \begin{bmatrix} X \\ Y \\ Z \\ 1 \\ \end{bmatrix} $$ 最后,我们可以将 $(X',Y',Z')$ 投影到图像平面上,得到一个新的齐次坐标 $(u,v,w,1)$。这个投影可以表示为: $$ \begin{bmatrix} u \\ v \\ w \\ 1 \\ \end{bmatrix} = K \cdot \begin{bmatrix} X'/Z' \\ Y'/Z' \\ 1 \\ \end{bmatrix} $$ 将以上三个变换组合起来,我们可以得到透视投影变换矩阵的形式: $$ P = K [R|t] = \begin{bmatrix} f_x & 0 & c_x & 0 \\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \\ \end{bmatrix} $$ 其中,$f_x$ 和 $f_y$ 是 $K$ 矩阵的对角线元素,分别表示 $x$ 和 $y$ 方向上的焦距;$c_x$ 和 $c_y$ 是 $K$ 矩阵的中心点,表示图像平面上的主点;$r_{ij}$ 和 $t_i$ 是 $[R|t]$ 矩阵的元素,表示相机的旋和平移。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值