ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

计算成像入门:前向模型、逆问题与AI先验的数学框架

计算成像入门:前向模型、逆问题与AI先验的数学框架

1. 计算成像到底在算什么:从“拍照片”到“解方程”

很多人第一次听到“计算成像”这四个字,脑子里浮现的画面大概是:拿个相机,按一下快门,然后电脑自动把照片修得更好看。这个理解不能说全错,但只摸到了皮毛。计算成像真正在做的事情,是把“成像”这件事从光学系统的硬件行为,重新定义成一个数学上的求解过程。传统相机的工作方式是:光线经过镜头,落在传感器上,传感器把光强转成电信号,电信号再转成像素值,一张图就出来了。整个过程是“所见即所得”,传感器记录什么,我们就看到什么。计算成像不一样,它承认传感器记录下来的原始数据往往不是我们最终想要的图像,而是一个被物理过程“污染”过的中间产物。我们要做的,是从这个中间产物出发,反推出那个真正想要的图像。

这个“反推”的过程,就是解逆问题。而描述“原始数据是怎么被物理过程污染出来的”那个数学模型,就是前向模型。至于AI,它在这个链条里扮演的角色越来越重,但它的位置不是取代前向模型,也不是取代逆问题求解,而是作为一种强力的先验知识来源,帮助我们在信息不足的情况下做出更合理的推断。这三个词——前向模型、逆问题、AI——构成了计算成像入门最核心的一条逻辑线。你把这三点吃透了,后面不管是做超分辨率、去模糊、单像素成像、还是无透镜成像,本质上都是在同一个框架里换不同的前向模型和不同的求解策略。

我写这个系列的第一讲,目标很明确:让完全没有计算成像背景、但有基本理工科思维的人,能够理解这个领域到底在干什么,为什么它跟传统图像处理有本质区别,以及AI到底应该放在哪个位置去用。如果你之前做过一些深度学习图像恢复的项目,但总觉得“调包跑通了但不知道自己在干嘛”,那这一讲就是帮你把那个“干嘛”补上。如果你是从光学、物理或者信号处理转过来的,对逆问题有感觉但对AI那一套不太熟,这一讲也会帮你把AI的位置摆正。

2. 前向模型:把物理过程写成数学表达式

2.1 为什么必须先有前向模型

前向模型是整个计算成像的基石。没有前向模型,你根本不知道传感器上的数据是怎么来的,也就无从谈起怎么反推。我见过不少初学者,拿到一个图像恢复任务,上来就开始搭网络、调损失函数,结果训练出来的模型换一个数据集就崩了。根本原因就是他们跳过了前向模型这一步,把“图像恢复”当成了一个纯粹的输入输出映射问题,而不是一个带有物理约束的逆问题。

前向模型的作用,用一句话概括:它描述了从“我们想要的理想图像”到“传感器实际记录到的原始数据”之间的全部物理变换。这个变换可能包括光学系统的点扩散函数卷积、传感器的采样过程、编码孔径的调制、光谱响应、噪声引入等等。把这些东西写成一个数学表达式,通常形式是:

y = A(x) + n

其中 x 是理想图像,y 是观测数据,A 是前向算子,n 是噪声。这个式子看起来简单得过分,但它的威力在于:一旦你写出了 A,你就知道了信息在哪个环节丢失了、丢失了多少、以什么形式丢失的。这直接决定了你的逆问题有多难解,以及你需要什么样的先验才能解得好。

2.2 前向模型的常见形式与物理直觉

不同成像模式下,前向算子 A 的形式差别很大。我列几种最常见的,帮你建立直觉。

第一种是卷积型前向模型。这是最经典也最容易理解的一种。比如荧光显微镜成像,由于衍射极限的存在,一个点光源在传感器上不会成一个点,而是成一个模糊斑,这个模糊斑就是点扩散函数(PSF)。整幅图像可以看作是理想图像与PSF的卷积,再加上噪声。写成式子就是 y = x * k + n,其中 * 表示卷积,k 是PSF。这种前向模型的特点是:它是线性的、平移不变的,而且在频域里看特别清楚——卷积在频域就是乘法,所以逆问题在频域里就是除法。但除法有个致命问题:PSF的频谱在高频部分往往接近零,直接除会把噪声放大到爆炸。这就是为什么去卷积从来不是简单做个除法就完事。

