关于相机的AI与计算摄影

背景

首先叠个甲,本文不涉及大疆内部的任何机密技术,只是一些开发感悟,并不机密与敏感。相机是一个光学传感器Sensor,传感器表面覆盖了一层拜耳滤镜进行取色照射在独立的光电二极管阵列CMOS。ADC将光电二极管的电信号转化为数字信号,而ADC位数决定了整个Sensor的分辨率,比如12bit色深或16bit色深,其实就是ADC的位数。我们最终的Sensor通过如DSI、MIPI、CSI等接口引出到我们的SoC上,利用DMA进行循环读取ADC转化后的数据,并配置水平同步信号和垂直同步信号,实现完整的一帧图像获取。这样我们就在SoC的内存上保留了一个图像的原始数据信号,这个信号的图像就是我们的RAW图。

RAW出来之后剩下的事情就交给我们这些写软件的了。传统ISP是一条固定的流水线,去马赛克、白平衡、降噪、锐化,一步一步走下去,都是工程师对着标准色卡标定出来的。但这几年手机厂商卷夜景、卷人像、卷视频防抖,光靠传统ISP早就顶不住了,于是AI、计算摄影这些词就进来了。

这一期我想写一篇稍微体系一点的东西。起因是我自己最近把一个桌面摄像头的整个软件链路从头到尾写了一遍,从传感器驱动一路写到USB输出,把一条真实相机里该有的环节都摸了一遍。写的过程中我就在想,与其把这些环节零散地记在脑子里,不如顺着一张照片是怎么诞生的这条线,把每一环的原理、功能、思想、算法都摊开来写清楚。这样以后再聊AI、再聊计算摄影,就有了一个完整的坐标系,知道每一样东西是挂在哪个位置上的。

所以这一篇,本质是以点带面,从我踩过的那些坑出发,把整张相机的知识地图铺开。不针对任何具体板子或厂商,只讲原理。我会先从最底层的摄影常识讲起,因为它是后面所有算法为什么这么做的根源;然后钻进传统ISP内部,把RAW域和RGB/YUV域每一道工序说清楚;接着讲让相机赋予观感的3A,也就是自动曝光AE、自动白平衡AWB、自动对焦AF;再讲软件怎么通过V4L2把图拿到手;之后进入重头戏,卷积、降噪、AI ISP;最后落到电子防抖、计算摄影的浅景深、美颜和端到端算法。

这篇文章会很长,但每一节都可以独立阅读。如果你只想了解某一块,可以直接跳到对应的标题。我的目标是:读完这一篇,你能对整个相机软件技术栈有一个从底到顶的完整印象。

我之所以想这么写,是因为我发现很多人在聊相机AI的时候,容易陷入两个极端:要么把它神秘化,觉得AI一上画质就无敌了;要么把它轻视化,觉得不就是套个神经网络嘛。这两种态度都不对。相机里的AI,是一整条精密流水线上的一个环节,它强不强、该不该上、能提升多少,全看它前面的ISP做得怎么样、后面的算力够不够、中间的数据管道稳不稳定。脱离了这条流水线去谈AI,就像脱离了底盘去谈发动机,是没有意义的。

所以AI部分的主线是从一条相机的完整链路是怎么搭起来的,AI在这条链路的哪个位置、承担什么角色。我希望读完的人能建立起一张完整的知识地图:从光子打到传感器上,到它变成你手机里那张好看的照片,中间每一步在干什么、为什么这么干、以及未来会被AI改造成什么样。这样以后再看到任何新技术,你都能把它安放到正确的位置上。好,我们正式开始。

一张照片的完整旅程

首先把全景图铺开,后面每一节都是在这张图上细分。一张照片从光线进来,到最终显示在屏幕上,大致要经过这么几层:

一张照片的完整旅程

这张图里藏着一个很多人忽略的事实:ISP不是一条单向流水线,而是一条可以随时被软件截胡的流水线。传感器出来的RAW,传统ISP先做一遍在物理世界正确的处理,但到了应用层,我们想加AI降噪、加风格化、加超分、加浅景深,随时可以在中间插入自己的环节。换句话说,传统ISP负责把RAW变成一张正确的图,而把正确的图变成一张好看的图,这件事已经越来越多地交到了软件和AI手里。

这个分工是必然的。因为传统ISP它是通用的。一条ISP流水线要同时照顾白天黑夜、顺光逆光、人像风景,只能取一个折中的效果,任何一步的参数都是够大多数场景用的妥协。而软件和AI的价值,就在于能针对具体场景做专用的处理,比如检测到人脸就专门优化人脸,检测到夜景就专门堆多帧。这种从通用到专用的转变,是整个影像行业这几年最大的趋势。

理解了这层分工,后面每一节就好定位了。我们先讲最底层的摄影知识,因为它决定了上面所有环节的为什么。然后讲传统ISP的每一道工序。再讲3A,它是整条链路的地基;接着是V4L2,软件拿到图的入口;然后进入降噪、AI、图像处理这些往上叠加的东西。最后落到计算摄影、美颜和端到端,看看这条链路的尽头是什么。

在正式开始之前,还有两件事值得点明,它们贯穿全文。第一件是数据形态的演变,一张图在链路的不同阶段,是以完全不同的形态存在的,刚出传感器是Bayer RAW,每个像素一个通道,ISP处理完是RGB三通道完整,到了编码和显示又是YUV或压缩码流。切记一定要理解当前处理的是哪种形态的数据,这样可以快速理解每个算法设计的关键。第二件是实时性的约束,相机不是离线的,它要持续地、一帧一帧地产出画面,每一帧都要在几十毫秒内走完这条链路。单帧的时间预算,决定了为什么很多效果很好但太慢的算法在相机里用不了,也决定了为什么后面要花那么多精力讲端侧推理和硬件加速。记住这两点,后面每一节都会用得上。

基础摄影知识:光圈、快门与ISO

在讲任何算法之前,得先把摄影的三件事讲清楚,因为后面AE、景深、计算摄影全都建立在这上面。这三件事就是曝光三要素:光圈、快门、感光度ISO。

光圈

光圈是镜头里那个可以开合的孔,控制进光量。它的大小用f数表示,f数越小光圈越大、进光越多。f数等于焦距除以通光孔径,所以f/1.4反而比f/16的孔大得多。光圈的标准档位是一串按$\sqrt{2}$递增的数,f/1.4、f/2、f/2.8、f/4、f/5.6、f/8,每相邻一档,进光面积差一倍。所以开大一档光圈,就是进光量翻倍。光圈不仅决定进光量,还决定景深,光圈越大,景深越浅,背景越虚化。这就是为什么拍人像要用大光圈,能把背景虚化突出人物主体。

快门

快门是传感器曝光的时间。快门越快,越能冻结运动,但进光越少;快门越慢,进光越多,但手一抖就糊。快门速度的档位也是按倍率走的,1/30秒、1/60秒、1/125秒,每一档差一倍进光量。快门还有一个物理上的讲究:相机的焦平面快门有同步速度限制,超过某个速度,比如1/200秒,就要用前帘后帘的狭缝曝光,这在拍视频和闪光灯配合时会带来卷帘效应,后面讲EIS时还会提到。

ISO

感光度ISO是传感器对光的灵敏度。ISO越高,同样的光能读出更亮的图,但代价是噪声越大。因为提高ISO本质上是把模拟信号放得更大,噪声也跟着一起放大。前文讲过,在有限的输出范围内提高ISO能提高信噪比,但那是相对于ADC的量化噪声而言。信号里本身带的光子噪声,ISO是压不掉的。所以高ISO的图,噪点是真真切切变多了,不是心理作用。

曝光三角

这三个量构成了一个曝光三角关系,如果你想得到一张亮度合适的照片,光圈、快门、ISO必须配比得当。它们之间存在一个严格的调节方式把光圈开大一档、同时把快门加快一档,进光量不变,曝光结果一样。这个控制方式是曝光控制的基础,AE算法就是在这个随动的环境下做平衡的。而这个配比关系,有一个非常优雅的数学表达,叫APEX系统,我们在讲AE的时候会详细展开。现在只需要记住一个直觉:这三个旋钮都能调亮度,但它们各自有各自的副作用,光圈影响景深,快门影响运动模糊,ISO影响噪声。所谓的老法师,就是知道自己愿意牺牲哪个副作用去换另两个。

