一条细线移动很小的距离后突然消失,不一定是几何数据丢了。如果采样点恰好都落在线外,图像数组中就没有任何数值能证明那条线存在。随后放大图片,也无法从缺失的样本中恢复它。

本篇把二维图像暂时简化成一维明暗信号,在完全相同的信号上改变采样率与预滤波。输出包括浮点 CSV、原始 PPM 和实际转换的 PNG。显示放大与信号采样分开处理,避免把浏览器缩放造成的视觉变化当作算法改善。

从连续函数到有限数组

取归一化区间 0x<10\le x<1,定义:

g(x)=12+12cos(2π12x).g(x)=\frac12+\frac12\cos(2\pi\cdot12x).

它在一个单位区间内有12个周期,数值范围为[0,1]。x是归一化位置,12的单位是“每单位区间的周期数”。这里的数值是教学灰度信号,尚不宣称是经过标定的物理亮度;第04篇再区分线性颜色与显示编码。

N个均匀样本分别取在区间中心:

ci=i+1/2N,i=0,,N1.c_i=\frac{i+1/2}{N},\qquad i=0,\ldots,N-1.

中心位置与第02篇的像素中心约定相容。点采样就是记录 g(ci)g(c_i)。数组长度N有限,点之间发生了什么,并没有被直接记录。

为了显示成条纹图,每个样本沿竖直方向重复16行。这16行没有新增横向信息,也不是16次独立采样。所有图的横向仍对应同一个区间[0,1),原始宽度分别为16、32、64。

两个不同信号可以得到同一组样本

先用不带半格偏移的位置 xi=i/16x_i=i/16 构造一个精确反例。比较12周期与4周期余弦:

cos(2π12i/16)=cos(2πi2π4i/16)=cos(2π4i/16).\cos(2\pi\cdot12i/16) =\cos(2\pi i-2\pi\cdot4i/16) =\cos(2\pi\cdot4i/16).

对整数i,这两组样本完全相同。一次采样丢失了区分两种连续信号所需的信息;后续任何只读取这16个数的算法,都不能唯一判断输入到底是哪一种。

本次双精度程序逐点比较,最大差为 3.98×10153.98\times10^{-15},来自浮点三角函数求值与舍入,而不是两个采样序列具有可用的差异。测试阈值设为 101210^{-12}

图像实验使用中心采样,不能把上面不带偏移的等式原封不动套进去。在 xi=(i+1/2)/16x_i=(i+1/2)/16 处,12周期余弦会对应反号的4周期余弦,即低频别名还带有相位变化。采样位置既影响结果,也影响反例的写法。

对带限信号,采样频率必须高于最高频率的两倍,并配合适当重建,才能避免频谱重叠导致的歧义。N=16低于本例所需的24;N=32与64高于24。但实际几何边界是不连续的,不能用一个有限的最高频率完全描述,因此“增加分辨率”不是对所有图像内容的完整解法。

预滤波发生在取样之前

点采样只看区间中心,另一种选择是先求每个区间内的平均值:

gˉi=Ni/N(i+1)/Ng(x)dx.\bar g_i=N\int_{i/N}^{(i+1)/N}g(x)\,dx.

前面的N用于除以区间宽度1/N,保证常量信号经过平均后仍保持原值。对本例积分,可以得到:

gˉi=12+12sin(12π/N)12π/Ncos(24πci).\bar g_i=\frac12+\frac12\frac{\sin(12\pi/N)}{12\pi/N} \cos(24\pi c_i).

中间的比值是盒式滤波对这个频率的幅度缩放。它可以由余弦的积分直接推导,不需要先生成高分辨率图片再缩小。实验同时用每个区间4096个中点样本做独立数值积分,检查解析公式。

滤波不是在已混叠的16个数上做模糊。它访问的是取样之前的连续函数,因而能利用区间内部的信息。若手中只剩已经混叠的数组,模糊可以改变外观,却无法知道原信号究竟是12周期还是4周期。

盒式平均也不是理想低通。N=16时,12周期分量被乘以约0.3001,仍然非零,因此仍会形成低频别名,只是对比度降低。不能把“条纹变淡了”写成“混叠已经消失”。

同一信号的六张实际结果

下面每组第一张图是点采样,第二张图是盒式平均。图片来自C++程序生成的PPM,再经本机sips转换成PNG;没有绘制或修改条纹结果。每张显示为320×80 CSS像素并使用最近邻式放大。原始高度16、原始宽度见行标题,因此显示尺寸不是原始采样数量。

N=16

16个中心点样本,原图16乘16 16个盒式平均样本,原图16乘16

N=32

32个中心点样本,原图32乘16 32个盒式平均样本,原图32乘16

N=64

64个中心点样本,原图64乘16 64个盒式平均样本,原图64乘16