第二种是采样型前向模型。比如单像素成像,它不是一次性拍一整幅图,而是通过一系列编码图案对场景进行调制,每次只记录一个标量强度值。前向模型就是 y_i = <a_i, x> + n_i,其中 a_i 是第 i 次测量的编码图案,<·,·> 是内积。测量次数远小于图像像素数时,这就是一个欠定问题,但只要你设计的编码图案满足一定条件(比如随机高斯矩阵或哈达玛矩阵),就可以通过压缩感知的方法高概率恢复出原图。这里的前向模型直接决定了你最少需要多少次测量、以及用什么算法恢复。

第三种是非线性型前向模型。比如相位恢复问题,传感器只能记录光强,记录不到相位,而光强是相位的非线性函数(通常是傅里叶变换的模平方)。这时候前向模型 A 是非线性的,逆问题也就变成了非凸优化,求解难度陡增。再比如一些计算摄影中的饱和、量化、伽马校正,也都是非线性的来源。

我个人的经验是:在动手做任何计算成像项目之前,先花时间把前向模型写清楚,最好能写成矩阵形式或者算子形式,并且用一个小规模的仿真验证你的前向模型代码是对的。具体做法是:造一个已知的 x,用你的前向模型生成 y,然后再用最简单的逆方法(比如伪逆或者Tikhonov正则化)试着恢复 x,看看能不能大致恢复出来。如果连仿真都恢复不了,那要么是前向模型写错了,要么是逆问题本身太病态,你需要换测量方式或者加更强的先验。

2.3 前向模型设计中的取舍与坑

设计前向模型时,有几个常见的取舍需要提前想清楚。

第一个取舍是:物理精确度 vs 计算可处理性。真实物理过程往往非常复杂,比如镜头的像差不是简单的平移不变卷积,而是空间变化的;传感器的噪声也不是简单的高斯白噪声,可能包含泊松噪声、读出噪声、固定模式噪声等。如果你把所有这些都精确建模,前向模型会变得极其复杂,逆问题求解的计算量可能大到无法接受。所以实际中经常做简化:把空间变化的PSF近似为分块平移不变,把混合噪声近似为高斯噪声。这些简化会带来模型误差,但换来了可解性。我的建议是:先从一个简化但可解的模型开始,跑通整个流程,然后再逐步增加物理精确度,观察性能提升是否值得计算代价。

第二个取舍是:编码设计是否可微。如果你打算用端到端学习的方式来联合优化编码图案和前向模型,那么前向模型必须对编码参数可微。这时候你就不能用那些包含不可微操作(比如硬阈值、量化)的前向模型,或者需要用直通估计器(straight-through estimator)之类的技巧来处理。这一点在做光学编码孔径设计、可编程照明设计时特别重要。

第三个坑是:忽略了标定误差。前向模型里的参数(比如PSF、编码图案、噪声方差)往往不是精确已知的,而是通过标定实验估计出来的。标定误差会直接传播到逆问题的解里。我踩过的一个坑是:在仿真里用理想PSF训练了一个去卷积网络,效果很好,但换到真实数据上效果骤降,后来发现是真实PSF和仿真PSF有细微差异,导致网络过拟合到了错误的PSF上。解决办法是在训练时加入PSF扰动做数据增强,或者把PSF也作为可学习参数一起优化。

3. 逆问题:从观测数据反推理想图像

3.1 逆问题为什么“逆”起来这么难

前向模型是 y = A(x) + n,逆问题就是已知 y 和 A,求 x。听起来很直接,但难就难在 A 往往不是可逆的,或者即使可逆,逆算子也会把噪声放大到无法接受的程度。数学上管这个叫病态性(ill-posedness)。病态性有三个典型表现:解不存在(因为噪声让 y 落在了 A 的值域之外)、解不唯一(因为 A 的零空间非空)、解不稳定(y 的微小扰动导致 x 的巨大变化)。

