给定一张被点光源照亮的平面图,如果几何、反射率和光源位置都已知,能否反推出光源有多亮?这个问题只剩一个未知数,仍然足以检查梯度是否正确、步长为何影响收敛,以及图像完全匹配时参数是否唯一。

实验固定 Lambert 平面,只恢复非负光强 s。目标图由已知强度 3 生成,求解器只接收像素观测和已知系数。三个初值、三档步长都运行 40 次更新;另用全饱和图保留多解反例。

哪些量已知,哪个量待求

平面位于 z=0,法线为 +Z,反射率 ρ=0.7,点光源位于 (0,0,2)。32×32 个像素对应 [−1.5,1.5]² 内的格点中心。所有点都无遮挡,V=1;没有间接反射、噪声或曝光变化。

第 19 篇的 Lambert BRDF 为 ρ/π。点光源辐射强度除以距离平方,再乘入射余弦,得到表面接受的照度贡献。因此像素线性输出为:

Ii(s)=sai,ai=ρπmax⁡(0,ni⋅ℓi)ri2Vi.I_i(s)=s a_i,\qquad a_i=\frac{\rho}{\pi}\frac{\max(0,n_i\cdot\ell_i)}{r_i^2}V_i.

ℓ 是从表面指向光源的单位向量,r 是距离。s 表示点光源辐射强度的标量幅值,不能直接解释为总功率;ρ、距离或单位一旦改变,系数 a 也随之改变。此处三个 RGB 通道相等,形成中性灰图。对单通道取均方与对三个相同通道取均方,结果相同。

目标 yᵢ=3aᵢ保留为浮点线性值。显示时才经过 sRGB 编码,优化不读取 PNG 码值,也不比较各自归一化后的图片。初始化和迭代函数不访问生成器中的强度常量。

几何与材质固定,使 aᵢ能预先计算。若同时未知反射率和光强,乘积 ρs 就可能对应多组参数,当前唯一性结论将不再适用。

梯度与闭式解应互相核对

采用像素均方的一半作为损失,N=1024:

E(s)=12N∑i(sai−yi)2,E′(s)=1N∑iai(sai−yi).E(s)=\frac{1}{2N}\sum_i(sa_i-y_i)^2, \qquad E'(s)=\frac1N\sum_i a_i(sa_i-y_i).

每个残差乘以该像素对光强的导数 aᵢ,再求平均。前面的 1/2 抵消平方求导的系数 2;漏掉 N 不改变最优点,却会把梯度和允许步长整体缩放。

令导数为零可得最小二乘参考:

s∗=∑iaiyi∑iai2.s_* = \frac{\sum_i a_i y_i}{\sum_i a_i^2}.

至少一个 aᵢ非零时分母才为正。当前输入 aᵢ、yᵢ均非负,闭式解也非负;一般带噪观测若允许负值,则还需处理 s≥0 的边界。所有系数为零时图像完全不随强度变化,代码明确拒绝求解,不能返回一个看似可靠的零光强。

手算检查另用 a=(1,2)、y=(3,6):E=1.25(s−3)²,梯度为 2.5(s−3)。从 s=1、η=0.4 更新一步正好到 3。这个小例子与真实平面图分开,能检查归一化、符号和更新方向。

有限差分不是越小越好

独立核对使用中心差分:

gh(s)=E(s+h)−E(s−h)2h.g_h(s)=\frac{E(s+h)-E(s-h)}{2h}.

检查点固定为 s=0.5、2、6,h 从 10⁻¹扫描到 10⁻⁹。每档取三个检查点的最大绝对梯度差:

h 最大绝对差
10⁻¹ 7.76×10⁻¹⁷
10⁻³ 1.36×10⁻¹⁴
10⁻⁵ 5.65×10⁻¹³
10⁻⁷ 5.69×10⁻¹¹
10⁻⁹ 1.35×10⁻⁸

这里的损失恰是二次多项式,中心差分在精确算术下没有截断误差。h 很小时,两次接近的损失相减,浮点舍入反而被除以 h 放大。因此表中的大 h 表现好有明确前提,不能推广为所有可微渲染都应选大扰动。

差分只用于核对手写解析梯度。实验没有自动微分,也没有对遮挡变化或几何交界求导;这些在当前固定系数模型里都未发生。

步长怎样决定误差变化

二阶导数为常数 H=mean(aᵢ²)。没有触及非负边界时,梯度更新满足:

sk+1=sk−ηE′(sk),sk+1−s∗=(1−ηH)(sk−s∗).s_{k+1}=s_k-\eta E'(s_k),\qquad s_{k+1}-s_*=(1-\eta H)(s_k-s_*).

误差缩小要求 |1−ηH|<1,即 0<η<2/H。ηH 小于 1 时误差同号缩小;在 1 与 2 之间时越过最优点,两侧交替收缩。η=1/H 对这个精确二次问题一步到解。