曝光三角:光圈、快门、ISO 的互易关系

弥散圆

这里还要引入一个贯穿后面浅景深和计算摄影的关键概念:弥散圆,英文叫Circle of Confusion,简称CoC。理想情况下,一个点光源经过镜头会在传感器上汇聚成一个点,但只有恰好对焦在焦平面上的点才是点,前后的点在传感器上会散成一个圆斑,这个圆斑就是弥散圆。弥散圆越小,画面越锐;弥散圆大到一定程度,人眼就觉得糊了。景深的本质,就是弥散圆小到人眼分辨不出模糊的那段物距范围。所谓虚化,不过就是让背景的弥散圆大到肉眼可见。

等效光圈

这里还有一个进阶概念值得提前埋下,叫等效光圈。手机镜头的实际焦距只有几毫米,但厂商会宣传等效24mm、等效50mm,这是因为手机的传感器面积远小于全画幅,同样的视角下,小传感器需要的实际焦距更短。而等效光圈这个概念说的是:小传感器加短焦距,即使f数看起来很小,比如f/1.8,它产生的物理景深,也相当于全画幅上一个更小的光圈。换句话说,手机的光圈在进光量上是真实的f/1.8,但在景深虚化这件事上,它只相当于全画幅的f/8甚至更小。这就是为什么手机物理上很难拍出浅景深,也是后面计算摄影模拟浅景深这一节存在的前提。

传统ISP的RAW域处理

有了摄影基础,就可以钻进ISP内部了。这里我按瑞芯微rkaiq这套ISP引擎的模块划分来讲,因为它和主流的ISP流水线是高度一致的,而且每个模块都有明确的物理意义。ISP的第一步都在RAW域上做,也就是在拜耳马赛克数据上、还没恢复出完整三通道之前,先做几道修复。

拜耳 RGGB 阵列

传统 ISP 的 RAW→RGB→YUV 三域流水线

坏点校正

第一道是坏点校正,英文缩写DPC。传感器上总有一些像素是坏的,有的永远读出一个亮点,叫hot pixel,有的永远读出一个暗点,叫dead pixel,有的是整簇坏掉。坏点如果不处理,去马赛克之后会变成一个亮斑扩散到周围,非常扎眼。DPC的思路是:检测出和周围邻居差异异常大的像素,然后用周围同颜色像素的中值或均值把它替换掉。检测这一步通常也分静态和动态两种,静态坏点可以在出厂时标定好、存成一张坏点表;动态坏点则要在运行时实时判断,因为坏点可能随温度、曝光变化而出现,比如一个像素的亮度超出周围同色像素均值好几倍标准差,就判定为坏点。这是一个典型的异常检测加插值问题。

黑电平校正

第二道是黑电平校正,英文缩写BLC。上一期说过,传感器在没有光照时,光电二极管也会因为暗电流输出一个非零的底,叫黑电平。它不是光线,却会被当成亮度一起读进来,所以要把这个底减掉:

其中B是标定出来的黑电平值。这一步不做,暗部就会发灰、发雾,整个画面的动态范围也被抬高了底噪。黑电平的标定通常是在全黑环境下,比如用镜头盖盖住镜头,读传感器输出,取一个平均值或分通道的值作为B。值得注意的是,不同增益ISO下黑电平可能略有不同,精细的做法是给每个增益档都标一个黑电平。

镜头阴影校正

第三道是镜头阴影校正,英文缩写LSC,也叫暗角校正。镜头中心进光多、边缘进光少,广角镜头尤其明显,所以拍出来的图四周是暗的。LSC用一个随像素到光心距离变化的增益,把边缘抬起来。这个增益曲线通常是标定出来的,可以是径向对称的,只随半径变化,也可以是非对称的,因为镜头光轴可能偏离传感器中心,暗角不均匀。有些LSC还会分通道校正,因为不同波长光的衰减不一致,会导致边缘偏色。

绿平衡校正

第四道是绿平衡校正,英文缩写GIC。拜耳阵列里绿色像素是红蓝的两倍,RGGB,2×2里有两个G,这两个G像素分别紧邻不同的邻域,实际制造和读出上会有微小的不一致,导致绿通道内部出现棋盘格式的明暗差异。GIC就是把这个差异抹平。这一步很细小,但不去掉,画面会有细微的纹理感,在放大后尤其明显。

这四道之外,RAW域上还有一些可选的高级处理,比如高动态范围合成HDR、动态范围压缩DRC、去雾Dehaze、去紫边Chromatic Aberration Correction等等。它们的共同特点是:都发生在数据还是线性的、还是Bayer结构的时候,这时候数据最原始,物理意义最明确,处理起来最干净。这也是为什么很多AI算法喜欢在RAW域动手,RAW是线性的,没有伽马和色彩空间的非线性干扰,网络更容易学到物理规律。

补充一句LSC的数学形态,因为它其实就是一个逐像素的增益乘:对于每个像素,算它到光心的归一化半径r,然后查一条增益曲线$gain(r)$,把原始值乘以这个增益。这条$gain(r)$曲线在中心是1,不补偿,往边缘逐渐抬升,补偿暗角,形状类似一个下凸的碗。标定的时候,对着均匀亮度的灰墙拍一张,看四角比中心暗了多少,反推出$gain(r)$。这个标定查表逐像素乘的三段式,几乎是ISP里所有校正模块的统一套路,后面讲CCM、3D LUT还会反复见到它。

传统ISP的RGB与YUV域处理

RAW域修完之后,数据要经历一次最重要的转变,去马赛克,英文Demosaic,从每个像素只有一个通道的Bayer图,恢复出完整的RGB三通道。这是整条ISP里最容易出伪彩和摩尔纹的地方,值得单独说。

去马赛克

上一期讲过,拜耳阵列里每个像素只装了红绿蓝三种滤镜中的一种。去马赛克要做的,是给每个像素猜出它缺的那两个通道。最简单的方法是双线性插值,缺哪个通道就取周围同色像素的平均。但双线性插值在边缘处会糊、在高频纹理处会出伪彩,比如彩色边缘的彩虹纹,和摩尔纹,细密纹理的干涉条纹。于是有了各种自适应算法,核心思想都一样:先判断局部是不是有边缘、边缘朝哪个方向,然后只沿着边缘方向插值,不要跨边缘平均。比较经典的比如Hamilton-Adams算法,它会先算水平和垂直两个方向的梯度,哪个方向梯度小,说明是平滑方向,就优先沿那个方向插值。这一步的难点在于,它是个病态问题,你手里只有三分之一的信息,要重建出全部信息,插值算法再聪明也是在猜,猜不准的地方就露馅。这恰恰是AI最喜欢下手的地方,后面讲AI ISP时会回到这里。

白平衡

去马赛克之后就是RGB域的几道色彩工序。第一道是白平衡,英文WB,解决不同色温下白色还是不是白色的问题,详细的估计算法放到3A那节讲,这里只说它在流水线里的位置:它在去马赛克之后、色彩校正之前,因为这时候每个像素终于有了完整的三通道,可以按通道调增益了。

色彩校正矩阵

第二道是色彩校正矩阵,英文缩写CCM。传感器对颜色的响应和人眼不一样,CCM用一个3×3矩阵把传感器的原始颜色响应,映射到人眼习惯的标准颜色空间,比如sRGB:

这个矩阵通常也是标定出来的,对着标准色卡,24色Macbeth卡,拍一张,求解一个使色卡颜色误差最小的3×3矩阵,本质上是一个最小二乘问题。CCM和白平衡是配套的:白平衡先把白点归一到中性,CCM再把整体色彩映射到标准空间,两者共同决定了色彩的准确度。

伽马与 Log

第三道是伽马校正,英文Gamma。人眼对暗部亮度变化比亮部敏感,但传感器是线性的。直接把线性值送去显示,暗部死黑、亮部刺眼。伽马校正用一个幂函数把中间调拉起来:

这也是影调这个词的由来,伽马曲线的形状,直接决定了一张照片是胶片味还是数码味。很多ISP还会用一个更精细的分段映射,比如BT.709的OETF曲线,本质都是在做线性转感知这件事。