我举个直观的例子帮你理解。假设 A 是一个模糊核的卷积,模糊核是一个高斯函数。在频域里,高斯函数的频谱也是高斯函数,高频部分衰减极快。当你做逆滤波(频域除法)时,高频部分的噪声被除以一个接近零的数,结果就是噪声被放大到淹没信号。这就是为什么直接逆滤波几乎从来不能用。你需要正则化,需要先验,需要把那些不稳定的高频分量压制住。

3.2 从经典正则化到AI先验

经典逆问题求解的思路是:在数据保真项之外,加一个正则化项,把解约束在一个合理的范围内。最经典的形式是:

x_hat = argmin_x ||y - A(x)||^2 + λ R(x)

其中 R(x) 是正则化项,λ 是平衡参数。不同的 R(x) 对应不同的先验假设。Tikhonov正则化用 R(x) = ||x||^2,假设解是光滑的、能量有限的。总变差(TV)正则化用 R(x) = ||∇x||_1,假设解是分片光滑的,能保留边缘。L1正则化假设解在某个变换域(比如小波域)是稀疏的。这些经典方法各有各的适用场景,但共同问题是:它们用的先验都是手工设计的、通用的,没有针对特定图像内容做自适应。

AI的介入改变了这个局面。深度学习最大的贡献,是它能够从大量数据中学习到一个非常强的、自适应的先验。这个先验可以以多种形式嵌入逆问题求解中。第一种方式是端到端学习:直接把 y 输入网络,网络输出 x_hat,前向模型和逆问题求解都被隐式地编码在网络参数里。这种方式简单粗暴,但可解释性差,而且对前向模型的变化很敏感——换一个模糊核,网络可能就失效了。第二种方式是展开式方法(unrolling):把经典迭代优化算法(比如ISTA、ADMM)的每一步展开成网络的一层,用网络来学习每一步中的正则化参数或者近端算子。这种方式既保留了前向模型的物理约束,又利用了深度学习的强先验,是目前学术界比较推崇的做法。第三种方式是即插即用(plug-and-play):在经典迭代算法的每一步中,用训练好的去噪网络替代近端算子。这种方式的好处是去噪网络可以独立训练,不需要针对特定前向模型重新训练。

我个人的实践体会是:如果你的前向模型比较准确、且测试时的前向模型和训练时一致,端到端方法往往能拿到最好的指标;但如果前向模型有不确定性、或者测试时前向模型会变化,展开式或即插即用方法鲁棒性更好。另外,端到端方法容易产生“幻觉”——网络会生成一些看起来合理但实际上不存在于真实场景中的纹理。这在医学影像和科学成像中可能是致命的,需要特别警惕。

3.3 逆问题求解的实操要点

在实际动手求解逆问题时,有几个关键点需要特别注意。

第一,数据保真项的选择要和噪声模型匹配。如果噪声是高斯噪声,用 L2 范数做数据保真项是合理的;如果噪声是泊松噪声(比如低光成像、荧光成像),用 L2 就不合适了,应该用泊松似然或者方差稳定变换后再用 L2。我见过有人用 L2 损失去训练低光图像增强网络,结果在极暗区域效果很差,就是因为噪声模型不匹配。

第二,正则化参数 λ 的调节非常关键。λ 太大,解会过度平滑,丢失细节;λ 太小,噪声压制不住。经典方法里 λ 通常靠 L 曲线或者交叉验证来选,但在深度学习方法里,λ 往往被吸收进了网络参数或者损失函数的权重里。我的经验是:在训练时用验证集上的重建指标来调 λ 相关的超参数,但不要只盯着 PSNR,还要看视觉质量和下游任务的性能。有时候 PSNR 最高的模型视觉上反而更模糊。

第三,初始化很重要。逆问题往往是非凸的,不同的初始化可能收敛到不同的局部极小值。一个常用的技巧是用经典方法(比如Tikhonov正则化)的解作为深度网络的初始输入,或者用多尺度策略从粗到细逐步恢复。

第四,别忘了评估不确定性。逆问题的解往往不是唯一的,尤其是在欠定情况下。一个好的求解器不仅应该给出一个估计值,还应该给出这个估计的不确定性范围。贝叶斯方法、集成学习、蒙特卡洛 dropout 都可以用来估计不确定性。这在医学和科学应用中尤其重要——医生需要知道这个重建结果有多可信。