程序实际使用 max(0,s−ηE′),阻止负光强。投影到非负半轴不会增加与可行最优点的距离,因此上述稳定区间仍是充分条件;一旦被截到零,未投影的线性递推就不能继续逐步套用。输入还设有限数值上界,当前所有运行都未触及它。

真实系数给出 H≈0.00141456757315,2/H≈1413.85964019。三档 η 分别取这个上界的 0.25、0.9、1.1 倍,约为 353.46491、1272.47368、1555.24560。η 是优化步长,量纲取决于参数和损失定义,与物理时间步长无关。

同样四十次更新得到什么

下表列出全部九次运行。参数误差以浮点闭式解为参考,图像 MSE=2E,在原始线性像素上计算。

初值 η/(2/H) 最终 s 参数绝对误差 线性图像 MSE
0 0.25 2.999999999997 2.74×10⁻¹² 1.05×10⁻²⁶
1 0.25 2.999999999998 1.83×10⁻¹² 4.68×10⁻²⁷
6 0.25 3.000000000003 2.72×10⁻¹² 1.05×10⁻²⁶
0 0.9 2.999601232 3.99×10⁻⁴ 2.25×10⁻¹⁰
1 0.9 2.999734154 2.66×10⁻⁴ 1.00×10⁻¹⁰
6 0.9 3.000398768 3.99×10⁻⁴ 2.25×10⁻¹⁰
0 1.1 0 3.0 0.0127311
1 1.1 0 3.0 0.0127311
6 1.1 6.6 3.6 0.0183328

0.25 档的误差因子是 0.5,0.9 档是 −0.8。后者虽然步长更大,却每步只把误差幅度乘以 0.8,因此同预算更慢。它仍在收敛,不能因为 40 次尚有约 10⁻⁴ 的参数误差就称为失败。

1.1 档的未投影因子为 −1.2。振荡扩大到负半轴后,参数被截为零;下一步从零跳到 6.6,再被截回零。三个初值分别有 20、21、20 次损失上升。这种失败可以直接归因于更新参数,不需要假设非凸局部最优。

数据含每组初态加 40 次更新,共 369 行状态。每次损失或梯度计算扫描 1024 个系数,固定九组、40 次更新说明了本次计算规模。没有训练墙钟基准、GPU 执行或通用性能结论;这些数字也不代表完整路径追踪的成本。

完全匹配也可能没有唯一答案

另将观测改为 Cᵢ(s)=min(1,saᵢ),模拟固定单位阈值的曝光截断。当前最小 a 约为 0.0188982,因此 s≥约 52.915 时每个像素都饱和成 1。

目标由 s=100 经过同一截断生成。实际测试 100、150、200 三个强度,三幅输出逐字节相同,损失和解析梯度都是零。区间内部 C 对 s 的导数为零;任何更大的强度也无法从这张全白图中区分出来。阈值交界另有不可微问题,三个测试点均远离交界。

这是观测丢失信息造成的不可辨识性。原先未截断、H>0 的单参数问题是严格凸二次问题;不能把全白反例称为那个问题的“坏局部最优”。恢复需要增加未饱和观测或改变曝光条件,继续增加原图上的迭代次数不增加信息。

练习与自检

练习一。a=(1,2)、y=(3,6) 时,为什么 η=0.4 能一步恢复?η=0.8 会怎样?

答案:H=2.5,前者使误差因子为零;后者使因子为 −1。若从 s=1 出发,参数在 1 与 5 之间往返,不收敛,稳定范围的上端点不能取等号。

练习二。把所有 a 和 y 同时放大两倍,闭式解和稳定步长上界怎样变化?

答案:分子分母同乘四,s_*不变;H 变为四倍,2/H 缩为四分之一。图像尺度改变会影响梯度大小,不能照搬旧步长。

练习三。a=(1,2),饱和观测为 (1,1),哪些非负 s 能解释它?梯度为零能否证明 s 已恢复?

答案:所有 s≥1 都能解释;在 s>1 的区间,预测不随参数变化,梯度为零。它只说明当前观测没有区分能力,不能确认生成时用了哪个强度。

复跑与资料

在 examples/computer-graphics/ 目录中执行:

1
2
make build/inverseE06_check
build/inverseE06_check build/inverseE06

inverseE06.hpp 保存前向系数、损失、梯度和更新,检查器输出九组结果、逐次状态、差分扫描、目标线性像素、拟合像素和饱和对照。显示图来自同目录实际 PPM,命令、无效输入检查及哈希保存在 writing-plans/computer-graphics/evidence/E06-cpu.txt。

系列入口 · 上一篇:两连杆逆运动学 · 下一篇:三维高斯拟合。