说完伽马,还得提一个更有趣的处理,Log曲线。伽马虽然把暗部抬起来了,但它的幂函数在高光段压得特别狠:越亮的地方码值越挤,稍微一过曝就死白一片。而Log曲线是对整个动态范围做一种更均匀的压缩,暗部和亮部都留出码值余量。影视工业里的S-Log、C-Log、LogC就是干这个的,它可以把传感器能捕捉的十几档动态范围,塞进有限的8bit/10bit码值里,既保住阴影,又不让高光死白。数学形态就是一个对数映射:

输入光谱十几档动态范围 vs CMOS 有限接收范围:Log 把十几档塞进有限码值

拍出来的log素材灰蒙蒙一片,俗称灰片,但里面藏着的信息量最大,后期套一个LUT转回Rec.709就还原出正常观感。这条线性到Log到LUT还原的路子,本质就是先把动态范围无损地存下来,显示的时候再去做风格化取舍。

同一张真图在原始 / 伽马 / Log 下的观感:Log 就是灰片

线性、伽马与 Log 曲线的对比

RGB域的最后一道是3D LUT,一个三维查找表,可以做更精细的色彩风格化,这个我们在风格滤镜那节展开。

YUV 与色度下采样

接着数据转到YUV域,在这里做最后的降噪和锐化。为什么降噪要放到YUV域?因为人眼对亮度噪声敏感、对色度噪声迟钝,所以可以把色度通道降得更狠一些、亮度通道保守一些,比在RGB域一刀切更精细。锐化则只在亮度通道上做,对色度做锐化只会放大彩色噪点。至此,一张物理正确的图才算出炉。这套RAW到RGB到YUV的工序,就是传统ISP的全部家当,也是后面AI ISP要去改造的对象。

YUV还有一个省带宽的秘密,叫色度下采样。人眼对亮度分辨率敏感、对颜色分辨率迟钝,所以可以把色度通道降采样,最常用的是4:2:0,也就是每2×2的4个像素共享一组色度值。RGB转YUV再4:2:0,数据量直接减半,而人眼几乎看不出区别。这就是为什么编解码器、摄像头、视频传输全都用YUV而不直接用RGB,它不是技术妥协,而是巧妙地利用了人眼的生理特性。理解了这个,就理解了为什么后面V4L2采集、硬件编码里到处都是NV12这种YUV格式。

自动曝光AE

讲完ISP的静态工序,该讲让它动起来的3A了。3A是自动曝光AE、自动白平衡AWB、自动对焦AF的总称,它是整条链路的地基,如果地基歪了,上面盖什么都不稳。先说AE。

APEX 曝光方程

AE的目标是:让画面亮度处在一个合适的目标值附近。它要调的就是前面说的曝光三要素。这三要素的配比关系,有一个非常优雅的量化系统叫APEX,它把乘除关系全部转成了加减关系。定义几个值:

其中N是f数、t是快门时间,单位秒、B是场景亮度、K是测光校准常数,通常取12.5。这些值满足一个极其简洁的方程:

左边是相机的进光量,右边是场景的亮度需求。它的好处在于:光圈、快门、ISO每调一档,亮度翻倍或减半,对应的值就加1或减1,加减法比乘除法直观得多。AE算法本质上就是在这个方程里来回平衡,场景亮度Bv由测光得到,目标Av加Tv由曝光策略决定,然后分配多少个档位给光圈、多少个给快门、多少个给ISO。

测光

光知道方程还不够,还得知道场景亮度是多少,这就是测光。最简单的测光是全图平均,方法简单但容易出错,比如拍雪地会严重欠曝,雪太亮,平均亮度高,相机以为太亮就压暗,拍黑夜会过曝。所以工程上用的是分区测光或中心加权测光:把画面分成若干块,给中心区域更高的权重,主体通常在中间,再综合出目标亮度。更智能的做法还结合场景识别,检测到人脸,就优先保证人脸亮度。测光的本质,是从图像的统计量反推场景的真实亮度,而图像统计量里藏着的各种偏差,雪地、夜景、逆光,就是测光要克服的。

曝光程序与平滑收敛

拿到目标亮度后,就是三要素的分配策略。这个策略体现了会拍照的经验:先满足快门,保证不糊,再满足光圈,保证景深需求,最后用ISO兜底。比如拍静止场景,优先降ISO、拉长快门;拍运动场景,优先保快门、必要时牺牲ISO。这就是AE里最讲究的曝光程序,英文叫Program Line,不同厂商、不同场景的曝光程序都不一样,是各家调优的侧重点,也是功能亮点。此外AE还要处理一个工程细节:曝光不能跳变。如果场景亮度突然变化,比如从室内走到室外,曝光参数如果一步到位,画面会突然一亮一暗地闪烁。所以AE要做平滑收敛,把目标曝光拆成若干小步,逐步逼近,让亮度过渡自然。这就是为什么你从暗处走到亮处,画面是慢慢变亮而不是啪地一下变亮。

曝光补偿与锁定

除了平滑收敛,AE还有几个容易被忽略的细节,第一个是曝光补偿和场景锁定。用户手动的曝光补偿,也就是EV偏移,本质上就是在APEX方程的右边加一个常量,把整个目标亮度整体往上或往下平移一档,让相机认为的正确亮度和用户想要的亮度错开;而场景锁定,也就是AE Lock,则是把当前的曝光参数冻住,不让它随画面变化,拍视频时经常用它,避免人物移动、背景变化导致曝光来回跳。第二个是测光的时序问题:AE依赖的亮度直方图来自ISP的统计模块,而统计模块通常滞后当前帧一到两帧,如果AE的收敛速度设得太快,就会在滞后的数据上过冲,产生亮度振荡,画面会周期性地忽明忽暗。所以工程上AE有三个互相耦合的关键参数:测光权重、收敛步长、目标亮度,如果调亮一个往往要连带调另外两个,牵一发动全身,这正是AE最吃经验、也最难调好的地方。

自动白平衡AWB

AWB解决的是色温问题。同一个白色物体,在日光下偏冷、在白炽灯下偏暖,但人眼会自动把它看成白色,这叫颜色恒常性。传感器没有这个能力,它忠实地记录了不同光源下的颜色,于是需要AWB来估计当前的光源色温,把RGB三通道的增益调回来,让白色还原成白色。

灰度世界法

最经典的估计算法是灰度世界法,英文Gray World。它基于一个统计假设:真实世界的场景,红绿蓝三个通道的平均反射率是相等的,平均下来是灰的。于是我们计算整幅图三通道的均值$\bar R, \bar G, \bar B$,然后调整增益,让三者相等:

以绿色通道为基准,把红蓝通道拉到和绿一样,白色就还原了。灰度世界法简单高效,但它有一个明显的失效场景:当画面被某一种颜色大面积占据时,比如拍一片红色的晚霞、一大片绿草地,这个平均是灰的假设就崩了,白平衡会偏。所以它是个够用但不鲁棒的baseline。

主成分分析 PCA

比灰度世界法更鲁棒的是主成分分析法,英文缩写PCA。它的思路是:把图像的所有像素投影到RGB空间里,做一次主成分分析,找到像素分布方差最大的那个方向,这个方向通常就对应着光照颜色的方向。因为场景里物体的颜色是多样的、分散的,而光照颜色是共同叠加在一切物体上的那个统一偏置,所以在统计上,光照就是那个最显著的主成分。估计出光照方向后,同样可以算出各通道的增益。PCA比灰度世界更抗单色大块,因为它利用的是分布的几何结构,而不是简单的均值。

灯箱标定

除了算法,AWB还严重依赖标定。灯箱校正就是最标准的标定手段:把相机放进一个标准灯箱,灯箱能发出已知色温的标准光源,比如D65日光、A光源白炽灯、TL84荧光灯等,在每个标准光源下拍标准灰卡或色卡,记录下这个色温下正确的白平衡增益是多少,做成一张增益查找表。实际使用时,算法先估一个色温,再查表得到增益。这张表的质量直接决定白平衡的精度。

普朗克轨迹

估色温这件事,还可以借助物理规律,黑体辐射图。不同色温的光源,在色度图上的位置不是散乱的,而是精确地落在一条曲线上,这条曲线就是普朗克轨迹,对应着理想黑体在不同温度下发出的光的颜色。日光、白炽灯这些常见光源都近似黑体,所以它们都落在这条轨迹附近。AWB算法估出色度后,把它投影到这条轨迹上最近的点,就得到了一个最合理的色温。这条曲线,是把颜色和温度联系起来的桥梁。