4. AI在计算成像中的正确打开方式

4.1 AI不是魔法,它只是更强的先验

我经常看到两种极端观点。一种是“AI万能论”:觉得只要数据够多、网络够大,什么逆问题都能端到端搞定,前向模型不重要了。另一种是“AI无用论”:觉得AI就是黑箱拟合,没有物理可解释性,不如经典方法可靠。这两种观点都有问题。

正确的理解是:AI是一种从数据中学习先验的强大工具,但它不能凭空创造信息。如果前向模型本身丢失了某些信息(比如零空间非空),那么无论多强的先验也只能在零空间之外做推断,零空间内的分量是无法恢复的。AI能做的是:在信息不足的情况下,利用从训练数据中学到的统计规律,做出最合理的猜测。这个猜测的质量取决于训练数据是否覆盖了测试场景的分布。如果测试场景和训练场景差异很大,AI的先验就会失效,甚至产生严重的幻觉。

所以我在实际项目中,从来不会把AI当成唯一的求解手段。我的标准流程是:先建立尽可能准确的前向模型,分析问题的病态程度,然后用经典方法得到一个基线结果,最后再用AI方法去提升。如果AI方法相比经典方法有显著提升,我会进一步分析提升来自哪里——是更好地压制了噪声,还是更好地恢复了高频细节,还是仅仅过拟合了训练集的特定模式。

4.2 训练数据的准备与前向模型仿真

AI方法的效果高度依赖于训练数据的质量和多样性。在计算成像中,训练数据通常不是现成的,而是需要通过前向模型仿真生成的。这就带来一个关键问题:仿真数据和真实数据之间的域差距。

我做过一个去模糊的项目,仿真时用高斯模糊核生成训练对,网络在仿真测试集上 PSNR 超过 35dB,但换到真实拍摄的模糊图像上,效果惨不忍睹。原因就是真实模糊核不是高斯,而是复杂的运动模糊或者镜头像差。后来我改进了仿真策略:从真实模糊图像中估计模糊核,用估计出的模糊核生成训练数据,同时加入模糊核扰动做数据增强。改进后,真实数据上的效果提升非常明显。

所以我的建议是:在仿真训练数据时,一定要尽可能模拟真实的前向模型,包括噪声特性、编码误差、标定误差等。如果真实数据有限,可以考虑用域适应或者自监督学习的方法,在真实数据上做微调。另外,训练数据的多样性也很重要——如果训练集里只有人脸,测试时遇到自然场景就会崩。尽量覆盖目标应用场景中可能出现的各种内容。

4.3 网络架构选择与损失函数设计

在计算成像中,网络架构的选择取决于你把AI放在哪个位置。如果是端到端方法,U-Net 及其变体是目前最常用的 backbone,因为它能同时捕捉全局结构和局部细节。如果是展开式方法,每一层的网络通常比较轻量,几层卷积就够了,因为主要的迭代逻辑已经由展开的优化算法提供了。如果是即插即用方法,去噪网络的选择就很关键,DnCNN、FFDNet、DRUNet 都是常用的选择。

损失函数的设计也很有讲究。最常用的是 L2 损失(MSE),但它倾向于产生过度平滑的结果。L1 损失对异常值更鲁棒,能保留更多细节。感知损失(perceptual loss)用预训练网络的特征距离来度量,能提升视觉质量,但可能偏离物理真实。对抗损失(adversarial loss)能生成更锐利的纹理,但训练不稳定,而且容易产生幻觉。我的经验是:在科学成像中,优先用 L1 或 L2 损失,保证物理真实性;在消费级摄影中,可以加入感知损失和对抗损失来提升观感。另外,如果下游有特定任务(比如检测、分割),可以把下游任务的损失也加入训练,做端到端优化。

还有一个容易被忽略的点是:损失函数应该在什么域上计算。有些前向模型在频域里更自然(比如卷积),那么在频域里计算损失可能比空域更有效。有些任务对相位敏感,那么损失函数里应该包含相位项。这些细节需要根据具体问题来设计。

