What is WB(white balance)?
人的视觉和神经系统在看到白色物体的时候,基本不受环境的变化而出现严重的错觉。比如阴天,晴天,室内,室外,日光灯,白炽灯等的环境下,人依然会将白纸视作白纸。
但是imagesensor这种电子器件没有心理和神经作用。受制于环境色温的影响。拍出的照片会出现偏色的情况。
色温的定义:一个黑体加热之后,随着温度的升高,黑体会先发出红色,然后越来越亮,变成黄光,在变成白光,直至蓝光,这个温度就是色温。
下面看几组照片:
7700k 5100k 3500k
对在其色温下出现白色偏色的图片的修正就是白平衡。比如:7700 ,3500 的图片通过对sensor四通道数字增益达到5100k时的状态就可以实现白平衡。
why go to WB?
为让拍出的图片不受环境色温的影响,接近人眼感受,拍出白色物体不至于受到色温影响偏色。
how to go to wb?
说白了就是调节R,G,B的比例。调节到正常51000K时r;g;b的1:1:1的状态。下面的对角矩阵就是增益。
那么这个对角增益矩阵如何确定呢?
1.可以在不同的色温光源下分别拍图,计算r/g,b/g,gr/gb的比值。以5100k(拍出的白纸视为白色)作为标准色温。
2.通过计算Gain_r/g, Gain_b/g,Gain_gr/gb就有了。假设出现如下关系:
3.增益关系有了之后,我们再引进一个色温对应增益关系,如果知道色温就可以对原始图片进行白平衡了。例如:
上面的就是白平衡的原理了。
那么何为自动白平衡呢?
当然就是色温估计后根据色温增益曲线直接对图片进行白平衡了。
那么色温估计如何做呢?目前的算法如灰度世界法,白点法等等一系列改进的方法。我看了这些算法,总感觉很牵强。有各种各样的问题。
1 目前主流的色温估计方法是使用统计加权白点估计法。
选取图片roi. 分成N*M块. 计算每一块的r,g,b平均值,然后计算r_avr/g_avr , b_avr/g_avr。然后将可能是白点的块保留,统计到色温曲线的距离,看哪些块距离色温曲线近且这样的块多,则认为就是目前的色温。如下图。
2 最新的色温估计直接使用色温传感器,预测的色温精准。这样就大大避开了估计算法的各种问题。例如,华为p20,传感器代替算法来估计色温的方法必将走向普及。
附一段灰度世界的白平衡方法(这个方法不需要模组厂进行wb calibration,方法简单,速度快,常用在车载镜头):
#include <highgui/highgui.hpp>
#include <imgproc/imgproc.hpp>
using namespace cv;
int main()
{
Mat imageSource = imread("sunny123456.jpg");
imshow("原始图像", imageSource);
vector<Mat> imageRGB;
//RGB三通道分离
split(imageSource, imageRGB);
//求原始图像的RGB分量的均值
double R, G, B;
B = mean(imageRGB[0])[0];
G = mean(imageRGB[1])[0];
R = mean(imageRGB[2])[0];
//需要调整的RGB分量的增益
double KR, KG, KB;
KB = (R + G + B) / (3 * B);
KG = (R + G + B) / (3 * G);
KR = (R + G + B) / (3 * R);
//调整RGB三个通道各自的值
imageRGB[0] = imageRGB[0] * KB;
imageRGB[1] = imageRGB[1] * KG;
imageRGB[2] = imageRGB[2] * KR;
//RGB三通道图像合并
merge(imageRGB, imageSource);
imshow("白平衡调整后", imageSource);
waitKey();
}
sensor 插值后的图和白平衡后的图比较。(我同事的肖像,男版lena)