AWB简介
AWB是Automatic white balance的英文缩写,即自动白平衡。
要了解AWB我们首先需要了解一下色温,色温是表示光线中包含颜色成分的一个计量单位,偏理论的部分比较枯燥,也不是本文的主要内容,这里就不展开介绍了,感兴趣的同学可以自行百度。通俗一点的来说,它可以用来反应一个光源的色调,当一个光源发出的光色温较低时(比如白炽灯),色调偏暖,颜色上就是偏红、偏黄。当一个光源发出的光色温较高时(比如节能灯),色调偏冷,颜色上就是偏白、偏蓝。
人眼拥有强大的色彩纠错能力,不管色温怎么变,人眼几乎都能分辨出物体原本的颜色,即自动白平衡。比如说,同一张白纸,不论是放在商场的暖黄灯光下,还是放在室外晴天的阴影下,人眼都知道它是一张白纸。而CMOS传感器没有这种能力,为了真实地反应人眼看到的颜色,就需要进行白平衡校正,即AWB。
AWB算法
灰度世界算法
如果一张图像的颜色是丰富多彩的,那这幅场景的平均反射就能够抵消色差。这便是灰度世界(gray-world)的假设。灰色世界法历史悠久、效果行之有效,并且至今仍然流行。
灰度世界算法是一个比较简单并且广泛应用的算法。该算法是基于gray-world 假设提出的。根据灰度世界的假设,一张色彩丰富的图像的(R,G,B) 三个颜色分量的平均值趋于同一个值。灰度世界法通过对图像的三个分量分别求和然后取均值,根据均值调整三个通道的增益,使(R,G,B) 三个颜色分量的平均值相等,即实现 R_avg = G_avg = B_avg。
灰度世界法的代码
灰度世界的代码十分简洁有效,具体代码如下:
def AWB_GRAY(data):
R_mean = np.mean(data[::2, ::2])
B_mean = np.mean(data[1::2, 1::2])
G_mean = np.mean((data[1::2, ::2] + data[::2, 1::2]) / 2)
data[::2, ::2] = data[::2, ::2] * G_mean / R_mean
data[1::2, 1::2] = data[1::2, 1::2] * G_mean / B_mean
data = np.clip(data, 0, 2 ** 10 - 1)
return data
具体的思路就是先分别算出一张图片的R/G/B分量的均值,然后把R、B分量补偿到和G分量均值相等即可。另外,在这里还可以添加一个判断R/G/B分量大小的操作,然后把最大和最小的分量往中间分量补偿,从而更小的影响到整体图像的亮度。但是因为一张raw图,G分量的占比最大,人眼最敏感,所以一般都是把R/B分量往G分量去补偿。
灰度世界法的优点
灰度世界算法是一个十分经典、且十分简洁有效的算法,可以cover住绝大多数的自然场景。如下图,在实验室灯箱低色温场景下,拍摄标准24色卡图片,在不做AWB的情况下,整体画面偏黄。
当添加了灰度世界算法,做了AWB后,图像如下:
可以看出,经过灰度世界算法后,整体画面明显从之前的暖黄变成偏白,恢复了物体本来的颜色。
灰度世界法的缺点
灰度世界法对色彩丰富的场景可以做到十分有效地校正,但是对一些特殊场景,比如说大面积的纯色场景,蓝天、海洋等,此时场景颜色不够丰富,灰度世界法就会发生误判,甚至过度矫正的情况,导致画面偏蓝,颜色惨淡。如下图是灰度世界法处理后的:
可以看出,针对蓝天这种大面积纯色场景,灰度世界法还原的并不好。针对这些灰度世界法不适用的特殊场景,后文会讨论到,暂时先略过。
镜面反射法
镜面反射法又叫做完美反射法,它是基于这样的一种假设:一幅图当中,最亮的点相当于物体有光泽或镜面的点,因为它反射阳光并不吸收阳光,所以这个点最能体现当前光源最真实的颜色。所以镜像发射法就是基于这个最亮的点做参考白点,然后基于这个参考白点去做AWB。
镜面反射法的代码
镜面反射法的基本思路是找到一幅图像里面最亮的那个点,然后把这个点做白,从而达到整体画面白平衡正常的目的。具体代码如下:
def AWB_white(data):
R_max = np.max(data[::2, ::2])
B_max = np.max(data[1::2, 1::2])
G_max = np.max((data[1::2, ::2] + data[::2, 1::2]) / 2)
max1 = max(R_max,B_max,G_max)
data[::2, ::2] = data[::2, ::2] * max1 / R_max
data[1::2, 1::2] = data[1::2, 1::2] * max1 / B_max
data[1::2, ::2] = data[1::2, ::2] * max1 / G_max
data[::2, 1::2] = data[::2, 1::2] * max1/ G_max
data = np.clip(data, 0, 2 ** 10 - 1)
return data
镜面反射法的优点
镜面反射法的优点是,当图像的颜色比较单一时,镜面反射法是十分有效的。如下图:
可以看出,在这种大面积纯色的场景,灰度世界法并不适用。而镜像反射法就能较好地还原场景本来的色彩。
镜面反射法的缺点
镜面反射法虽然可以较好地还原单一颜色场景的白平衡,但是也有它很大的局限性。首先,当画面色彩较丰富时,镜像反射法的还原效果不如灰度世界法。如下图:
其次,因为镜像反射法是以图像中的最亮的点做参考白点,所以当图像里出现过曝的点时(尤其是其中一个通道饱和,其他两个通道还未饱和的时候),此时最亮的点因为芯片满阱容量的限制,最大值被限制住了,所以此时最亮的点并不能很好地反映当前光源下的真实颜色,此时再基于镜面反射法去做白平衡,效果是十分不理想的。如下图:
如上图,经过镜面反射法后的图像,整体都偏绿。原因是:R/B通道未饱和,是真实的亮度值;但是G通道已经饱和了,达到了最大值。此时的G通道理论上应该更大才对。补偿的时候,基于这个小的G通道的值计算就会补更多的G(实际上是补更少的R/B,等效于补更多的G),导致画面整体偏绿。
所以,镜像反射法适用于场景颜色较单一、画面整体亮度不高的场景。
总结
综上所述,灰度世界法和镜面反射法都有其优点和缺点,实际应用中也是多种算法融合、取舍的过程。主要的流程是先判断目前的环境,再根据目前的环境选择某一种算法或者几种算法结果以不同的比例(即置信度)混合,不同的算法也会去做进一步的限制和改良,从而使结果更加准确。至于具体的做法,下一篇里我们再详细介绍。