CIE 1931 色度图与普朗克轨迹

色温传感器

更进一步的方案是色温传感器。它是一个独立的小传感器,直接测量环境光的色温,有的还能测明度,把结果作为一个先验喂给AWB算法。色温传感器的好处是它不受画面内容影响,就算你对着单色墙壁,它也能告诉你环境是5000K。在手机里,色温传感器用来做快速、稳定的白平衡启动值,让相机一打开就是对的,而不是先闪一下再收敛。实际系统里,往往是色温传感器给先验、灰度世界和PCA给统计估计、灯箱标定表给最终映射,三者融合,才得到一个又快又准的白平衡。

白点检测

顺带说一句,AWB还有一个常见的前置处理叫白点检测:先把画面里那些已经过曝、近乎纯白的像素找出来,用它们来估计色温,因为这些像素最忠实地反映了光源本身的颜色,受物体颜色的干扰最小。而灰度世界和PCA有一个共同的短板,它们在几乎没有白色物体的场景里,比如一片蓝天、一面纯色墙壁,都会失效,因为平均是灰的假设和主成分是光照的假设都站不住脚了。这也解释了为什么高端方案一定要配一个色温传感器做兜底:算法总有猜错的时候,但物理传感器直接量出来的色温,永远是对的。

自动对焦AF

AF的目标是找到最清晰的对焦位置。这里的关键问题是:怎么衡量清晰?两种主流方案,对应两种传感器设计。

对比度检测 CDAF

第一种是CDAF,对比度检测对焦。它的衡量标准是:图像越清晰,局部对比度越高。清晰对焦时,边缘锐利,相邻像素亮度差大,高频能量高;失焦时,图像变模糊,对比度下降。所以CDAF的工作方式就是:移动镜头到一个位置,算一次对比度,再移动、再算,找到对比度峰值的位置。对比度值怎么算?工程上常用的是对图像做高通滤波,如拉普拉斯算子的绝对值求和,或者直接统计梯度幅值,本质都是在度量高频能量。

CDAF的搜索策略就是爬山法,英文Hill Climbing:从当前位置开始,往一个方向移动镜头,如果对比度上升,说明方向对了,继续同向;如果对比度下降,说明过了峰值,就反向移动。就这样来回逼近,像爬山一样爬到山顶。爬山法简单可靠,但有两个固有缺点:一是慢,要反复移动镜头、反复计算;二是可能陷入局部极值,或者来回拉风箱,在峰值附近反复振荡。为了克服这些,实际实现里爬山法有很多变体,比如先大步粗扫找到峰值的大致区间,再用小步精扫收敛;或者用二次曲线拟合对比度曲线,一步算出峰值位置。但再怎么优化,CDAF的试错本质决定了它慢。

相位检测 PDAF

第二种是PDAF,相位检测对焦。它不靠试,而是直接算。原理是在传感器上埋一些特殊像素,每个对焦像素只被遮住一半,左右遮罩或上下遮罩,于是从同一场景光线会形成一对半像。当对焦准确时,这对半像重合;失焦时,它们之间产生一个相位差,这个相位差的大小和方向直接告诉对焦系统离焦量是多少、往哪个方向调。所以PDAF是一步到位的,测一次相位差,直接算出镜头该移动多少,不用爬山试错。这就是为什么手机和现代相机对焦又快又安静。

CDAF 爬山法与 PDAF 相位检测

混合对焦与激光辅助

PDAF快,但也不是万能。它的相位检测在低光、低纹理场景会失灵,半像素读出的信噪比低,而且制造上更复杂,要在传感器上挖对焦像素。所以实际系统往往是混合对焦:PDAF先快速粗对焦,CDAF再精对焦收尾,两者结合,既快又准。此外还有一个对焦区域选择的问题,画面里有很多物体,该对焦在哪?简单的是对焦中心,智能的会结合人脸检测对焦到人脸上,或者让用户点选。这个对哪里的问题,和AE的测哪里、AWB的以哪块为基准是同一个思想,都是先理解画面,再局部决策。

除了CDAF和PDAF,还有一个补充方案值得一提,就是激光对焦,英文ToF,全称Time of Flight。它在镜头旁放一个激光测距模块,朝目标打一束光、测量反射回来的时间差,直接算出主体到相机的距离,然后一步到位把镜头推到对应位置。它完全不依赖画面内容,在纯黑环境里照样能对焦,这是CDAF和PDAF都做不到的;缺点是只对近距离有效、且一次只能测一个点的距离,拍远处或拍大范围场景就力不从心了。所以高端手机往往是PDAF加激光加CDAF三管齐下,PDAF负责快、激光负责暗光兜底、CDAF负责精调收尾,三者各管一摊,覆盖又快、又准、又能在暗光下工作的所有需求。

统计量时序对齐

AF之外,3A还有一个常被忽略但极其重要的工程问题:统计量的时序对齐。AE、AWB用的亮度直方图、白点统计,AF用的对比度,都来自ISP的统计模块,这些统计量必须和当前的帧严格对齐。一旦错位,比如统计量滞后了一帧,3A就会在错误的数据上做决策,画面出现亮度闪烁、颜色漂移。所以工程上3A通常是一个独立进程,先于采集启动、先把标定文件加载好,再让采集开始,这也是为什么很多相机一打开画面是绿的或暗的,过一秒才正常,往往就是3A还没就位。

V4L2视频采集框架

ISP把图处理好之后,数据躺在内核的缓冲区里。在Linux里,用户态程序把图拿出来的标准姿势就是V4L2,全称Video for Linux 2。这一节把整个框架讲一遍,因为它是一切相机软件的起点。

分层架构

先看架构。V4L2不是一个简单的字符设备,而是一套分层框架。最底层是具体的硬件驱动,比如某个ISP、某个USB摄像头的驱动,它注册成一个v4l2_device;这个设备可能包含多个子设备,比如一个ISP背后还有传感器、镜头马达这些v4l2_subdev,它们之间的拓扑关系由一个叫Media Controller的框架来管理,你可以把它理解成内核里的一个媒体管线图,描述数据从传感器到ISP到输出的走向。对用户态而言,最终暴露出来的是一堆/dev/videoN节点,每个节点代表管线里的一个端口,采集口、输出口等,你对它做ioctl就能操作。

工具链

用户态看V4L2,看到的就是这个/dev/videoN文件节点。操作它有一套标准的工具链,最常用的是v4l2-ctl。比如v4l2-ctl —list-devices列出所有视频设备,—list-formats-ext列出某个设备支持的所有格式和分辨率,—set-fmt-video=width=1920,height=1080,pixelformat=NV12设置格式,—stream-mmap —stream-count=10抓10帧存下来。还有一个v4l2-compliance,专门用来测驱动是否符合V4L2规范,排查驱动bug时非常好用。这套工具链,是每个做Linux相机的人案头必备的,很多时候一个v4l2-ctl —list-formats-ext就能定位到底是驱动不支持还是应用写错了。

采集五步走

采集本身,是一套固定的五步走流程:找设备、协商格式、申请缓冲、开流、循环取图。找设备这步有个经典陷阱,多节点驱动里,capabilities字段是所有节点的并集,用它判断这个节点是采集还是输出会误判,必须用device_caps字段,它才代表当前这一个节点的能力。协商格式这步,之所以叫协商,是因为你请求1920×1080的NV12,驱动可能只支持1280×720,最后给你什么得读回来。这里还引出NV12这个关键格式,一种YUV420半平面格式,一个亮度平面Y,每像素一个字节,加一个交错的色度平面UV,每2×2像素共享一组UV,比RGB省一半带宽,是编解码器和ISP输出最爱的格式。

内存模式

申请缓冲是V4L2的精髓,它支持三种内存模式:MMAP内存映射、USERPTR用户指针、DMABUF DMA共享。最经典的是MMAP,内核分配缓冲、用户态mmap把它映射到自己的地址空间,零拷贝访问,不用来回拷数据。申请缓冲用VIDIOC_REQBUFS,指定要几个缓冲,内核分配好后,用VIDIOC_QUERYBUF拿到每个缓冲的偏移量,再mmap映射进来。DMABUF模式则更进一步,可以让缓冲在ISP、编码器、显示这些不同的硬件之间直接共享,一次都不经过CPU,是高性能管线的首选。