N=16的两张图都显示较粗的条纹,不能据此判断原信号只有这么少的周期。N增大后,对原信号的横向变化保留得更充分。点采样与盒式平均的差别也变小,因为平均区间变窄,当前频率的滤波衰减减弱。

这些PNG将浮点值乘255并四舍五入成整数码值。定量比较仍用原始浮点CSV,不要反过来从已经量化的PNG推导高精度误差。

用数值区分滤波与显示现象

三个采样率的第一个样本实际为:

N 点采样 盒式平均 余弦幅度乘子
16 0.1464466094 0.3938967046 0.3001054387
32 0.6913417162 0.6500527194 0.7842133036
64 0.9157348062 0.8921066518 0.9431653207

第一个中心位置随N改变,所以不能把这一列样本值的升降解释为“整体图像越来越亮”。可以比较的是同一行中两种方法在同一区间的结果,以及明确给出的滤波幅度。

盒式解析值与4096子样本中点积分的最大差为 5.85×1095.85\times10^{-9},小于检查阈值 10710^{-7}。这是解析滤波实现与数值积分的一致性检查,不是“相对于所有可能图像的抗锯齿误差”。中点积分本身也是近似,只是对当前平滑函数与步长足够精细。

另保留N=16点采样的原尺寸显示,以及浏览器普通缩放:

原尺寸:16乘16原尺寸

普通缩放:同一16乘16图像由浏览器普通缩放

两处读取同一个PNG。浏览器普通缩放可能产生过渡灰度,具体外观受浏览器、设备像素比和缩放设置影响;它没有修改CSV,也没有增加对连续信号的观测。算法是否正确应先检查原始数组,显示方式负责帮助解释,不能替代数值证据。

为什么细线和动画更容易暴露问题

设一条亮线只覆盖连续位置区间的一小段。如果它落在两个采样中心之间,点采样可能全为零;平移后恰好覆盖某个中心,又会突然出现一个亮样本。几何只发生了连续的小位移,离散输出却发生大跳变。

棋盘格远离相机时,投影后的格子越来越窄,空间频率相对于固定像素网格越来越高。相机移动还改变格子与采样网格的相位,于是空间混叠在连续帧中表现为闪烁。本篇只运行固定余弦实验,没有把这段机制解释冒充已经完成的棋盘动画测试;纹理缩小与运动实验将在后续篇目落实。

提前过滤会抑制无法稳定采样的变化,但也会丢失细节。选择滤波器是在细节、残余混叠、振铃和计算成本之间作具体权衡。盒式平均便于解析验证,不能因为实现短就认定它在所有图像上最佳。

复跑与检查范围

在仓库根目录运行:

1
2
make -C examples/computer-graphics check
examples/computer-graphics/build/sampling examples/computer-graphics/build

输出目录必须已经存在。程序生成六个PPM与samples.csv,CSV共有16+32+64=112行数据。检查同时复跑前面三篇,核对别名等式、盒式解析值与数值积分;缺少目录参数时返回非零。原始日志位于writing-plans/computer-graphics/evidence/03-cpu.txt

全部采样为确定性规则,无随机种子;每个积分区间固定4096个子样本,没有自适应终止。未测量性能。PPM的尺寸与通道数另行读取核对,六次PNG转换成功;显示诊断码值的约定继续沿用第00篇。

练习与自检

练习一:为什么正好两倍仍需小心?sin(2π8x)\sin(2\pi\cdot8x)x=i/16x=i/16 取样,得到什么?这说明只说“采样数等于频率两倍就够了”遗漏了什么?

答案:每个样本都是 sin(πi)=0\sin(\pi i)=0,非零连续信号与零信号无法区分。频率边界、相位与允许的信号类别必须说明;本篇采用严格高于两倍的条件,不将恰好处在边界的任意相位信号也列为保证恢复。

练习二:模糊为什么不能补回证据? 已知16个整数位置样本既可来自12周期余弦,也可来自4周期余弦。对这16个数进行相邻平均,能判定原来的周期数吗?

答案:不能。相同输入数组经过同一个确定算法仍输出相同结果,处理过程没有得到区间内部的新观测。预滤波能改变采样前的频谱,是因为它在信息丢失前访问连续函数;事后平均只能选择一种重建或平滑外观。

系列导航与资料

前篇:02:相机怎样把空间投到屏幕系列入口。下一篇:04:为什么平均颜色会发暗

PBRT 4ed §8.1 Sampling Theory,重点为8.1.3的采样重建、8.1.4的像素约定、8.1.5的混叠来源与预滤波,图8.8–8.12。资料实际查阅于2026-09-19。余弦反例、盒式积分与112行实验数据是本系列独立构造,不是对教材图像的复刻。