<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Clarency - 线性代数</title>
    <subtitle>My personal blog</subtitle>
    <link rel="self" type="application/atom+xml" href="https://luciddream.online/tags/xian-xing-dai-shu/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://luciddream.online"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-10-10T00:00:00+00:00</updated>
    <id>https://luciddream.online/tags/xian-xing-dai-shu/atom.xml</id>
    <entry xml:lang="en">
        <title>齐次坐标到底是什么？为什么要多加一个 w？</title>
        <published>2026-10-10T00:00:00+00:00</published>
        <updated>2026-10-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://luciddream.online/blog/homogeneous-coordinates/"/>
        <id>https://luciddream.online/blog/homogeneous-coordinates/</id>
        
        <content type="html" xml:base="https://luciddream.online/blog/homogeneous-coordinates/">&lt;p&gt;齐次坐标为什么要多加一个 w？为什么点通常写成 w = 1，向量却写成 w = 0？又为什么算完以后，还要除以 w？&lt;&#x2F;p&gt;
&lt;p&gt;我们先不急着给出定义，而是从平移这个具体问题出发，一步步看看这种表示方式是怎么来的。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yi-wei-shen-me-ping-yi-bu-neng-zhi-jie-yong-ju-zhen-cheng-fa&quot;&gt;一、为什么平移不能直接用矩阵乘法？&lt;&#x2F;h2&gt;
&lt;p&gt;理解齐次坐标，可以先从一个很具体的问题入手：&lt;strong&gt;为什么旋转、缩放都能用矩阵乘法来做，平移却不行？&lt;&#x2F;strong&gt; 普通笛卡尔坐标下，任何矩阵乘法都满足 M · 0 = 0，也就是说，线性变换必须把原点钉死在原点。你可以旋转，可以放大，可以把整个空间拉斜，但原点始终不能挪窝。&lt;&#x2F;p&gt;
&lt;p&gt;平移偏偏就要把原点挪走。比如向右移动 3，原点就应该从 (0, 0) 变成 (3, 0)。可不管怎么填一个 2 × 2 矩阵，把它乘上 (0, 0)，结果都只能是 (0, 0)。所以，二维空间里的非零平移，不能只靠一个 2 × 2 矩阵乘以二维坐标来完成；三维空间也一样，单靠一个 3 × 3 矩阵做不到，通常还得另外加上一个位移向量。&lt;&#x2F;p&gt;
&lt;p&gt;这样一来，一连串旋转、缩放、平移，就会把矩阵乘法和向量加法混在一起。虽然可以合成为“先乘一个矩阵，再加一个位移”，却不能直接把所有步骤写成同维度矩阵的连乘。如果能让平移也参与矩阵乘法，整条变换链就能统一合成一个矩阵，让所有顶点重复使用，传给 GPU 的接口也更统一。这正是多加一个分量首先要解决的问题。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;er-wei-li-zuo-bu-dao-na-jiu-sheng-yi-ge-wei-du-shi-shi&quot;&gt;二维里做不到，那就升一个维度试试&lt;&#x2F;h3&gt;
&lt;p&gt;想象一下，在水平的二维平面上添加一根竖着的 &lt;strong&gt;w 轴&lt;&#x2F;strong&gt;，把平面上的一个点沿 w 方向竖直向上拉成一条线，就像盖高楼，一层一层往上盖。w 轴是一根有刻度的数轴，w = 0、1、2、3……分别对应不同的高度。然后，轻轻地、水平地把这栋高楼推歪：底部不动，越往上，水平移动得越远。这里想象的是理想的线性推歪，钢筋骨架仍然是一条直线，不是真的把楼推弯了。&lt;&#x2F;p&gt;
&lt;p&gt;这个操作就是高一个维度里的&lt;strong&gt;错切，也叫切变（shear）&lt;&#x2F;strong&gt;。假设每升高一层，水平位移增加 t，那么第 w 层的水平位移就是 w · t：第一层移动 t，第二层移动 2t，第三层移动 3t。楼层只是方便理解的比喻，w 可以是小数，也可以是负数。把操作写成坐标变化，就是 (X, Y, w) → (X + w·tₓ, Y + w·tᵧ, w)。这里用大写 X、Y 表示升维后的分量，稍后会看到它们与普通二维坐标的区别。&lt;&#x2F;p&gt;
&lt;p&gt;平移量现在变成了“输入分量 w 乘上固定系数”，这正是矩阵乘法能够表达的形式。采用列向量写法，把 tₓ、tᵧ 放进 3 × 3 矩阵的最后一列，就能让 w 自动参与计算。&lt;strong&gt;只看 w = 1 这一层，移动量恰好就是 t，于是三维空间中的错切，在这一层上看起来就是普通的二维平移。&lt;&#x2F;strong&gt; 二维里的平移虽然不是线性变换，却可以通过升维后的线性变换来实现。&lt;&#x2F;p&gt;
&lt;p&gt;你可能会问：矩阵不是必须让原点不动吗，这里怎么又能动了？关键在于，我们把原来的二维原点放到了 (0, 0, 1)，而不是三维原点 (0, 0, 0)。三维原点仍然老老实实待在原地，被移走的是第一层上的那个点，线性变换的规则一点也没破坏。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;er-dian-wei-shen-me-yong-w-1-xiang-liang-wei-shen-me-yong-w-0&quot;&gt;二、点为什么用 w = 1，向量为什么用 w = 0？&lt;&#x2F;h2&gt;
&lt;p&gt;到这里，我们只是把二维点 (x, y) 放到三维空间里的 (x, y, 1)，就已经能用同一种矩阵乘法处理旋转、缩放和平移了。这些仿射变换的标准矩阵表示保持 w 不变。因此，如果只做这些操作，让所有点一直待在 w = 1 这一层，算完直接读出前两个分量就够了。&lt;&#x2F;p&gt;
&lt;p&gt;点表示的是“在哪里”，位移向量表示的则是“朝哪个方向、走多远”。把两个点一起平移，它们之间的位移并不会改变，因此位移向量不应受到平移的影响。&lt;&#x2F;p&gt;
&lt;p&gt;沿用高楼的比喻，只要把向量放在 w = 0 的底层，平移对应的错切就不会让它移动。代入前面的坐标变化也能看到：平移量乘上 w，也就是乘上 0，整个平移部分便消失了。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;点用 w = 1 的标准表示，向量用 w = 0，同一个矩阵就能让点跟着平移，同时让向量不受平移影响。&lt;&#x2F;strong&gt; 这两个数并不是随手贴上的标签，而是与点和位移的运算关系吻合。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;san-ru-guo-w-bian-cheng-liao-bie-de-shu-gai-zen-me-ban&quot;&gt;三、如果 w 变成了别的数，该怎么办？&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;cong-gu-ding-de-yi-ceng-zou-xiang-ren-yi-fei-ling-de-w&quot;&gt;从固定的一层，走向任意非零的 w&lt;&#x2F;h3&gt;
&lt;p&gt;到这一步，我们已经在高一个维度的线性代数框架里，统一了点和向量的仿射变换。这里采用的约定很简单：把二维点放在 w = 1 这一层，计算后读取前两个分量。&lt;&#x2F;p&gt;
&lt;p&gt;不过，更一般的三维线性变换并不保证把这一层上的点仍然送回这一层。比如，让 (X, Y, w) 变成 (X, Y, X + w)，就是一个合法的可逆线性变换。原本在第一层的 (1, 2, 1)，经过它以后就成了 (1, 2, 2)。&lt;&#x2F;p&gt;
&lt;p&gt;先不急着给这种表示取名字，继续考虑眼下的问题：我们已经借助升维统一了平移、旋转和缩放，但对二维点的读取规则还只定义在 w = 1 这个切面上。如果想把这套表示推广到其他非零的 w，就需要说明：不同层上的坐标，应该怎样对应到二维点？&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xian-rang-bu-tong-lou-ceng-du-chu-tong-yang-de-ping-yi-liang&quot;&gt;先让不同楼层读出同样的平移量&lt;&#x2F;h3&gt;
&lt;p&gt;我们尝试最朴素的思路：&lt;strong&gt;无论选哪一层，都希望同一个平移矩阵在读取后表示同样的二维平移。&lt;&#x2F;strong&gt; 于是，先让 w = 2、3、4……，看看会怎样。&lt;&#x2F;p&gt;
&lt;p&gt;以 X 分量为例，设这一方向上的平移量为 t。在 w = 2 这一层，平移矩阵会把 X 变成 X + 2t，但我们希望读出来的位移仍然只是 t。一个自然的做法，就是在读取坐标时，把这一层的 X 除以 2：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;(X + 2t) &#x2F; 2 = X&#x2F;2 + t&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;同样，在 w = 3 时，位移是 3t，那就除以 3。Y 分量也是同样的道理。这样，无论选哪个非零的 w 层，按照 (X&#x2F;w, Y&#x2F;w) 读取坐标，都能得到相同的二维平移量。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ping-yi-liang-dui-liao-qi-dian-ye-yao-bao-chi-bu-bian&quot;&gt;平移量对了，起点也要保持不变&lt;&#x2F;h3&gt;
&lt;p&gt;但这里还有一个问题。如果原来的二维点是 (x, y)，只是把它的表示从 (x, y, 1) 改成 (x, y, 2)，那么按照刚才的规则，读出来的起点就会变成 (x&#x2F;2, y&#x2F;2)；改成 (x, y, 3)，起点就变成 (x&#x2F;3, y&#x2F;3)。&lt;&#x2F;p&gt;
&lt;p&gt;也就是说，虽然读取后的平移量符合要求，起点却已经不是原来的二维点了。&lt;strong&gt;要同时保持原来的起点和读取后的平移量，只修改 w 是不行的。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;解决办法也很直接：把同一个二维点放到不同层时，同时把 x、y 乘以对应的 w，用 (wx, wy, w) 来表示它。读取时除以 w，就能得到原来的 (x, y)；经过平移矩阵后，X 变成 wx + wt，除以 w 得到 x + t，Y 分量同理。&lt;&#x2F;p&gt;
&lt;p&gt;因此，无论选哪个非零的 w 层，包括负的 w，用 (wx, wy, w) 表示同一个二维点，再统一按 (X&#x2F;w, Y&#x2F;w) 读取，就既能保持原来的起点，也能让同一个平移矩阵产生相同的二维平移。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cheng-bi-li-de-zuo-biao-zu-biao-shi-tong-yi-ge-dian&quot;&gt;成比例的坐标组，表示同一个点&lt;&#x2F;h3&gt;
&lt;p&gt;到这里，我们从平移的需求出发，构造出了有限二维点的齐次坐标表示。现在再来看它的几何意义：当 w 取遍非零实数时，(wx, wy, w) 描述的是同一条过原点直线上的所有非零坐标组。我们把这些坐标组，看作同一个二维点的不同代表。&lt;&#x2F;p&gt;
&lt;p&gt;这种选择能与矩阵运算配合，是因为线性变换会保留整体倍数关系：输入整体乘以某个数，输出也会整体乘以这个数。只要输出不是零坐标组，换一个等价代表去计算，最终仍然表示同一个射影点。可逆矩阵保证非零输入不会变成零坐标组。&lt;&#x2F;p&gt;
&lt;p&gt;所谓齐次坐标，核心就在这里：&lt;strong&gt;一个非零坐标组与它的任意非零整体倍数，表示同一个射影点。&lt;&#x2F;strong&gt; 对于有限点，我们最常用的代表，就是最后一项为 1 的那个。&lt;a href=&quot;https:&#x2F;&#x2F;www.pbr-book.org&#x2F;4ed&#x2F;Geometry_and_Transformations&#x2F;Transformations&quot;&gt;PBRT 的齐次坐标介绍&lt;&#x2F;a&gt;也说明了这种比例等价关系。至于 w = 0 对应的射影点，我们留到下一节讨论。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;chu-yi-w-jiu-shi-hui-dao-di-yi-ceng-du-shu&quot;&gt;除以 w，就是回到第一层读数&lt;&#x2F;h3&gt;
&lt;p&gt;有了这条直线，怎么从 (X, Y, w) 找回二维位置就很清楚了。只要 w 不为 0，把三个分量一起除以 w，就得到 (X&#x2F;w, Y&#x2F;w, 1)，也就是同一条直线与第一层的交点，前两项便是二维坐标。&lt;strong&gt;除以 w，其实就是沿着这条过原点的直线，回到 w = 1 这一层读数。&lt;&#x2F;strong&gt; 所以 (2, 4, 2) 和 (−1, −2, −1) 都读成 (1, 2)。负数没有问题，因为这里用的是一整条直线，包括原点两侧；但 (0, 0, 0) 本身不能表示射影点，因为所有这些直线都经过它，光凭它无法确定是哪一条。&lt;&#x2F;p&gt;
&lt;p&gt;回头看刚才会改变 w 的变换：(1, 2, 1) 变成 (1, 2, 2)，除以 2，读回二维就是 (1&#x2F;2, 1)。如果一开始换用两倍的代表 (2, 4, 2)，输出会是 (2, 4, 4)，除以 4，仍然得到 (1&#x2F;2, 1)。中间的数字不同，最后表示的位置却完全一样，这正是比例关系在矩阵运算中的作用。&lt;&#x2F;p&gt;
&lt;p&gt;前面的平移也符合这套规则。二维点 (1, 2) 向右移动 3，用第一层的代表来算，就是 (1, 2, 1) 变成 (4, 2, 1)；换用第二层的等价代表，就是 (2, 4, 2) 变成 (8, 4, 2)。第二层的 X 虽然增加了 6，最后除以 2，读出来仍然是 (4, 2)。高楼越往上被推得越远，与最终表示同样的二维平移并不矛盾，因为读数时的比例也跟着变了。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;si-w-0-wu-qiong-yuan-dian-yu-wei-yi-xiang-liang&quot;&gt;四、w = 0：无穷远点与位移向量&lt;&#x2F;h2&gt;
&lt;p&gt;既然要除以 w，那么 w = 0 怎么办？先看它对应的直线：比如 (1, 0, 0) 所在的过原点直线，完全躺在 w = 0 平面里，永远不会与 w = 1 相交，因此无法读成这一层上的某个有限位置。在射影几何里，这样的直线表示无穷远点，用来记录平行线共同的方向。二维里沿水平方向延伸的一组不同直线没有有限交点，但在扩展后的射影平面里，它们共享同一个无穷远点。这里的“无穷远”是一种方向的表示，并不是一个特别大的坐标。&lt;&#x2F;p&gt;
&lt;p&gt;不过，无穷远点与位移向量需要分清。“向右走三米”和“向右走六米”，可以分别写成 (3, 0, 0) 和 (6, 0, 0)。作为位移向量，它们当然不同，因为长度不同；只有把它们当作无穷远点的齐次代表时，才忽略这个倍数，把它们看成同一个射影点。&lt;strong&gt;不能因为齐次点允许整体缩放，就把三米和六米的位移也当成一回事。&lt;&#x2F;strong&gt; 同样，零向量 (0, 0, 0) 作为位移完全合法，只是不能表示射影点。&lt;&#x2F;p&gt;
&lt;p&gt;前面“点在第一层、向量在底层”的处理方式，针对的是仿射变换。换成更一般的射影变换，w = 0 不一定继续保持为 0，无穷远点也可能变成有限点。因此，用 w = 0 表示位移向量时，不能直接把仿射变换中的结论套到任意射影变换上。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zai-tu-xing-xue-li-wei-shen-me-yao-qu-fen-dian-he-xiang-liang&quot;&gt;在图形学里，为什么要区分点和向量？&lt;&#x2F;h3&gt;
&lt;p&gt;区分点和向量最直接的用处，就是避免把平移加到方向上。比如方向 (1, 0) 遇到向上平移 5，写成 (1, 0, 0)，平移后仍然是 (1, 0, 0)；如果误写成 (1, 0, 1)，结果就成了 (1, 5, 1)。再把前两项拿来当方向，朝向已经变了，即使重新归一化长度，也无法恢复原来的方向。&lt;&#x2F;p&gt;
&lt;p&gt;w = 0 只会去掉平移部分，旋转和缩放照样能影响向量。另外，法线在非均匀缩放下通常需要用可逆线性部分的逆转置来变换，才能继续垂直于表面，光把 w 填成 0 还不够。&lt;a href=&quot;https:&#x2F;&#x2F;www.pbr-book.org&#x2F;4ed&#x2F;Geometry_and_Transformations&#x2F;Applying_Transformations&quot;&gt;PBRT 关于点、向量和法线变换的说明&lt;&#x2F;a&gt;给出了相应推导。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wu-qi-ci-zuo-biao-neng-zhi-jie-xiang-jia-jian-ma&quot;&gt;五、齐次坐标能直接相加减吗？&lt;&#x2F;h2&gt;
&lt;p&gt;理解了点和向量的区别，加减法就顺了。把有限点都写成 w = 1 的标准代表，两个点相减，最后一项是 1 − 1 = 0，得到位移向量；点加位移向量，最后一项是 1 + 0 = 1，得到另一个点；两个位移向量相加，最后一项仍然是 0，得到的还是位移向量。&lt;&#x2F;p&gt;
&lt;p&gt;那两个点直接相加呢？比如 A 是 (1, 2)，B 是 (3, 4)，用标准代表相加，会得到 (1, 2, 1) + (3, 4, 1) = (4, 6, 2)。如果把结果当作齐次点来读，除以 2，就得到 (2, 3)，恰好是 A 和 B 的中点。但这依赖一个关键条件：我们给两个点选的代表，最后一项都是 1。如果把 A 换成等价的 (2, 4, 2)，B 仍用 (3, 4, 1)，相加就会得到 (5, 8, 3)，读出来是 (5&#x2F;3, 8&#x2F;3)，已经不是中点了。&lt;&#x2F;p&gt;
&lt;p&gt;两个点明明没变，只是其中一个换了代表，结果就变了。这说明，齐次代表虽然可以像普通向量一样相加，但这种加法不会自动成为与代表选择无关的“点的加法”。要用它求中点，就先把两个有限点都统一到 w = 1，再计算 0.5A + 0.5B，最后一项自然是 1，前两项直接给出中点。前面用相减求位移，同样依赖先选好这样的标准代表。&lt;&#x2F;p&gt;
&lt;p&gt;更一般地，对这些标准代表做 0.25A + 0.75B，得到的点会更靠近 B。权重加起来等于 1，这样的运算叫仿射组合；权重都非负时，就是熟悉的加权平均。如果权重加起来等于 0，结果的 w 也等于 0，可以解释为位移向量，其中也包括零向量。B − A 正是这种情况，两个权重分别是 1 和 −1。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;liu-tou-shi-tou-ying-wei-shen-me-ye-yao-chu-yi-w&quot;&gt;六、透视投影为什么也要除以 w？&lt;&#x2F;h2&gt;
&lt;p&gt;理解了“沿过原点的直线，回到选定平面读数”，透视中的除法就不突然了。想象一个最简单的相机：相机中心放在原点，成像平面放在 z = 1。从相机出发，穿过空间中的点 (x, y, z) 画一条直线，它与成像平面的交点就是 (x&#x2F;z, y&#x2F;z, 1)，这里假设点在相机前方，z &amp;gt; 0。横向坐标 x、y 相同，深度 z 越大，投影后的位置就越靠近中心；同样大小的物体放得越远，成像也越小，近大远小就这样出现了。&lt;a href=&quot;https:&#x2F;&#x2F;docs.opencv.org&#x2F;4.13.0&#x2F;d9&#x2F;d0c&#x2F;group__calib3d.html&quot;&gt;OpenCV 的针孔相机模型说明&lt;&#x2F;a&gt;使用的就是这种投影关系。&lt;&#x2F;p&gt;
&lt;p&gt;在三维图形管线里，我们给点 (x, y, z) 添加第四个分量 w，使用 4 × 4 矩阵。透视投影矩阵会让输出的 w 与深度有关，再通过除以 w 实现按深度缩小的效果。具体正负号和深度表达取决于所用约定，但这个除法与前面读回标准代表的思路相同。通常，裁剪坐标经过这一步得到归一化设备坐标，还需要视口映射，才会变成屏幕上的像素位置。&lt;&#x2F;p&gt;
&lt;p&gt;下次看到一个点经过矩阵以后，w 从 1 变成别的数，就可以沿着本文的思路去理解：只要 w 不为 0，把所有分量一起除以 w，就能回到标准代表，读出它所表示的位置。单独把最后一项改成 1，一般会改变整组坐标的比例关系，也就改变这个点。&lt;&#x2F;p&gt;
&lt;p&gt;回到最初的问题：多出来的 w，先让平移能够参与矩阵乘法；当我们把读取规则推广到任意非零的 w 时，成比例的坐标组便可以表示同一个点。沿着过原点的直线回到选定平面读数，又把这套表示自然地连接到了透视投影。&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
