0. 写在前面
在3dmm中,重要的一步是对3d模型进行拍照。
这里引出问题:怎么给3d模型拍照?
下面解决这个拍照问题。
1. 相机模型
本节目标:
理解针孔相机的模型,内参与径向畸变参数。
理解一个空间点是如何投影到相机成像。
我们知道:
一张照片(二维):由多个像素组成,每个像素记录了色彩或亮度的信息。
一个物体(三维世界):物体反射或发出的光线,通过相机光心后,投影到相机的成像平面。
相机将三维世界中的坐标点(单位米)映射到二维图像平面(单位像素)的过程能够用一个几何模型进行描述。
这个模型有很多种,其中最简单的为针孔模型 。事实上,真实的相机镜头是透镜,会使得光线投影到成像平面的过程会产生畸变。
那么总结一下,所谓相机模型实际是是:针孔相机模型+畸变模型。
在3dmm中我们暂不考虑畸变模型。
1.1 针孔相机模型 (Pinhole camera)
在小孔成像过程中,小孔模型将三维世界中的蜡烛投影到一个二维成像平面。
首先我们要先认识一下4种坐标:
世界坐标 (World reference system)
相机坐标 (camera coordinate)
归一化相机坐标 (normalized coordinate)
像素坐标 (pixel coordinate)
我们来品一下这张图><。
世界坐标 是我们客观存在的世界,它有自己的固有坐标。在这里我们定义三维空间的三个方向分别为:x w , y w , z w x_w, y_w, z_w x w , y w , z w 例子 :
例子1: 长城。它就存在在那里,有它自己的坐标。
例子2: 3d模型。3d模型在计算机中是以点的坐标来存储的,这个坐标代表点在x w , y w , z w x_w, y_w, z_w x w , y w , z w 三个方向上的大小,比如一个点B B B ,它的存储形式是( 12 , 15 , 18 ) (12, 15,
18) ( 1 2 , 1 5 , 1 8 ) 。这样的点有n n n 个,在3dmm中实际上有53215个这样的三维点,这些点组成了基本的人脸3d模型。
相机坐标 是从相机的角度去看世界,相机本身是这个坐标系的原点。
在这里我们定义在这个角度的三维空间的三个方向分别为:x c , y c , z c x_c, y_c, z_c x c , y c , z c 例子 :
例子1: 小时候我总觉得门前的山特别高,后来长大之后回到老地方,发现这个山也没那么高嘛。山变了吗?山没变,是我看山的角度变了。
例子2: 正所谓【横看成岭侧成峰】,说的也是这回事。
归一化相机坐标 物理成像平面。在这里我们可以定义三维空间的三个方向分别为:x n , y n , z n x_n, y_n, z_n x n , y n , z n
原点O ˊ \acute O O ˊ 是相机坐标的z c z_c z c 轴与物理成像平面的交点。一般取z n z_n z n 的方向与z c z_c z c 方向相同,将点P P P 在针孔相机模型到物理成像平面的距离统一为z n = f z_n = f z n = f ,其中f f f 为焦距,这就相当于对相机坐标进行归一化。
像素坐标 水平方向是U,垂直方向是V,通过这个平面的,二维的UV坐标系。我们可以定位图象上的任意一个像素。
注意 这里的像素坐标的单位是像素,而上述3个坐标系的单位为米。
在这里我们定义二维空间的二个方向分别为:u , v u, v u , v
1.2 计算过程
================== 计算过程(1) 从世界坐标到相机坐标 ==================
已知 我们有一个点P P P ,它的世界坐标(我们常说的坐标)为:P w = [ x w y w z w ] P_w =\begin{bmatrix} x_w \\ y_w \\ z_w \end{bmatrix} P w = ⎣ ⎡ x w y w z w ⎦ ⎤
这个点P P P ,它在相机视角下的坐标为:P c = [ x c y c z c ] P_c=\begin{bmatrix} x_c \\ y_c \\ z_c \end{bmatrix} P c = ⎣ ⎡ x c y c z c ⎦ ⎤
我们知道P w P_w P w 和P c P_c P c 是同一点在不同坐标系下的表达方式,那么P w P_w P w 和P c P_c P c 之间是什么关系呢?其实是:
P w P_w P w 旋 转 变 换 + 平 移 变 换 → \underrightarrow{旋转变换+平移变换} 旋 转 变 换 + 平 移 变 换 P c P_c P c
这里需要引入一下齐次坐标 的概念。
齐次坐标就是将一个原本是n维的向量 用一个n+1维向量来表示,是指一个用于投影几何里的坐标系统,如同用于欧氏几何里的笛卡儿坐标一般。
比如从欧式坐标变换到齐次坐标时,即欧 式 坐 标 → 齐 次 坐 标 欧式坐标 \rightarrow 齐次坐标 欧 式 坐 标 → 齐 次 坐 标 :( x , y ) = [ x y z ] (x, y) = \begin{bmatrix} x \\ y\\ z\\ \end{bmatrix} ( x , y ) = ⎣ ⎡ x y z ⎦ ⎤ ( x , y , z ) = [ x y z 1 ] (x, y, z) = \begin{bmatrix} x \\ y\\ z\\ 1 \\\end{bmatrix} ( x , y , z ) = ⎣ ⎢ ⎢ ⎡ x y z 1 ⎦ ⎥ ⎥ ⎤
从齐次坐标变换到欧式坐标时,即齐 次 坐 标 → 欧 式 坐 标 齐次坐标 \rightarrow 欧式坐标 齐 次 坐 标 → 欧 式 坐 标 :
[ x y w ] = ( x w , y w ) \begin{bmatrix} x \\ y\\ w\\ \end{bmatrix} = (\frac{x}{w}, \frac{y}{w}) ⎣ ⎡ x y w ⎦ ⎤ = ( w x , w y ) [ x y z w ] = ( x w , y w , z w ) \begin{bmatrix} x \\ y\\ z\\ w \\ \end{bmatrix} = (\frac{x}{w}, \frac{y}{w},\frac{z}{w}) ⎣ ⎢ ⎢ ⎡ x y z w ⎦ ⎥ ⎥ ⎤ = ( w x , w y , w z )
接下来回到P w P_w P w 旋 转 变 换 + 平 移 变 换 → \underrightarrow{旋转变换+平移变换} 旋 转 变 换 + 平 移 变 换 P c P_c P c 。
(1)旋转变换
R x ( α ) = [ 1 0 0 0 cos α − sin α 0 sin α cos α ] R_x(\alpha) = \begin{bmatrix}\ 1 & 0 &0 \\ 0 & \cos \alpha & -\sin \alpha \\ 0 &\sin \alpha &\cos \alpha \\ \end{bmatrix} R x ( α ) = ⎣ ⎡ 1 0 0 0 cos α sin α 0 − sin α cos α ⎦ ⎤ R y ( β ) = [ cos β 0 sin β 0 1 0 − sin β 0 cos β ] R_y(\beta) = \begin{bmatrix}\ \cos \beta& 0 & \sin \beta\\ 0 & 1 & 0 \\ - \sin \beta& 0 & \cos \beta\\ \end{bmatrix} R y ( β ) = ⎣ ⎡ cos β 0 − sin β 0 1 0 sin β 0 cos β ⎦ ⎤ R x ( γ ) = [ cos γ − sin γ 0 sin γ cos γ 0 0 0 1 ] R_x(\gamma) = \begin{bmatrix}\cos \gamma & -\sin \gamma & 0\\ \sin \gamma & \cos \gamma & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} R x ( γ ) = ⎣ ⎡ cos γ sin γ 0 − sin γ cos γ 0 0 0 1 ⎦ ⎤
此时:R = R x ( α ) R y ( β ) R x ( γ ) R = R_x(\alpha) R_y(\beta) R_x(\gamma) R = R x ( α ) R y ( β ) R x ( γ )
(2)平移变换T = [ T x T y T z ] T = \begin{bmatrix} T_x \\ T_y\\ T_z\\ \end{bmatrix} T = ⎣ ⎡ T x T y T z ⎦ ⎤
结合(1)(2),那么对于点P P P (下角标h _h h 表示齐次坐标):P h c = [ x c y c z c 1 ] = [ R T 0 1 ] 4 × 4 [ x w y w z w 1 ] 4 × 1 = [ R T 0 1 ] 4 × 4 P h w P_{hc} = \begin{bmatrix} x_c \\ y_c\\ z_c\\ 1 \\ \end{bmatrix} = \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} \begin{bmatrix} x_w \\ y_w\\ z_w\\ 1\end{bmatrix} _{4\times1 } = \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} P_{hw} P h c = ⎣ ⎢ ⎢ ⎡ x c y c z c 1 ⎦ ⎥ ⎥ ⎤ = [ R 0 T 1 ] 4 × 4 ⎣ ⎢ ⎢ ⎡ x w y w z w 1 ⎦ ⎥ ⎥ ⎤ 4 × 1 = [ R 0 T 1 ] 4 × 4 P h w
================== 计算过程(2) 从相机坐标到像素坐标 ==================
由图可知:
△ O O ˊ P ˊ △O \acute O \acute P △ O O ˊ P ˊ 与△ O P ˊ P ˊ ˊ △O \acute P\acute {\acute P} △ O P ˊ P ˊ ˊ 相似,那么对于点P P P 在相机坐标下的表示P c = [ x c y c z c ] P_c = \begin{bmatrix} x_c \\ y_c\\ z_c \end{bmatrix} P c = ⎣ ⎡ x c y c z c ⎦ ⎤ 及在归一化相机坐标系里的表现P n = [ x n y n z n ] P_n = \begin{bmatrix} x_n \\ y_n\\ z_n \end{bmatrix} P n = ⎣ ⎡ x n y n z n ⎦ ⎤ , (z n = f z_n = f z n = f ):x n = f x c z c x_n = f \frac{x_c}{z_c} x n = f z c x c y n = f y c z c y_n = f \frac{y_c}{z_c} y n = f z c y c
接下来要从归一化相机坐标系继续变换到像素坐标系,归一化相机坐标系与像素坐标系之间,相差了一个缩放 和原点的平移 。
我们设像素坐标在u u u 轴上缩放了α \alpha α 倍,在v v v 轴上缩放了β \beta β 倍。同时,原点平移了 [ c x c y ] \begin{bmatrix} c_x \\ c_y \end{bmatrix} [ c x c y ] ,那么像素坐标系下的P u v P_{uv} P u v 与归一化相机坐标系下的P n P_n P n 的关系为:u = α x n + c x = α f x c z c + c x u = \alpha x_n + c_x = \alpha f \frac{x_c}{z_c} + c_x u = α x n + c x = α f z c x c + c x v = β y n + c y = β f y c z c + c y v = \beta y_n+ c_y =\beta f \frac{y_c}{z_c} + c_y v = β y n + c y = β f z c y c + c y
我们设α f = f x \alpha f = f_x α f = f x , β f = f y \beta f = f_y β f = f y ,得到:u = f x x c z c + c x u = f_x \frac{x_c}{z_c} + c_x u = f x z c x c + c x v = f y y c z c + c y v = f_y\frac{y_c}{z_c} + c_y v = f y z c y c + c y
上述内容总结一下,用齐次坐标来表示:P h u v = [ u v 1 ] = [ f x x c z c + c x f y y c z c + c y 1 ] P_{huv} = \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} {f_x \frac{x_c}{z_c} + c_x} \\ f_y\frac{y_c}{z_c} + c_y \\ 1 \end{bmatrix} P h u v = ⎣ ⎡ u v 1 ⎦ ⎤ = ⎣ ⎡ f x z c x c + c x f y z c y c + c y 1 ⎦ ⎤
因为齐次坐标乘以非零常数后表达相同含义:
[ u v 1 ] = [ f x x c z c + c x f y y c z c + c y 1 ] = [ f x x c + c x z c f y y c + c y z c z c ] \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} {f_x \frac{x_c}{z_c} + c_x} \\ f_y\frac{y_c}{z_c} + c_y \\ 1 \end{bmatrix} = \begin{bmatrix} f_x x_c + c_x z_c \\ f_y y_c + c_y z_c\\ z_c \end{bmatrix} ⎣ ⎡ u v 1 ⎦ ⎤ = ⎣ ⎡ f x z c x c + c x f y z c y c + c y 1 ⎦ ⎤ = ⎣ ⎡ f x x c + c x z c f y y c + c y z c z c ⎦ ⎤ = [ f x 0 c x 0 f y c y 0 0 1 ] [ x c y c z c ] = \begin{bmatrix} f_x & 0 &c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_c \\ y_c \\ z_c \end{bmatrix} = ⎣ ⎡ f x 0 0 0 f y 0 c x c y 1 ⎦ ⎤ ⎣ ⎡ x c y c z c ⎦ ⎤
回忆一下的(1)部分的结果:P h c = [ x c y c z c 1 ] = [ R T 0 1 ] 4 × 4 [ x w y w z w 1 ] 4 × 1 = [ R T 0 1 ] 4 × 4 P h w P_{hc} = \begin{bmatrix} x_c \\ y_c\\ z_c\\ 1 \\ \end{bmatrix} = \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} \begin{bmatrix} x_w \\ y_w\\ z_w\\ 1\end{bmatrix} _{4\times1 } = \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} P_{hw} P h c = ⎣ ⎢ ⎢ ⎡ x c y c z c 1 ⎦ ⎥ ⎥ ⎤ = [ R 0 T 1 ] 4 × 4 ⎣ ⎢ ⎢ ⎡ x w y w z w 1 ⎦ ⎥ ⎥ ⎤ 4 × 1 = [ R 0 T 1 ] 4 × 4 P h w
这里的P c h P_{ch} P c h 是P c P_c P c 齐次坐标,为了将这一部分带入[ u v 1 ] \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} ⎣ ⎡ u v 1 ⎦ ⎤ ,[ u v 1 ] = [ f x x c z c + c x f y y c z c + c y 1 ] \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} {f_x \frac{x_c}{z_c} + c_x} \\ f_y\frac{y_c}{z_c} + c_y \\ 1 \end{bmatrix} ⎣ ⎡ u v 1 ⎦ ⎤ = ⎣ ⎡ f x z c x c + c x f y z c y c + c y 1 ⎦ ⎤ = [ f x x c + c x z c f y y c + c y z c z c ] = \begin{bmatrix} f_x x_c + c_x z_c \\ f_y y_c + c_y z_c\\ z_c \end{bmatrix} = ⎣ ⎡ f x x c + c x z c f y y c + c y z c z c ⎦ ⎤ = [ f x 0 c x 0 f y c y 0 0 1 ] [ x c y c z c ] = \begin{bmatrix} f_x & 0 &c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_c \\ y_c \\ z_c \end{bmatrix} = ⎣ ⎡ f x 0 0 0 f y 0 c x c y 1 ⎦ ⎤ ⎣ ⎡ x c y c z c ⎦ ⎤                                ↑ \,\,\,\,\,\, \,\,\,\,\,\,\, \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\uparrow ↑
我们称这个矩阵为内部参数K K K ,
= [ f x 0 c x 0 0 f y c y 0 0 0 1 0 ] 3 × 4 [ x c y c z c 1 ] 4 × 1 =\begin{bmatrix} f_x & 0 &c_x & 0\\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}_{3 \times 4} \begin{bmatrix} x_c \\ y_c \\ z_c \\ 1 \end{bmatrix}_{4 \times 1} = ⎣ ⎡ f x 0 0 0 f y 0 c x c y 1 0 0 0 ⎦ ⎤ 3 × 4 ⎣ ⎢ ⎢ ⎡ x c y c z c 1 ⎦ ⎥ ⎥ ⎤ 4 × 1                                ↑                                  ↑ \,\,\,\,\,\, \,\,\,\,\,\,\, \,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\uparrow\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\,\, \,\ \,\,\, \,\,\,\,\,\,\,\,\,\,\uparrow ↑ ↑
这可以写作K [ I 0 ] K \begin{bmatrix} I & 0 \end{bmatrix} K [ I 0 ]                 \,\,\,\,\,\, \,\,\,\,\,\,\,\,\, 是不是很眼熟,这不是P c P_c P c 的齐次坐标嘛!
= [ f x 0 c x 0 0 f y c y 0 0 0 1 0 ] 3 × 4 [ R T 0 1 ] 4 × 4 [ x w y w z w 1 ] 4 × 1 = \begin{bmatrix} f_x & 0 &c_x & 0\\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}_{3 \times 4} \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} \begin{bmatrix} x_w \\ y_w\\ z_w\\ 1\end{bmatrix} _{4\times1 } = ⎣ ⎡ f x 0 0 0 f y 0 c x c y 1 0 0 0 ⎦ ⎤ 3 × 4 [ R 0 T 1 ] 4 × 4 ⎣ ⎢ ⎢ ⎡ x w y w z w 1 ⎦ ⎥ ⎥ ⎤ 4 × 1
= K [ I 0 ] [ R T 0 1 ] P h w =K\begin{bmatrix} I & 0 \end{bmatrix} \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}P_{hw} = K [ I 0 ] [ R 0 T 1 ] P h w
= K [ R T ] P h w =K\begin{bmatrix} R & T \end{bmatrix} P_{hw} = K [ R T ] P h w
============================== 总结 ==============================
[ u v 1 ] = [ f x 0 c x 0 0 f y c y 0 0 0 1 0 ] 3 × 4 [ R T 0 1 ] 4 × 4 [ x w y w z w 1 ] 4 × 1 \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} f_x & 0 &c_x & 0\\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}_{3 \times 4} \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} \begin{bmatrix} x_w \\ y_w\\ z_w\\ 1\end{bmatrix} _{4\times1 } ⎣ ⎡ u v 1 ⎦ ⎤ = ⎣ ⎡ f x 0 0 0 f y 0 c x c y 1 0 0 0 ⎦ ⎤ 3 × 4 [ R 0 T 1 ] 4 × 4 ⎣ ⎢ ⎢ ⎡ x w y w z w 1 ⎦ ⎥ ⎥ ⎤ 4 × 1
即:P h u v = K [ R T ] P h w P_{huv} = K\begin{bmatrix} R & T \end{bmatrix} P_{hw} P h u v = K [ R T ] P h w
当我们有一个3d模型的n个点的三维坐标,可以通过这个变换得到它的照片。
2. 例子 + 代码
比如以我们提到的点B B B 为例,它的世界坐标是( 12 , 15 , 18 ) (12, 15,
18) ( 1 2 , 1 5 , 1 8 ) 。
================== 计算过程(1) 从世界坐标到相机坐标 ==================
(1)旋转变换
R x ( α ) = [ 1 0 0 0 cos α − sin α 0 sin α cos α ] R_x(\alpha) = \begin{bmatrix}\ 1 & 0 &0 \\ 0 & \cos \alpha & -\sin \alpha \\ 0 &\sin \alpha &\cos \alpha \\ \end{bmatrix} R x ( α ) = ⎣ ⎡ 1 0 0 0 cos α sin α 0 − sin α cos α ⎦ ⎤ R y ( β ) = [ cos β 0 sin β 0 1 0 − sin β 0 cos β ] R_y(\beta) = \begin{bmatrix}\ \cos \beta& 0 & \sin \beta\\ 0 & 1 & 0 \\ - \sin \beta& 0 & \cos \beta\\ \end{bmatrix} R y ( β ) = ⎣ ⎡ cos β 0 − sin β 0 1 0 sin β 0 cos β ⎦ ⎤ R x ( γ ) = [ cos γ − sin γ 0 sin γ cos γ 0 0 0 1 ] R_x(\gamma) = \begin{bmatrix}\cos \gamma & -\sin \gamma & 0\\ \sin \gamma & \cos \gamma & 0 \\ 0 & 0 & 1 \\ \end{bmatrix} R x ( γ ) = ⎣ ⎡ cos γ sin γ 0 − sin γ cos γ 0 0 0 1 ⎦ ⎤
此时:R = R x ( α ) R y ( β ) R x ( γ ) R = R_x(\alpha) R_y(\beta) R_x(\gamma) R = R x ( α ) R y ( β ) R x ( γ )
def angle2matrix ( angles) :
'''
根据右手系三个旋转角,
得到三个旋转矩阵。
Args:
angles: [3,]. x, y, z angles
x: pitch. positive for looking down.
y: yaw. positive for looking left.
z: roll. positive for tilting head right.
Returns:
R: [3, 3]. rotation matrix.
'''
x, y, z = np. deg2rad( angles[ 0 ] ) , np. deg2rad( angles[ 1 ] ) , np. deg2rad( angles[ 2 ] )
Rx= np. array( [ [ 1 , 0 , 0 ] ,
[ 0 , cos( x) , - sin( x) ] ,
[ 0 , sin( x) , cos( x) ] ] )
Ry= np. array( [ [ cos( y) , 0 , sin( y) ] ,
[ 0 , 1 , 0 ] ,
[ - sin( y) , 0 , cos( y) ] ] )
Rz= np. array( [ [ cos( z) , - sin( z) , 0 ] ,
[ sin( z) , cos( z) , 0 ] ,
[ 0 , 0 , 1 ] ] )
R= Rz. dot( Ry. dot( Rx) )
return R. astype( np. float32)
(2)平移变换T = [ T x T y T z ] T = \begin{bmatrix} T_x \\ T_y\\ T_z\\ \end{bmatrix} T = ⎣ ⎡ T x T y T z ⎦ ⎤
结合(1)(2),那么对于点P P P :P h c = [ x c y c z c 1 ] = [ R T 0 1 ] 4 × 4 [ x w y w z w 1 ] 4 × 1 = [ R T 0 1 ] 4 × 4 P h w P_{hc} = \begin{bmatrix} x_c \\ y_c\\ z_c\\ 1 \\ \end{bmatrix} = \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} \begin{bmatrix} x_w \\ y_w\\ z_w\\ 1\end{bmatrix} _{4\times1 } = \begin{bmatrix} R& T \\ 0 & 1 \\ \end{bmatrix}_{4\times4} P_{hw} P h c = ⎣ ⎢ ⎢ ⎡ x c y c z c 1 ⎦ ⎥ ⎥ ⎤ = [ R 0 T 1 ] 4 × 4 ⎣ ⎢ ⎢ ⎡ x w y w z w 1 ⎦ ⎥ ⎥ ⎤ 4 × 1 = [ R 0 T 1 ] 4 × 4 P h w
def similarity_transform ( vertices, s, R, t3d) :
''' similarity transform. dof = 7.
3D: s*R.dot(X) + t
Homo: M = [[sR, t],[0^T, 1]]. M.dot(X)
Args:(float32)
vertices: [nver, 3].
s: [1,]. scale factor.
R: [3,3]. rotation matrix.
t3d: [3,]. 3d translation vector.
Returns:
transformed vertices: [nver, 3]
'''
t3d = np. squeeze( np. array( t3d, dtype = np. float32) )
transformed_vertices = s * vertices. dot( R. T) + t3d[ np. newaxis, : ]
return transformed_vertices
值得注意的是:函数angle2matrix(angles)中从世界坐标到相机坐标的计算并没有用到齐次坐标。只在欧式坐标下计算,P c = R 3 × 3 [ x w y w z w ] + [ T x T y T z ] P_c = R_{3 \times 3} \begin{bmatrix} x_w \\ y_w \\ z_w \end{bmatrix} + \begin{bmatrix} T_x \\ T_y \\ T_z \end{bmatrix} P c = R 3 × 3 ⎣ ⎡ x w y w z w ⎦ ⎤ + ⎣ ⎡ T x T y T z ⎦ ⎤ 这并没有关系,因为齐次坐标和非齐次坐标本质上并没有区别:P h c = [ x c y c z c 1 ]                         P c = [ x c y c z c ] P_{hc} = \begin{bmatrix} x_c \\ y_c\\ z_c\\ 1 \\ \end{bmatrix} \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, \, P_c = \begin{bmatrix} x_c \\ y_c\\ z_c\ \end{bmatrix} P h c = ⎣ ⎢ ⎢ ⎡ x c y c z c 1 ⎦ ⎥ ⎥ ⎤ P c = ⎣ ⎡ x c y c z c ⎦ ⎤ 只要在用的时候区分开就好。
我们之所以引入齐次坐标是为了直接计算P h u v = K [ R T ] P h w P_{huv} = K\begin{bmatrix} R & T \end{bmatrix} P_{hw} P h u v = K [ R T ] P h w 。
================== 计算过程(2) 从相机坐标到像素坐标 ==================
我们已经知道:
[ u v 1 ] = [ f x 0 c x 0 f y c y 0 0 1 ] [ x c y c z c ] \begin{bmatrix} u \\ v \\ 1 \end{bmatrix} = \begin{bmatrix} f_x & 0 &c_x \\ 0 & f_y & c_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix} x_c \\ y_c \\ z_c \end{bmatrix} ⎣ ⎡ u v 1 ⎦ ⎤ = ⎣ ⎡ f x 0 0 0 f y 0 c x c y 1 ⎦ ⎤ ⎣ ⎡ x c y c z c ⎦ ⎤
还原一下这个过程,相机坐标→ \rightarrow → 归一化相机坐标→ \rightarrow → 像素坐标。
(2.1) 相机坐标→ \rightarrow → 归一化相机坐标z n = f z_n = f z n = f x n = f x c z c x_n = f \frac{x_c}{z_c} x n = f z c x c y n = f y c z c y_n = f \frac{y_c}{z_c} y n = f z c y c
我们可以假设物品的深度 ,远远小于物体与相机间的距离 ,比如两个点i , j i,j i , j ,两个点的z c z_c z c 方向坐标z i ≈ z j z_i \approx z_j z i ≈ z j ,此时我们可以直接删去z c z_c z c 方向坐标,且归一化时我们取f = 1 f = 1 f = 1 :z n = f = 1 z_n = f = 1 z n = f = 1 x n = x c x_n = x_c x n = x c y n = y c y_n = y_c y n = y c
这样的映射也称为平行映射(orthographic project).
def orthographic_project ( vertices) :
return vertices. copy( )
这里的代码虽然保留z c z_c z c ,计算上其实我们只取x c , y c x_c, y_c x c , y c 。
(2.2) 归一化相机坐标→ \rightarrow → 像素坐标
设归一化相机坐标→ \rightarrow → 像素坐标时无缩放, 归一化相机坐标的圆心O ˊ \acute O O ˊ 落在像素为( w , h ) (w,h) ( w , h ) 的2d照片的中心,此时O ˊ \acute O O ˊ 在像素坐标系下的坐标为 ( w / 2 , h / 2 ) (w/2, h/2) ( w / 2 , h / 2 )
那么对于点B B B :
u = f x x c z c + c x = x c + w / 2 u = f_x \frac{x_c}{z_c} + c_x = x_c + w/2 u = f x z c x c + c x = x c + w / 2 v = f y y c z c + c y = − y c + h / 2 − 1 v = f_y\frac{y_c}{z_c} + c_y = -y_c + h/2 - 1 v = f y z c y c + c y = − y c + h / 2 − 1
def to_image ( vertices, h, w) :
'''
Args:
vertices: [nver, 3]
h: height of the rendering
w : width of the rendering
Returns:
projected_vertices: [nver, 3]
'''
image_vertices = vertices. copy( )
image_vertices[ : , 0 ] = image_vertices[ : , 0 ] + w/ 2
image_vertices[ : , 1 ] = image_vertices[ : , 1 ] + h/ 2
image_vertices[ : , 1 ] = h - image_vertices[ : , 1 ] - 1
return image_vertices
至此,得到三维点B B B 在照片里的像素坐标。