QBUF/DQBUF 轮转

开流之后,就是一个出队、处理、回队的轮转循环,这是V4L2最核心的运行时模型。它的工作机制像一个环形队列:一开始,你申请的所有缓冲都在空闲队列里,你用VIDIOC_QBUF把它们一个个入队,交给驱动去填充;驱动采集到一帧,就填充一个缓冲,把它放到完成队列;你用VIDIOC_DQBUF从完成队列里出队一帧,处理它,处理完再用VIDIOC_QBUF把它塞回空闲队列,循环使用。整个过程就是QBUF和DQBUF的交替轮转,缓冲在一个闭环里打转,永远不会分配新内存。理解了QBUF/DQBUF这个轮转,就理解了V4L2的零拷贝是怎么实现的,数据从头到尾只在那一块内核内存里流转,用户态只是借用它看一眼。

V4L2 的 QBUF/DQBUF 环形缓冲

性能调优

这个轮转模型里还藏着性能调优的钥匙。设备通常以非阻塞模式打开,直接DQBUF在没数据时会立刻返回EAGAIN,如果傻乎乎地循环重试就是100% CPU忙等,正确姿势是先poll等可读再出队。另一个更微妙的点是缓冲数量:每多一个在队列里排队的缓冲,从塞回到取出的往返就多一帧的延迟,所以缓冲不是越多越好,它本质是用更长的延迟换更不容易丢帧。实时视频里,缓冲数往往要压到最小,才能把端到端延迟降下来。还有一个NV12的经典坑:Y平面每行的字节数可能大于图像宽度,也就是行对齐的stride,UV平面的起始位置不是宽乘高,而是stride乘hstride,这个偏移算错了,UV就会错位,画面出现色块错乱。

卷积与频域滤波

前面讲降噪的时候,反复提到滤波这个词。滤波到底是什么?在数学上,图像上的滤波就是卷积。这一节把卷积和它的频域视角讲清楚,因为这是理解所有降噪、锐化、甚至卷积神经网络的地基。

卷积的定义

一维卷积的定义是:一个信号f和一个核g的卷积,是把g翻过来、滑动、逐点相乘再求和:

二维卷积与核

二维图像上的卷积就是把这个过程推广到两个维度:一个卷积核,比如3×3的小矩阵,在图像上滑动,每次把核和它覆盖的像素逐点相乘再求和,得到输出图像的一个像素。你选的核不同,卷积的效果就完全不同:核是周围一圈取平均,就是均值滤波,能把噪声抹平;核是中间高、四周低的高斯形状,就是高斯滤波,平滑得更柔和;核是中间是正、四周是负,比如拉普拉斯核,就是在算二阶导数,能突出边缘,这就是锐化。还有Sobel核、Prewitt核,是在算一阶梯度,专门用来做边缘检测。

卷积:滑动、相乘、求和

卷积定理与频域

这里有一个极其重要、却常常被忽略的事实:滤波和傅里叶变换FFT是不分家的。卷积定理告诉我们,两个信号在空间域或时间域的卷积,等于它们在频域的乘积:

频域看降噪与锐化

这意味着什么?意味着在图像上滑动核做平滑,和把图像变换到频域、把高频分量乘一个小系数、再变回来,是同一件事。一张图变换到频域后,低频对应大面积的平缓变化,比如天空、皮肤,高频对应细小的剧烈变化,比如噪点、边缘、纹理。于是降噪在频域里变得一目了然:噪点集中在高频,用一个低通滤波器把高频压掉,噪声就没了;锐化则相反,用一个高通滤波器把高频提起来,边缘就突出了。二维图像的频谱通常用一个二维FFT变换得到,中心是低频、四周是高频,你甚至可以在频谱图上直观地看到一张图是锐还是糊,锐的图高频成分多,频谱四周亮;糊的图高频成分少,频谱集中在中心。

频谱:原始、低通、高通

为什么要讲FFT呢?因为它还和计算效率有关。对于小的卷积核,3×3、5×5,直接在空间域滑动算最快;但对于大核,比如100×100的大模糊,空间域要算一万次乘法,而频域只需要一次点乘,用FFT把图像和核都变换过去、相乘、再反变换回来,反而快得多。这就是滤波FFT不分家的另一层含义,它们不只是数学上等价,在工程上也是可以互相换算、按需选择的两种实现。

与 CNN 同谱系

这个频域视角,和后面要讲的卷积神经网络是同一个谱系,CNN里的卷积层,本质上就是在学出合适的滤波核,只不过传统滤波的核是人工设计的,高斯核、拉普拉斯核,而CNN的核是从数据里学出来的。理解了传统卷积和频域,再去看CNN,就不会觉得它神秘了,它就是一堆会自动学习的滤波器。这也是为什么很多图像处理工程师转行做深度学习很快,他们早就和卷积打过交道了。

把卷积和频域统一起来看,还能帮我们理解很多工程上的直觉。比如模糊一张图和先缩小再放大在频域上是相近的,都是在砍高频信息;而锐化过头的代价,是频域里的高频被过度抬升,边缘处出现白边和振铃,这种振铃在频域里就是所谓的吉布斯现象。再比如,为什么JPEG压缩会留下块状和蚊噪?因为JPEG是分8×8的块做DCT,一种和FFT同源的频域变换,量化时把高频系数抹掉,块与块之间的高频不连续,就产生了块效应;蚊噪则是高频系数被过度量化后,在强边缘周围出现的振铃。理解了频域,这些看起来玄学的伪影,其实都有清晰的数学来源,不再是玄学。

降噪的演进:从空间到时域到AI

有了卷积和频域的地基,降噪的演进史就能讲清楚了。降噪是相机画质里最吃力的一环,它的演进史,本质就是从显式规则到学习的缩影。

空间域降噪

最早的空间域降噪,思路是噪点是像素点,跟邻居不一样,于是用滤波把突兀的像素抹平。最基础的是均值滤波,但它连边缘一起糊了;改进一点是双边滤波,英文Bilateral Filter,它在做平均时同时考虑两个权重:空间距离近的权重高、亮度接近的权重高。这样平滑就绕着边缘走了,噪点被抹平,但边缘两侧亮度差异大、权重低,边缘就保住了。双边滤波的权重可以写成一个空间核和一个亮度核的乘积,前者是高斯、后者也是高斯,两者相乘,就同时约束了空间上近和亮度上像两个条件。更进一步的非局部均值,英文Non-Local Means,简称NLM,则把找相似像素的范围扩大到整幅图,凡是纹理相似的块都参与加权平均,降噪效果更好但计算量巨大。

空间域降噪的宿命难题是:噪声和纹理长得太像了,都是局部高频波动,滤波器分不清哪个是噪点、哪个是头发丝,于是降噪一用力细节就糊,保细节一用力噪点就回来。这个矛盾,空间域自己解决不了。

时间域降噪

于是有了时间域降噪。它的核心洞察是:静态场景里,噪声是随机的、一帧一帧抖,但信号是稳定的。把相邻帧按比例混合,噪声就互相抵消了:

其中prev是上一帧的对应像素,a是混合系数。这就是一阶IIR滤波器。但它有个致命问题:画面里有东西在动时,直接混合会拖出鬼影。于是引入运动门限,当前帧和上一帧差异大的地方是运动区域,就增大a,更相信当前帧;差异小的地方多混历史、多降噪:

亮度通道和色度通道分开处理,因为人眼对亮度噪声更敏感。更高级的时间域降噪还会做运动估计,像视频编码那样估计每个块的运动矢量,对有运动的区域做运动补偿后再混合,进一步减少鬼影。这个算法简单、省、有效,到今天还在被大量使用。但它的天花板也很明显:它只知道这个像素和上一帧差了多少,它不知道什么是纹理、什么是噪声,参数永远在折中。

AI 降噪

