【转载】利用 Matlab 和 Dcraw 处理数码相机 Raw 文件的完整流程(2)

分类: matlab |
下面的图片截图如果不特殊说明都是指在 Matlab 中预览的效果。
得到的这幅 tiff 图像除了一些缩略图和文件头之外,基本上记录了与 Raw Data 同样多的图像信息,并且是 Matlab 可读取的。由于编码上的差异,并且 Dcraw 不像大多数软件那样去除了图像边缘的一些像素,有时这个 tiff 文件的体积甚至会比 Raw Data 文件更大。
与 Camera Raw、LightRoom 等软件打开的 Raw 文件最明显的区别就是,这张 tiff
图片是黑白的。这里牵涉到了去马赛克(Demosaic,但我更喜欢叫它彩色插值)的问题,下面我简单地谈谈我的理解,不一定完全正确。详细的介绍还是看
大家都知道一般民用的数码相机只有一块 CMOS 或 CCD(这里不谈
既然传感器只能感受光的“强度”而非“色彩”,我们就需要在传感器之前放置一些特定波长的滤光片,使得经过这些滤光片后作用在传感器上的光信号只是单一波长的乘积形式(比如550nm),而非整个可见光波段(380nm ~ 780nm)的积分形式。实现这个功能最常见的滤光片就是拜耳滤镜,如下图所示。
http://capbone-img.qiniudn.com/raw_process_5.pngMatlab
灰色部分为 CMOS,彩色部分为对应颜色的滤镜,每个滤镜下方对应的像素点只能接收到该滤镜对应波长的光信号,而不是整个可见光谱范围的光信号。根据左上角四个滤镜从左至右、从上至下的顺序一般有“RGGB”、“GBRG”、“GRBG”几种。D3x 为“RGGB”型,具体相机的滤镜排列可以对着红绿蓝单色图片分别拍摄一张然后查看 Raw Data 的数值分布来获得。知道自己相机所用的拜耳滤镜的排列模式(Pattern)是进行彩色插值操作的前提(之所以绿色滤波片的数量是红蓝滤波片数量的两倍,主要是因为人眼对绿光最为敏感,这点不作展开说明)。既然知道了每个颜色滤波片背后 CMOS 对于像素单元上的光强度,以及各个像素之上的滤波片颜色,我们就可以对每个像素的三原色进行恢复,这就是去马赛克(Demosaic)或者说色彩插值的本质。举个例子,假设某个 CMOS 阵列上的滤波片为“RGGB”排列(参考上图),现已知某个像素点 x 对于为 R 滤波片,则其上、下、左、右四个像素点必定对于 G 滤波片,右上、左上、右下、左下四个像素点必定对于 B 滤波片,因此这时候像素点 x 对应的 R 通道数值就是该点 CMOS 上实际的电流大小;而 G 通道数值是对上、下、左、右四个像素 CMOS 电流大小取平均之后的值;同理,B 通道是对右上、左上、右下、左下四个像素取平均之后的值。当然这里说的只是最简单的插值方法 -- 领域取平均法,实际上各个厂商都需要考虑各方面因素对色彩插值进行算法上的优化。
一般我们看到的 JPEG 图像或者彩色的所谓的 Raw Data,都必定经过这一步色彩插值。但是我们现在希望把这一步骤留到 Matlab 中进行,所以在 Dcraw 中选用 -D 参数使得插值先不被执行,这也是为什么上面得到的 tiff 图像仅仅是灰度图像 -- 因为它只记录了光强度信息,而不包含任何颜色信息。
这时可以在 Matlab 中打开这幅灰度图像了。由于各个像素上记录的光强度是一个标量,这幅图像相当于一个 m × n 的矩阵,其中 m 和 n 分别为 CMOS 纵向和横向的像素数。
现在终于可以开始在 Matlab 中对相机传感器的原始数据进行处理了。
整个处理过程大概遵循以下步骤:
http://capbone-img.qiniudn.com/raw_process_1.pngMatlab
如果不是要对图像进行处理,而仅仅是希望获得拍照时场景照度的相关数据,只需要进行到第三部 Demosaicing
即可。下面的步骤仅仅是在 Matlab 中模拟一张相片从被 CMOS
记录到最终呈现在屏幕上的整个过程,相当于人为地重新干了一遍数码相机中图像处理芯片干的事情。若是出于研究的需要,可以对任意一步修改或增加操作。例如需要研究
Gamma 曲线,就不应该在 Matlab 中执行我提供的 Gamma 校正(
1. 线性处理(Linearization)
出于节省数据存储空间的目的,一些厂商(例如尼康和索尼)的 Raw Data
并不完全与像素点上的照度呈线性关系,而是会在编码上做一些处理,比如非线性压缩等。不过这里我们不需要担心这个问题,因为之前在 Dcraw
中使用 -4 参数时就已经解决了这个问题。我们只要确保各个像素的数值是分布在 14-bit(虽然 Dcraw 中的 -4
参数将图像设为16位,但其最大值仍然为
要说明的是,我这里使用的 black = 0 以及 saturation = 16383 仅仅是针对 D3x
而言,不同厂家的相机,或者同一厂家不同型号的相机都可能不同。如果第一次使用某台相机不知道这两个参数,可以使用
http://capbone-img.qiniudn.com/raw_process_6.pngMatlab
线性处理到这里就完成了,在 Matlab 中用
http://capbone-img.qiniudn.com/raw_process_8.pngMatlab
2. 白平衡校正(White Balancing)
其实将这一步叫作白平衡校正也并不是很恰当,因为这并不是指利用各种白平衡算法对图片的色调进行修复的那个白平衡校正,而仅仅是对 RGB 三通道乘上不同的增益系数,以补偿因为三种滤波片具有不同光谱灵敏度带来的影响。如果不考虑图像亮度(亮度的处理我们放在后面),将 R 通道乘以2并保持 G 通道不变,或者将 G 通道乘以0.5并保持 R 通道不变,这两种方式对画面颜色变化的影响是等效的。因此我们通常将 G 通道的增益系数固定为1,仅仅考虑 R 和 B 的系数。关于这两个系数具体数值应该取多少,则取决于相机的型号以及拍摄时使用的白平衡参数。实际上,在相机的白平衡设置里选择不同场景,就是在调整这两个增益系数。如果想还原为拍摄时使用的白平衡设置,可以在 Dcraw 中使用 -w -v 参数,这时屏幕上会显示出当时所使用的 R、B 通道的增益系数。
http://capbone-img.qiniudn.com/raw_process_9.pngMatlab
上图中的2.433594和1.347656分别表示拍摄这张图像时所使用的 R 通道和 B 通道的增益。要注意的是,一旦使用了 -w 参数,Dcraw 就会自动完成彩色插值的工作,这样得到的 tiff 图像就不再是原始灰度图像了。因此我们仅仅是使用 -w 来查看增益系数。如果不希望使用拍摄时的白平衡设置,则可以使用 -W 参数,这样不管当时用的是哪种白平衡档位,其 R、B 增益都是一个固定的值。例如对于这台 D3x 来说固定的 R、B 增益分别为2.625910和1.263930。在实际的图像处理应用中,通常需要固定相机的白平衡参数,即在相机的白平衡设置中手动输入色温。对于使用相同相机白平衡设置(Auto 除外)拍出的图片,它们都具有相同的增益系数。可以通过 -g 参数手动设置三通道的增益系数,例如 -g 1 1 1 1。
得到了 R、B 通道的增益后,我们需要将相应的像素值乘上这个系数。前面说过,不同相机具有不同的拜耳滤镜排列方式,因此需要根据实际情况进行增益系数的乘法。这里我使用的是相机拍摄时的白平衡参数,即 r_multiplier = 2.433594 和 b_multiplier = 1.347656。
上面代码中的
完成白平衡调整后的图像如下。由于 R 和 B 通道都乘以了大于1的数,图像的平均亮度较上一张略有提高了。
http://capbone-img.qiniudn.com/raw_process_10.pngMatlab
3. 色彩插值(又称去马赛克,Demosaicing)
上文提到的插值步骤在这一步中实现,经过色彩插值之后原来的灰度图像就成为了一幅三通道的彩色图像。空间插值有非常多的方法,这里为了方便我们使用
Matlab 内置的
完成这一步之后我们就得到了最原始的彩色信息。一些应用中所需要的就是这幅图像的数据,可以使用
http://capbone-img.qiniudn.com/raw_process_11.pngMatlab