5. 常见问题与排查技巧实录

5.1 重建结果模糊或噪声放大

这是最常见的问题。如果你用经典方法,大概率是正则化参数没调好。λ 太大导致模糊,λ 太小导致噪声放大。解决办法是画 L 曲线:横轴是数据保真项,纵轴是正则化项,取拐点处的 λ。如果你用深度学习方法,可能是训练数据的噪声分布和测试时不一致,或者网络的感受野不够大,无法捕捉长程依赖。可以尝试增大网络深度、加入多尺度结构、或者在训练时加入不同噪声水平的样本做数据增强。

5.2 仿真效果好但真实数据效果差

这是域差距问题。排查步骤:第一,检查真实数据的前向模型参数(PSF、编码图案、噪声方差)是否和仿真一致,如果不一致,要么重新标定,要么在仿真中加入参数扰动。第二,检查真实数据的预处理是否和仿真一致(比如归一化方式、颜色空间、裁剪方式)。第三,考虑用少量真实数据做微调,或者用自监督方法在真实数据上做自适应。我自己的做法是:保留一个小的真实验证集,每次改动仿真流程后都在真实验证集上测一下,确保没有过拟合到仿真域。

5.3 网络训练不收敛或指标震荡

可能的原因包括:学习率太大、batch size 太小、损失函数尺度不合适、数据归一化有问题。排查时可以先在小规模数据上过拟合一个 batch,如果连一个 batch 都过拟合不了,那肯定是代码有 bug。如果过拟合没问题但验证集指标震荡,可能是验证集太小或者分布不一致。另外,计算成像中的前向模型往往包含不可微操作,如果你用端到端训练,需要检查梯度是否能正确回传。可以用 torch.autograd.gradcheck 来验证自定义算子的梯度正确性。

5.4 重建结果出现幻觉纹理

这是端到端深度学习方法的一个固有风险。网络在训练集上见过某种纹理,测试时即使输入数据中不包含这种纹理的信息,网络也会“脑补”出来。解决办法:第一,在损失函数中加入物理一致性约束,确保重建结果经过前向模型后和观测数据一致。第二,用展开式或即插即用方法,保留前向模型的约束。第三,在训练数据中加入多样性,减少网络对特定纹理的偏好。第四,如果应用场景对幻觉零容忍(比如医学诊断),优先用经典方法或者不确定性量化方法,对高不确定性区域做人工复核。

5.5 计算资源不够怎么办

计算成像的逆问题求解,尤其是展开式方法,往往需要大量显存和计算时间。几个实用的技巧:第一,用混合精度训练,能省不少显存。第二,用梯度检查点(gradient checkpointing),用时间换空间。第三,如果前向模型是卷积,可以用 FFT 加速。第四,对于大规模图像,用分块处理,但要注意块之间的重叠和拼接。第五,如果实在跑不动,先从低分辨率、小规模数据开始,验证方法有效性后再逐步放大。

6. 从这一讲出发,后面可以怎么走

这一讲把计算成像的骨架搭起来了:前向模型描述物理过程,逆问题求解反推理想图像,AI提供强先验。这三者之间的关系不是替代,而是互补。前向模型越准确,逆问题越好解;逆问题求解器越强,对先验的依赖越小;AI先验越强,在信息不足时恢复质量越高。但无论哪一环,都离不开对物理过程的尊重和对数据分布的清醒认识。

如果你跟着这一讲的思路走下来,接下来可以选一个具体的方向深入。比如做超分辨率,就深入研究图像退化的前向模型(模糊核、下采样、噪声),然后对比经典正则化方法和深度学习方法的效果差异。比如做单像素成像,就深入研究编码图案的设计和压缩感知恢复算法。比如做相位恢复,就深入研究非凸优化的初始化策略和正则化设计。每个方向都有大量的经典文献和最新工作可以挖。

我个人的体会是:计算成像这个领域,最怕的就是“只调包不懂原理”。你如果能把前向模型写清楚、把逆问题的病态性分析清楚、把AI先验的适用边界想清楚,那你做出来的东西就不仅仅是“跑通了”,而是真正“理解了”。这种理解,才是你在面对新问题时能够举一反三的底气。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进