AI降噪的思路彻底反过来了:不靠相邻帧混合这种显式假设,而是喂给网络海量的带噪图干净图配对,让网络自己学一个从带噪到干净的映射。网络见过几万张图之后,就知道了什么是纹理、什么是噪声,这是传统滤波永远做不到的。AI降噪和IIR最本质的区别就在这里:IIR是我告诉你物理规律,你照着算;AI是我塞给你几万张图,你自己把规律找出来。前者可解释、可控、但上限低;后者上限高、能处理它见过的各种复杂噪声模式,但它是黑盒。把空间域、时间域、AI这三代放在一起看,能看到一条清晰的主线:人类显式写下的规则越来越少了,从数据里学出来的成分越来越多了。

如果非要给这条演进路线画一个坐标系,横轴是参数从哪里来,纵轴是效果上限。空间域滤波的参数是手工调的,核的大小、权重,时间域IIR的参数也是手工调的,混合系数、运动门限,它们可解释、可控、但上限被人想得到的规则锁死了,人想不到的噪声模式,滤波器就处理不了。AI降噪的参数是从几十万张图里学出来的,上限高、能处理各种复杂噪声,但人再也看不懂网络内部在干什么,出了问题也不知道该改哪里。这个坐标系一路延伸,它的终点就是后面要讲的AI ISP,它把学习这件事,从降噪这一个环节,推到了整条ISP流水线上,让从数据里学取代手工调参的范围越来越大。

AI ISP与先进算法

有了降噪的铺垫,AI ISP就很好理解了:它就是把传统ISP流水线里最吃力的几个环节,换成神经网络。这里要说明的是,我自己的项目里并没有真的上这些AI ISP,但这一节不局限于项目,而是讲讲这个方向目前主流的先进算法,看看学界和业界在往哪走。

联合去马赛克与降噪

去马赛克是AI最早攻克的环节,也是最自然的切入点。因为去马赛克本质是个重建问题,你手里只有三分之一的信息,要重建出全部信息,而重建正是神经网络最擅长的事。早期的代表工作是DemosaicNet,2016年,它用卷积网络直接从Bayer输入回归出RGB三通道,比双线性插值准得多,边缘伪彩和摩尔纹明显减少。更进一步,学界发现去马赛克和降噪应该联合起来做,英文缩写JDD,因为真实传感器出来的RAW是既有马赛克又有噪声的,先降噪再去马赛克、还是先去马赛克再降噪,都不是最优,一个网络同时把两件事做了反而更好,噪声统计在Bayer域更干净,去马赛克在干净的输入上更准。这个联合优化的思想,是AI ISP比传统ISP高明的地方之一:传统ISP是分步独立调优的,AI可以把多个步骤放进一个可微分的图里联合优化。

降噪网络演进

降噪网络是AI ISP里成果最丰硕的。最早有DnCNN,2017年,它引入残差学习,不是直接学干净图,而是学噪声本身,然后从输入里减去噪声。这个trick让训练稳定得多。接着UNet架构,编码器解码器加跳跃连接,成了降噪的主流骨架,因为它能同时保留多尺度的细节。再往后,NBNet在2021年用自适应图像块投影、NAFNet在2022年用非线性激活自由网络、Restormer在2022年把Transformer引入降噪,一路把降噪的PSNR推向新高。这些网络名字不必都记住,记住一个趋势就够:降噪网络的演进方向是更大的感受野、更聪明的特征复用、更稳的训练。

端到端 ISP 与数据生成

更宏大的方向是端到端ISP。传统思路是保留传统ISP的骨架,用AI替换其中几个环节;端到端思路则是彻底扔掉传统骨架,RAW进去、一张好图出来,中间全是网络。代表工作有DeepISP,2018年,它端到端地学了从RAW到RGB的完整映射;以及Unprocessing,2019年,这个工作很有意思,它的贡献不是学得更好,而是怎么生成训练数据:它反向模拟了ISP的每一步,逆伽马、逆色调映射、逆白平衡,把干净的sRGB图反算回带噪的RAW,从而凭空造出海量的RAW-RGB配对数据。这个逆向ISP的思路影响深远,因为它解决了AI ISP最大的瓶颈,真实RAW数据太难采集。理解了Unprocessing,就理解了为什么AI ISP这几年突然加速:不是模型多聪明,而是数据管够了。

RAW 域直接出片

除了这些替换环节的思路,还有一个更有野心的方向,叫RAW域直接出片:不经过任何传统ISP步骤,网络直接吃Bayer RAW,输出最终的sRGB。这需要网络自己悟出去马赛克、白平衡、伽马这一整套物理规律,难度极大,但好处是彻底绕开了传统ISP的手工标定,理论上能逼近图像质量的上限。目前这条路还处于研究阶段,落地最多的还是AI替换关键几步加传统兜底的混合方案。

AI ISP 的评测

顺带说一个AI ISP绕不开的工程话题:评测。传统ISP有标准色卡、灰阶卡、清晰度测试卡,好坏一目了然;AI ISP的评测则复杂得多。PSNR和SSIM是纸面指标,但它们和人眼观感常常不一致,一张PSNR很高的图,可能被AI抹出了塑料感或油画感,纹理过于平滑,人眼反而觉得假。所以业界开始引入主观评测,双盲打分,和感知指标,如LPIPS,来补足。这也是AI影像落地时最大的争议点:到底以客观指标为准,还是以人眼看着舒服为准。这个争议,至今没有标准答案,也解释了为什么有的AI相机参数很能打,样张却翻车。

图像处理:电子防抖、风格滤镜与硬件编码

ISP把正确的图做出来了,AI把更干净的图也做了,但这一条链路还没走完,图要稳、要好看、要能传出去。这就是ISP之后的应用层图像处理,我挑三个最有代表性的讲:电子防抖、风格滤镜、硬件编码。

电子防抖

先说防抖。手持拍摄会抖,解决方案分两种。光学防抖,英文OIS,是物理手段,检测到抖动后,用马达反向移动镜头或传感器,把光路稳住。电子防抖,英文EIS,是软件手段,用陀螺仪实时测出角速度,积分得到每一帧相机的姿态变化,然后对图像做一个反向的几何变换,平移、旋转、甚至透视,把抖动抵消掉。EIS的代价是要裁掉边缘一圈,因为反向变换后边缘会露出没有数据的区域,所以防抖越强、裁剪越多、视场角越小。EIS和OIS经常配合使用:OIS先稳住大的物理抖动,EIS再收尾残差。这一块的本质是姿态估计加图像重投影,和前面讲的几何校正,鱼眼,是同一个数学谱系,都是算出像素该去哪,再重采样。另外EIS还要处理卷帘快门效应,英文Rolling Shutter,传感器是逐行曝光的,快速运动时画面会倾斜,EIS可以用陀螺仪的数据对每一行做不同的校正,把倾斜也修掉。

电子防抖:陀螺仪/光流测运动,反向几何变换抵消

风格滤镜与 3D LUT

再说风格滤镜,就是3D LUT那一套。前面ISP的RGB域里提过3D LUT,这里展开它的原理。它的思路特别朴素:与其实时算一个复杂的色彩映射,不如预先算好。把RGB空间在三个维度上各切成N份,比如N=17,就有17×17×17个格子点,每个格子点存一个映射后的RGB值;运行时输入一个RGB,定位到它落在哪8个相邻格子之间,做三线性插值:

一张.cube文件就是一个LUT,8种风格就是8张表。它的优点是确定性、可逆、几乎不占算力;缺点是只能做逐像素的颜色映射,表达不了语义级的变换。所以风格化这件事上,LUT负责稳定实时全局的色调,AI风格迁移负责LUT表达不了的语义变换,各司其职。

3D LUT:RGB 立方体格点与三线性插值

硬件编码

最后是硬件编码。图要传出去,USB摄像头、网络直播、存文件,就得压缩。如果是视频,就用H.264/H.265;如果是USB摄像头这类逐帧场景,就用MJPEG,逐帧JPEG。H.265,也就是HEVC,比H.264压缩率更高,同样画质省一半码率,但编码复杂度也更高;MJPEG不压缩帧间冗余,码率大但延迟低、容错好,适合实时传输。这一步几乎是硬件的活,用SoC上的视频编码单元VPU来做,CPU做不来,一帧1080p的软件编码就要几十毫秒,实时根本扛不住。硬件编码的接口思路和V4L2很像,也是初始化、塞帧、取包。但硬件编码器有两个通用的大坑:第一,很多编码器默认输出是非阻塞的,取包在队列空时会立刻返回,如果当成阻塞等一帧来处理就会丢包、队列塞满、卡死,必须在初始化时把超时设成阻塞;第二,硬件编码器输出的码流往往不带重启标记或分段信息,严格的解码器会显示块状花屏,得显式开启分段来插入重启标记。这类能跑但画面花的坑,是硬件编码调试的日常。

