齐次坐标
来由
齐次坐标由August Ferdinand Möbius(奥古斯特·费迪南德·莫比乌斯)在1827年提出,最初用于解决射影几何中的问题。在欧几里得几何中,平行线永不相交,但在射影几何中,平行线在无穷远处相交。为了统一处理这些情况,引入了齐次坐标。
原理
齐次坐标通过增加一个维度来表示点。例如,在二维空间中,点 ((x, y)) 的齐次坐标表示为 ((x, y, w)),其中 (w) 是额外的坐标。通常,(w = 1),因此点 ((x, y)) 的齐次坐标为 ((x, y, 1))。
齐次坐标是一种用 N+1 个数字表示 N 维坐标的方法。
要制作 2D 齐次坐标,我们只需在现有坐标中添加一个额外的变量 w。因此,笛卡尔坐标中的点 (X, Y) 变为齐次坐标中的 (x, y, w)。笛卡尔中的 X 和 Y 用齐次 as 中的 x、y 和 w 重新表示;
X = x/w
Y = y/w
例如,笛卡尔 (1, 2) 中的一个点在齐次中变为 (1, 2, 1)。如果一个点 (1, 2) 向无穷大移动,则它在笛卡尔坐标中变为 (∞,∞)。在齐次坐标中,由于 (1/0, 2/0) ≈ (∞,∞),它在齐次坐标中变为 (1, 2, 0)。请注意,我们可以在不使用 “∞” 的情况下表示无穷远处的点.
在图形处理时,如D3D11时,一般将3维扩展到4维(x,y,z,1),这样就可以统一进行平移旋转缩放等功能。
关键点
- 无穷远点:当 (w = 0) 时,((x, y, 0)) 表示无穷远点,用于描述平行线的交点。
- 缩放不变性:齐次坐标 ((x, y, w)) 与 ((kx, ky, kw))((k \neq 0))表示同一个点,具有缩放不变性。
- 统一变换:齐次坐标允许用单一的矩阵乘法表示平移、旋转、缩放等变换,简化了几何变换的计算。
应用
- 计算机图形学:用于表示和操作三维物体的变换。
- 机器人学:描述机械臂的运动和位置。
- 计算机视觉:用于相机模型和图像投影。
示例
在二维空间中,点 ((2, 3)) 的齐次坐标为 ((2, 3, 1))。平移变换可以通过矩阵乘法实现:
同质
如前所述,为了将齐次坐标 (x, y, w) 转换为笛卡尔坐标,我们只需将 x 和 y 除以 w;
将 Homogeneous 转换为 Cartesian,我们可以找到一个重要的事实。让我们看看下面的例子;
如您所见,齐次点 (1, 2, 3)、(2, 4, 6)、(3, 6, 9) 和 (4, 8, 12) 对应于同一个欧几里得点 (1/3, 2/3)。任何标量积 (1a, 2a, 3a) 都与欧几里得空间中的 (1/3, 2/3) 相同。因此,这些点是“齐次的”,因为它们表示欧几里得空间(或笛卡尔空间)中的同一点。换句话说,齐次坐标是尺度不变的。
(1,2,3) (2,4,6) 和 (3,6,9) 是相同的笛卡尔点 (1/3, 2/3)。所有齐次点(1a、2a、3a)都在橙色线上。
您可以将齐次坐标的 w 值想象成从电视投影仪到屏幕的距离。当 w 值增加时,屏幕会远离投影仪。
齐次坐标系两条平行线的相交证明
考虑以下欧几里得空间中的线性系统;
而且我们知道,由于 C ≠ D,上述方程没有解,即平行。
如果 C = D,则两条线相同(重叠)。
让我们通过将 x 和 y 分别替换为 x/w、y/w 来重写投影空间的方程。
现在,我们有一个解 (x, y, 0),其中 w = 0。
因此,两条平行线在 (x, y, 0) 处相交,即无穷远处的点。
齐次坐标在计算机图形学中是非常有用的基本概念,例如将 3D 场景投影到 2D 平面上。
总结
齐次坐标通过增加一个维度,统一处理有限点和无穷远点,简化了几何变换的表示和计算,广泛应用于多个领域。
齐次坐标与透视投影的关系?
https://jia.je/kb/software/cg.html#_5
透视投影要做的是把一个四棱台(Square Frustum,四棱锥水平切开,底面和顶面是正方形,其余四个面都是梯形)映射到 NDC 上。其中四棱台的四条棱延长以后,交于原点。也就是说焦点就是坐标轴的原点。
相比正交投影,透视投影最大的不同在于它近大远小的特性,更加贴近实际:正交投影无论深度多少,看到的物体大小不变;而在透视投影中,从原点出发,到 near 平面上的一点连成射线,这条射线上的点都对应同一个屏幕上的点,因此远的物体在屏幕上看的小,近的物体在屏幕上看得大。
因此在实现透视投影的时候,就要利用这条从原点出发到 near 平面的一点的射线:由于这条射线上的点都对应屏幕上同一个点,因此在 NDC 中也对应同一个(x’,y’) 坐标。那么,在计算x’和y’的时候,先利用相似三角形关系,把点映射到 near 平面上(near 平面的 Z 坐标是 z=-n ):
这样就得到了四棱台到长方体的映射,但是这里涉及到对z的除法运算,为了在矩阵中实现针对z的除法运算,需要利用齐次坐标自带的除法:(x,y,z,w)->(x/w,y/w,z/w,)也就是说,把 z 的值挪到w 上,就相当于实现了除法。按照这个思路,可以得到下面的矩阵:
其中A 和B 是未知数。验证一下上面的矩阵是否实现了除法:
首先是生成齐次坐标:
矩阵变换以后:
// Source: https://github.com/Mesa3D/mesa/blob/957009978ef6d7121fc0d710d03bc20097d4d46b/src/mesa/math/m_matrix.c#L773-L797
void
_math_matrix_frustum( GLmatrix *mat,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval )
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
x = (2.0F*nearval) / (right-left);
y = (2.0F*nearval) / (top-bottom);
a = (right+left) / (right-left);
b = (top+bottom) / (top-bottom);
c = -(farval+nearval) / ( farval-nearval);
d = -(2.0F*farval*nearval) / (farval-nearval); /* error? */
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE );
}