【转载请注明来源和作者】
虽然你可能拥有不止一个相机,而且现在用手机也能拍出精彩的照片,但你肯定也曾困惑过,为什么数码相机(单反),包括手机,可以拍出精彩的照片,它们跟传统的照相机到底区别在哪里?其实我自己也曾很困惑。我依稀记得我大学期间使用的相机都还是胶卷式的,怎么突然满大街都是数码相机和手机,人们甚至已经习惯了用手机来拍照,连数码相机都要被淘汰掉了似的。科技实在是进步得太快了。
现在让我们停下脚步,仔细的来探究一下,包括手机在内的数码摄影设备是如何将入射光转换为最终的JPEG格式的图片的。我会回答两个问题:
下图正是照相机将入射光转换为“常规”图像的完整操作序列。
我们今天会谈到的内容有传感器(Sensor),模拟前端(Analog front-end),颜色滤镜(Color Filter),相机内图像处理(红框内黄色部分)这几个主题。
让我们先看看现代数码相机的工作流程示意图。可以看到,从物体上传来的入射光通过相机的光学器件(蓝框部分)后会穿透颜色滤镜到达传感器,并通过模拟前端转化为数字信号(绿框部分),最后通过相机内的图像处理系统转换为最终的RGB格式图像,并存储为常见的JPG文件。
这一节我们先忽略光学部分,直接学习绿框部分的传感器、模拟前端、颜色滤镜,看看它们是如何将接收到的光线转换为RAW图像数据的。
正如下图所示,当相机的快门打开时入射光会穿过快门(通过镜头)到达传感器。此时到底会发生什么事?
快门关闭时
快门打开时
正如让爱因斯坦在1921年获得诺贝尔奖的发现“光电效应”所揭示的,入射光子进入传感器后会转换为电子。因此,基本的传感器的设计如下图所示,其目的还是使得微透镜所汇聚的光子能被光电二极管转换为电子并存储在势阱中。
光电效应
基本传感器设计
衡量一个传感器的性能的基本指标有:
量子效率 是指转换的电子数量与入射的光子数量的比值
量子效率(QE)
当不断改变入射光的强度时,转换的电子数量也会发生改变,这构成了上述所说的光电二极管的响应函数。通常来讲这是一个线性函数,如下图所示。 但当势阱饱和(过曝)或者光线过暗(噪声淹没了信号)时,它将不再是线性的。这个特性与后面之后会讲到的HDR图像的算法高度相关。
光电二极管的响应函数
势阱的最大容量称为满阱容量,下图显示了常见相机的传感器的满阱容量,由于硅中光子的有限和固定的吸收长度,满阱基本上是像素面积(而不是体积)的函数。
满井容量
根据读取电路的设计的不同,有两种不不同的传感器类型:CCD和CMOS。它们的区别可以用下表简要的概括。以前高端设备会采用CCD,而中低端、消费级产品才会采用CMOS。而现在的CMOS传感器已经和CCD传感器有相当的性能了,大多数消费级和工业摄像机已经采用了CMOS传感器。
CCD和CMOS的比较
仔细看看CCD和CMOS的结构图如下:
CCD
CMOS
模拟前端
当相机镜头关闭时,模拟前端会从传感器的势阱中读出电子,并转换为模拟信号。这些信号首先被Analog Amplifier(也称为Gain)所放大。大家在相机设置中的ISO通常是会映射为对Gain的放大倍率的设置,而这个模块也跟后续会提到的相机的Vignetting(渐晕)高度相关。
放大后的模拟信号接下来由Analog-to-Digital Converter(ADC)转换为通常是10bits-16bits的数字信号,常见的为12bits。
Look-Up Table (LUT)用于在一定的范围内修正传感器响应的非线性,这个模块同时还能够修复一些损坏的像素的输出。
我们上面提到了一种现象叫做Vignetting,它实际上是指生成的图像四周比中间暗,如下图所示:
Vignetting
Vignetting的产生有多种原因,例如:
有了LUT,可以产生非线性的Gain从而纠正Vignetting现象
纠正Vignetting
通过模拟前端生成的就是我们所说的RAW格式图像,后续的一系列处理都是基于RAW格式图像进行的。当然,不同的相机生产商会以不同的格式来存储RAW格式图像,大家可以查询到很多资料,推荐维基百科上的这一篇,此处不再赘述。
有没有记得前面曾经提到的颜色滤镜?这是起什么作用呢?
基本传感器示意图
在进一步讲解之前,让我们先来了解一下颜色的基础知识。
我们知道光是一种电磁波,而颜色并不是光的客观属性——光的客观属性是它的波长。下图展示了几乎完整的电磁波谱,而我们人眼所能看到的只是其中400nm到700nm的一小段,而颜色则是我们对这一小段电磁波的一种主观的感觉而已。
电磁波谱
这种主观的感觉既跟入射光的功率谱分布(SPD)相关,也跟人眼对不同光源的光谱敏感度相关,我们分别来探讨下这两个概念。
通常的光源都由多个波长的光组成,而每一种波长的光的功率一般都不一样。如果画出每种波长的功率和它的波长之间的关系,我们可以得到光源的功率谱分布(SPD)。例如下图展示了几种光源的SPD
功率谱分布(SPD)
不管是数字的还是非数字的传感器,它们对不同波长的入射光线会有不同的敏感度,可以用传感器的谱敏感度函数(SSF)来衡量。传感器对入射光的响应是一个累加了所有光波响应的单一的值,我们可以用一个积分表达式来描述:
传感器响应是入射光SPD与传感器本身的光谱敏感度函数乘积的积分
那么人眼呢?实际上人眼是由包含对不同光波敏感的三种视锥细胞,最终的感觉是由这三种细胞的响应共同构成的,如下公式所示。
三种细胞的响应函数
现在我们回到相机的传感器就明白了,为了能在最终的相片中加入颜色信息,人们用颜色滤镜来模拟了不同的视锥细胞。当这些颜色滤镜以预先设定好的形式排列时,就构成了颜色滤光阵列(Color Filter Array)。
这里面牵涉两个问题,第一是如何设计滤光镜对不同光线的敏感度,第二是如何设计不同的颜色滤光镜的最佳空间排列(也成为Mosaic)。
下图是Canon 40D和50D的谱敏感函数图比较。每个相机厂商,甚至是同一厂商的不同型号的相机的传感器的SSF都可能不同
Canon 40D 和 Canon 50D 的SSF不同
下图是一些Mosaic设计,其中我们最常用最基础的是Bayer Mosaic。
因此,当光线通过颜色滤光镜到达传感器,由模拟前端最终转换为数字RAW图像时,图像会变成什么样呢?可以看到RAW图像并未显示出颜色,反而显示出马赛克一样的方块,并且还有大量的噪声。所以,接下来很重要的就是通过相机内的图像处理系统对图像进行一系列处理,来使之变成最终美观的RGB图像。
RAW图像上的噪声和马赛克效应
二. 相机如何将RAW数据转换为最终我们看到的RGB图像?
相机内基本处理流程
前面讲过,颜色是我们对光的一种主观感受,它直接与我们人眼的SSF以及入射光的SPD相关,那么除此之外,是否跟别的因素相关呢?的确如此,从下图可以看到我们人眼对不同环境光线下拍摄的物体的颜色具有自纠正的作用。
但相机不具备这样的功能,因此如果不经过颜色的校正,拍出来的图片的颜色就会很失真。这就是白平衡的作用:它使得我们人眼感知为白色的物体在最终的成像中也为白色。
现在大家用普通的相机一般都会内置一些白平衡选项,可以根据自己的喜好和环境的光线选择合适的白平衡选项进行颜色的矫正:
相机上预设的白平衡设置
实际上,自动白平衡是一个很热门的研究领域,这里我们介绍两种基本的白平衡算法。正如前面所讲,白平衡是要使得我们人眼感知到的白色最后成像也是白色,那么首先就要确定图像中哪些是白色。这里有两种假设
它假设图像的平均颜色是白色,其基本的算法可以用如下公式表示
它假设图像中最亮的区域是白色,公式如下:
我们会在之后用实际代码来验证这两者的不同。但如果大家观察上述公式会发现,白平衡算法的前提是要能够获取不同通道的数据,但我们前面已经讲过,RAW格式图像实际上是不带颜色的数据。那么从RAW格式图像中分离三个通道的数据,就是所谓的Demosaicing的过程。
在去马赛克之前,每个像素只有一个单一的颜色,而我们是想恢复完整的颜色,如何做到呢?
基本上这是通过“插值”来完成的。 常见的插值方法有:
这里我们介绍只需要像素的四个领域即可完成的Bilinear插值,简单讲只需将同一颜色的四个领域取平均值即可:
而对于不同的颜色通道则独立的重复这一过程
如下图所示,未经去噪处理前的图像通常会包含很多噪声,尤其是在低光环境下。
噪声的来源是多样的,例如:
图像上的噪声
随机性导致,场景越量,这种随机分布的方差越小,越不容易产生噪声。对于比较明亮的场景以及较大像素尺寸的传感器,散粒噪声是最主要的噪声来源。
那么如何去噪呢?我们这里谈论的是相机内的去噪算法,由于大部分相机本身的运算能力不高,这也意味着无法选择很复杂的不利于硬件化的算法。这里简单用下面这页图来展示均值滤波和中值滤波,以后还会给大家介绍更多的去噪算法。
现在我们来谈一个很重要的问题:色调重建,也叫做Gamma校正。
我们已经知道,传感器对输入图像的响应大部分是线性的,而且我们人眼对输入光的响应也是线性的。然而,人的感觉却是非线性的,即人对暗光会更加敏感,而这种感觉上的敏感度很接近Gamma函数。与此同时,我们的传统CRT显示设备相对输入图像通常也是非线性的,其对输入的敏感性和人眼的特性恰好相反。这两种效应的共同作用,会使得我们大脑感知到的图像显得很暗。
人眼的响应特性
相机的原始响应是线性的,但是人眼和显示器却是非线性的
我们解决此问题的办法,是在相机内部对图像做一次Gamma校正,用于抵消显示器的显示效应。如果原图的线性响应值是L,那么新的图像会是
,
一般取2.2.
gamma校正一般在哪个阶段进行呢?可不可以在拍摄的过程中不进行gamma校正,只是保存图像为jpeg形式,在下一次显示之前才做呢? 通常来说不宜这样,因为当我们把图像保存为jpeg形式是会进行位空间压缩,这会导致信息损失。所以最好是在压缩前就做好gamma校正。大家注意回顾gamma校正的位置:
到此为止,我相信你已经对我阐述过的模块有了基本的理解。我特意忽略掉了色彩转换这一部分,因为关于颜色我会用专门的文章来做深入的探讨。
此时让我们来尝试仿真从入射光到最终的jpg图像的全过程, 我会把实例仿真分为两个部分:
当我们谈到获取RAW图像时,先回答一个问题:为什么我们需要RAW图像?我们平时用相机拍摄并存储的JPEG图像文件不够好吗?
事实上,JPEG是图像压缩后的存储格式,解压后是RGB图像,它本身正如上面所讲是非线性的,这使得很多计算摄影相关的算法直接作用到RGB图像上都会产生错误的结果,例如photometric stereo, shape from shading, image-based relighting, illumination estimation, 包括与光传输和反向渲染有关的任何算法。这时候,最佳的解决方案就是采用线性的RAW图像来替代。
那么如何获取到RAW图像呢?很简单,大部分单反在拍摄时都可以选择保存RAW图像文件。当然每个相机厂商都有自己不同的存储RAW图像的格式,例如Canon的RAW文件格式是CR2,是一种遵循TIFF规范的14bit的RAW文件。这里可以查到更多的信息。
假如你使用手机拍摄呢?你还可以使用lightroom这一款应用,不过注意并不是每一款手机都支持。你可以在这里查到更多的信息。
RAW格式文件是否可以直接用Matlab、Python或别的开发工具打开?事实上并不能直接打开。虽然有很多方法可以解决此问题,但这里推荐的一种方法是利用dcraw这个小软件来将RAW格式文件转换为TIFF文件,而后者时可以直接被很多图像处理软件打开的。dcraw的官网在这里:http://www.cybercom.net/~dcoffin/dcraw/,它由很多可选的参数。
为了3.3节仿真相机内的处理流程,我用下面的命令将一个CR2格式的RAW文件转换为对应的TIFF文件,并确保后者未经过相机内的任何处理,只包含原始信息。
dcraw -4 -D -T <RAW_filename>
dcraw非常强大,可以模拟相机内的的大部分标准流程。例如-a选项就可以模拟用全图信息做灰度世界的白平衡,-q可以用于控制demosaicing的插值质量等等。看官可以自行探索。
例如,我可以用dcraw -4 -D -T banana_slug.cr2轻松的将附件RAW文件转换为了banana_slug.tiff文件,后续就可以用任意一种开发语言来处理它。
有一些书籍也专门谈到了如何处理RAW格式图片,知乎上还有专门的LIVE讲座谈起这个主题:
从入射光到最终的相片,相机拍照的过程是非常复杂的,我们今天的内容对这个过程的大部分基本模块进行了介绍。但是需要注意的是,每个相机厂商都会设计自己私有的、非常复杂的In Camera Image Process Pipeline,很多时候通过最终的成像是完全无法知道其内部到底有哪些私有操作、以及这些操作的顺序的。
如下是这个帖子的核心内容总结,希望本文对你所有帮助,谢谢。
我在如下的Jupyter Notebook中展示了本帖中的相关操作,你可以对着它获取更深入的理解,也能够进一步掌握用Python来进行图像处理的一些技巧。
跟这一系列专题文章相关的Notebook可以从下面的仓库获取
https://github.com/yourwanghao/CMUComputationalPhotography.git
这一篇文章的绝大部分素材来自于
[1] CMU 2017 Fall Computational Photography Course 15-463, Lecture 2
如果不做特别说明,素材均来自于[1]
我也会参考下面的重要资料中的内容
[2] Richard Szeliski, Computer Vision : Algorithms and Applications,
[3] Michael Brown, “Understanding the In-Camera Image Processing Pipeline for Computer Vision,” CVPR 2016
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。