把EIS、LUT、硬件编码这三样放在一起看,会发现它们分别回答了应用层图像处理的三个问题:画面稳不稳,防抖,好不好看,风格,能不能传,编码。而这三样在工程上还有一个共同点:它们都极其吃硬件协同。EIS要陀螺仪的数据和ISP的帧严格对齐,差一帧防抖就失效甚至反抖;LUT要靠GPU或专用硬件做查表插值,纯CPU算三线性插值也扛不住实时;编码更是必须走VPU,CPU软编根本来不及。换句话说,应用层的图像处理,不是纯粹的算法,而是算法加硬件加时序的综合工程,任何一环没对上,效果就出不来。这也是为什么同一个算法,在demo里跑得漂亮,落到真机上就翻车,demo不关心硬件和时序,真机上每一处都要抠。

计算摄影与浅景深

讲到这里,该聊聊计算摄影这个最性感的部分了。它的定义很宽,凡是用算力弥补光学和物理的不足,都算计算摄影,多帧夜景、HDR、超分、浅景深模拟,都是。

先回到前面的弥散圆和景深。浅景深,背景虚化,是专业相机拍人像的招牌效果,它靠的是大光圈、长焦距、近物距,这三者都会让景深变浅、弥散圆变大、背景糊成一片。但手机、还有我们这种桌面摄像头,镜头是定焦的、光圈是固定的、焦距很短,物理上注定是大景深,什么都是清晰的,没有虚化。那么问题来了:定焦小光圈镜头,怎么拍出浅景深的效果?

三步算出浅景深

答案就是计算摄影,用三步算出来。第一步是深度估计:要知道画面里每个像素距离相机多远。传统做法可以用双摄像头视差,左右两个摄像头看同一点的角度差,反推距离,但现在更主流的是单目深度网络,一个CNN从单张图直接估计出稠密的深度图,网络学过了海量的图加真实深度配对,就能猜出哪里近、哪里远。第二步是语义分割:把人,或主体,从背景里抠出来。人像分割网络输出一个主体掩码,告诉我们哪些像素是人、哪些是背景。第三步是弥散圆施加:有了深度图和主体掩码,就可以模拟光圈了,对焦在主体上,背景距离越远、弥散圆就越大、模糊就越强。于是对背景按深度做不同程度的模糊,越远越糊,对主体保持清晰,一张假的浅景深照片就诞生了。这三步,深度计算、语义分割、弥散圆施加,就是定焦镜头实现浅景深的完整思想,现在的手机人像模式全是这么干的。模糊施加本身,就是用不同大小的卷积核,对应不同大小的弥散圆,去卷积背景,越远核越大,和前面讲的卷积是同一件事。

定焦镜头如何算出浅景深:背景点成像在传感器前,散成弥散圆

多帧融合与 HDR

除了浅景深,计算摄影的另一大支柱是多帧融合。夜景模式连拍多张短曝光,做多帧对齐、融合,把信噪比堆上去;HDR是多张不同曝光合成,把高光和暗部都拉回来。这个过程里AI干两件事:一是配准,手持抖动的几帧怎么对齐,传统靠光流,现在可以交给网络;二是融合,哪一帧的哪个区域可信就多取一点。有意思的是,前面讲的时间域IIR降噪,其实已经摸到了多帧融合的门槛,它就是在时间维度把多帧信息揉进一帧,只不过它是逐像素、无对齐、显式的;真正的计算摄影是有运动补偿、多帧、很多时候AI做的对齐和融合。从IIR到计算摄影,差的就是对齐这两个字,一旦知道每帧之间像素怎么对应,噪声就能压得更狠而不糊细节。此外还有超分辨率,把低分辨率图放大并补出细节,网络从海量高低分辨率配对里学到怎么补,这些技术合在一起,构成了算力重塑摄影的完整图景。

其中HDR的多帧加权融合,是最经典、也最能说明动态范围从哪来的例子。单帧曝光能覆盖的亮度范围有限:短曝光保住了高光、暗部却死黑;长曝光保住了暗部、高光又过曝。于是连拍几张不同曝光的图,每张只在它不欠不曝的那一段亮度里可信,最后按可信度加权合成一张动态范围更大的图。这个可信度就是一个权重函数$w(Z)$,中间调的像素码值最可信、权重最高,接近0,欠曝,和255,过曝,的像素已经饱和、信息不可逆丢失,权重趋近于0。

数学上,经典的做法是Debevec–Malik那一套:先用多帧曝光反推出传感器的响应曲线f,再把每张图的码值反算回真实辐照度,最后按权重加权平均:

其中$Z_i$是第i张曝光的像素码值,$t_i$是它的曝光时间,$f^{-1}$是响应曲线的反函数,把码值映射回线性辐照度,$w(Z_i)$就是那张中间调权重高、两端权重低的权重函数,分母做归一化。这个式子一眼看过去,本质就是哪张可信多取哪张,不可信的自动淡出,和前面时间域IIR的混合系数a是同一个思想,只不过IIR按帧间差异定权重,HDR按码值是否饱和定权重。

HDR 多帧曝光加权融合

这套加权融合,本质是用算力换动态范围,把几张各管一段的曝光,拼成一张同时保住高光和暗部的图。理解了HDR,再回头看Log曲线就通了:Log是单帧内压缩动态范围,HDR是多帧间扩展动态范围,一个往里压、一个往外扩,目标都是让更多亮度层次能被记录下来。

美颜算法

计算摄影是算出物理做不到的东西,美颜则是算出审美上想要的东西。它是相机算法里最贴近用户、也最有商业价值的一块,技术含量一点不低。美颜主要拆成三件事:白皮,美白,磨皮,加深细节。

白皮美白

白皮解决的是肤色的观感。第一步是定位皮肤区域。最朴素的思路是肤色阈值,把图转到YCbCr或HSV空间,肤色的CbCr或HS分量落在一个很窄的范围里,用这个范围就能把皮肤抠出来。这个办法快,但太脆:光照一变、人种一变,肤色范围就漂,不是把背景误判成皮肤,就是漏掉大片皮肤。工程里真正好使的是用人脸关键点:拿一个训练好的关键点模型,比如MediaPipe的Face Landmarker,一张脸478个点,把这些点连成凸包,就圈出了脸的轮廓;再从里面抠掉眼睛、眉毛、嘴唇这几个不该动的洞,最后用高斯模糊把边缘羽化一下,得到一张只覆盖皮肤、边缘柔和的掩码。这张掩码是后面一切操作的地基,有了它,美白和磨皮才只动皮肤,不动五官和背景。

抠出皮肤后做两件事:一是提亮,把皮肤的亮度V抬一点;二是调色,把肤色往白里透红的方向偏、去掉偏黄偏暗的成分。关键是把力度拿捏住,提亮太多就假、像贴了张面膜,去黄太狠就发灰发青,所以实际参数都很克制。

磨皮

磨皮解决的是皮肤纹理。皮肤上有毛孔、细纹、痘印、斑点,这些都是皮肤上的高频细节,磨皮就是把这些抹掉,但千万不能把眼睛、嘴唇、眉毛这些五官边缘一起抹掉。所以我直接把白皮那步算出来的皮肤掩码拿过来复用,所有磨皮操作都只落在掩码里,掩码之外一个像素都不动。整套思路就三件事:保边滤波、高低频分离、掩码引导。

先说保边滤波,主力是双边滤波。前面讲降噪时提过,它平滑时同时看两个权重:空间距离近的像素权重高,亮度接近的像素权重也高。写成公式:

其中 $W_p$ 是归一化项,$G_{\sigma_s}$ 是空间高斯核,$G_{\sigma_r}$ 是亮度高斯核。皮肤内部亮度起伏很小,$G_{\sigma_r}$ 接近 1,周围像素都参与平均,纹理就被抹平了;而五官边缘两侧亮度差一大,$G_{\sigma_r}$ 立刻跌到接近 0,这些像素不参与平均,边缘就保住了,这就是平滑时绕着边缘走。$\sigma_s$ 和 $\sigma_r$ 是仅有的两个旋钮,$\sigma_s$ 管平滑半径,$\sigma_r$ 管多大亮度差算边缘,磨皮磨得狠不狠、假不假,基本就是这两个值在打架。

再往上一步是高低频分离。做法很直接:用一次高斯模糊把原图糊掉,得到的就是低频层,只剩大面积的肤色和光影;用原图减去低频层,剩下的就是高频层,里面全是纹理和细节。然后分头处理,低频层再轻微平滑一次,把肤色不均匀的地方抹匀;高频层里属于皮肤瑕疵的部分减弱,属于五官细节的部分保留甚至增强。最后两层加回去。它比单纯双边滤波更可控,因为把皮和细节拆成了两个通道,想动哪个就动哪个。

说白了,磨皮就是一种语义引导的选择性降噪。降噪是全局的,看到高频就压;磨皮先知道哪块是皮肤,再只对皮肤压高频,而保边滤波和掩码保证这个动作永远落在皮肤上、绕着五官走。这就是为什么好的磨皮皮肤像剥了壳的鸡蛋,但眼睛还是炯炯有神。

下面这张是这一整套关键点定位皮肤、双边滤波磨皮、提亮美白流程跑出来的真实效果,左边原图、右边美颜后:

美颜前后对比:关键点定位皮肤 → 磨皮 → 美白

加深细节与几何美颜

加深细节则反过来,是在磨皮之后把该锐利的地方再提起来。磨皮难免会损失一点细节,所以要用锐化补回来,但不是全图锐化,那样噪点和瑕疵又回来了,而是局部锐化:只对眼睛、眉毛、嘴唇这些关键部位做锐化,甚至用局部对比度增强,英文Clarity,把五官的立体感拉出来。所以一套完整的美颜,本质是肤色检测加保边滤波加局部锐化的组合拳,每一步都在选择性上做文章,只动该动的,不动不该动的。这个选择性,和计算摄影里的语义分割是同一个思想:都是先理解画面,再局部处理。顺着这个思路,还能延伸出更多几何美颜,大眼、瘦脸、磨下巴,本质是对人脸关键点做局部的几何形变,把五官往标准比例上拉,数学上就是一个基于关键点约束的网格变形,英文Image Warping。这些功能加在一起,就是美颜相机的全部家底。

端到端影像算法

把前面所有环节串起来,就到了这条链路的终点,端到端影像算法。它的野心是:不要传统ISP的一步一步,也不要AI替换个别环节的渐进路线,而是RAW进去、一张最终的好图出来,中间一个网络全包了。

把整条链路内化进网络

这个方向的美妙之处在于,它能把前面讲的很多东西内化到网络里。传统ISP里,去马赛克、白平衡、CCM、伽马、降噪、锐化是分开的、各管各的,每一步都有自己的人工调参和标定;端到端网络则让这些步骤在一个可微分的图里联合优化,网络自己学会什么顺序、什么力度是最优的。前面提过的DeepISP是早期的尝试,它证明了端到端可行;Unprocessing解决了数据问题;再往后,PyNet、CycleISP、PMRID这些工作把端到端ISP一步步推向实用。端到端的另一个好处是能学到全局最优,传统ISP每步各自最优,拼起来不一定整体最优,而端到端网络直接优化最终画质,理论上能逼近这条链路的理论上限。

传统 ISP 分步调优 vs 端到端一个网络

端到端的代价

但端到端不是没有代价。最大的问题是可解释性和可控性,传统ISP的每一步都物理意义明确,出问题知道该调哪;端到端网络是黑盒,画面偏色了、过曝了,你不知道该改什么。其次是泛化性,网络在某个传感器、某种光线下训练得好,换个传感器、换个场景可能就崩,而传统ISP的标定流程是成熟可迁移的。所以现实的落地路径,绝大多数是混合架构:传统ISP做兜底,保证最差情况也出一张能看的图;AI在特定环节,去马赛克、降噪、超分,发力,把画质的上限拉高。这也回到了这篇贯穿始终的一句话,影像的尽头不是光学,也不是算力,而是工程,是在有限的算力和功耗里,把每一环都抠到极致的那种执念。

端侧推理的难处

量化与压缩

聊了这么多AI,最后不能不聊一个现实问题:这些AI跑在哪?相机里的AI和云端不一样,云端可以上大模型慢慢跑,相机里却要实时、要省电。所以端侧推理要做的第一件事就是量化,把浮点网络压缩成定点,甚至上专用的NPU跑。量化的核心是把FP32的权重和激活映射到INT8,常见的有对称量化和非对称量化两种,映射公式就是一个缩放因子和零点偏移。量化会带来精度损失,我们就得在精度和速度之间反复横跳,找到那个能落地的最小网络。除了量化,还有剪枝,砍掉不重要的连接,知识蒸馏,用大模型教小模型,这些压缩手段,目标都一样:把模型塞进几MB的NPU里还能实时跑。

工程细节

端侧还有一堆书里不会写的细节。比如输入分辨率,NPU算力有限,1080p的图直接送进去跑不动,往往要先下采样再推理、输出再上采样回去。比如零拷贝,把输入张量直接绑到DMA缓冲区上,让NPU原地读,省掉一次内存拷贝;但零拷贝有时会静默失败:对特别大的模型,NPU的地址空间被权重占满,输入张量绑定不上去,模型会继续读它默认的全零缓冲区,出来的结果全是错的,这种时候只能回退到拷贝路径。再比如内存布局,网络要NHWC、驱动给你NCHW,转一次就是一笔开销;还有算子支持,某些网络层NPU不支持,得在CPU上跑,来回搬运数据,这些琐碎的东西才是跑通demo和真能落地之间的分水岭。

说白了,相机里的AI从来不是越大越好,而是够用就好。一个能实时跑的小网络,只要能把夜景的噪点压下去、把肤色还原准,那就比一个跑不动的100MB大模型强得多。端侧的本质,就是在效果和实时之间找平衡,而找到这个平衡,靠的是对上面每一环,从ISP到V4L2到编码到NPU,的深刻理解。这也是为什么我一直觉得,做端侧AI的人,必须先把传统图像处理吃透,否则你都不知道自己优化的那5毫秒,是在跟哪一环抢时间。

总结

写到这里,这篇已经很长了,该收尾了。我把整条链路从头到尾走了一遍:从曝光三要素和弥散圆这些摄影基础,到传统ISP的RAW域和RGB/YUV域每一道工序,到AE/AWB/AF三个自动化的地基,到V4L2框架和QBUF/DQBUF的轮转,到卷积与频域、降噪的演进、AI ISP的先进算法,再到电子防抖、风格滤镜、硬件编码、计算摄影的浅景深、美颜算法、端到端影像,最后落到端侧推理的现实。

走完这一圈,我最想留下的一句话是:相机的技术栈是一个层层叠加的体系,每一层都有自己的原理、思想和算法,而AI不是来推翻这个体系的,它是来补位的,在传统方法够不着的地方,把画质的上限再往上顶一顶。传统ISP负责正确,AI负责更好,工程负责能实时跑起来。三件事,一件都不能少。

回想我写这篇文章的初衷,是想以点带面,从一个具体项目的几个坑出发,把整张相机的知识地图铺开。现在地图铺开了,我发现它比我一开始以为的要大得多:光是一张照片这四个字,背后就站着光学、信号处理、控制系统、操作系统、神经网络、硬件加速这一整条学科链。这也是影像行业最迷人的地方,它没有一个环节是多余的,每一个环节都有人在把它往极致里抠。

所以做相机,最难的不是上AI,而是先把传统ISP、V4L2、编码、同步这些基本功打牢,再让AI在正确的环节、以正确的代价进来。影像的尽头不是光学,也不是算力,而是工程,是你在有限的算力和功耗里,把每一环都抠到极致的那种执念。希望这一篇能给你一张完整的地图,下次再听到计算摄影、AI降噪这些词的时候,你脑子里能有它们的确切位置,而不是一团模糊的概念。


关于相机的AI与计算摄影
https://blog.minloha.cn/posts/222833787e35da2026082849.html
作者
Minloha
发布于
2026年8月28日
更新于
2026年8月29日
许可协议