简述
OpenCV对图像进行处理时,有时图像RGB受光照影响比较严重,转换到HSV等空间也解决不了时,可以用白平衡算法进行修正,使其发黄、发蓝、发红的照片更加趋于自然光下的图像。
白平衡算法有很多种,其中常用的有灰度世界法和镜面法。
色彩是人眼的对可视光的一种感知。对于不透明的物体而言,人眼所形成的色彩感知取决于光照光谱分布、物体表面光的反射性和人眼(或者其它光信号接收器)的光敏特性。在光信号接收器的光敏特性保持不变,物体也保持不变的情况下,人眼对该物体的色彩感知就取决于光照的光谱分布。由于人眼视觉的色彩恒常性,当环境光发生变化的时候,我们人类的视觉系统具有某种调节能力,可以让我们的大脑还原物体表面的不变特征,但是对于像照相机这样的光信号接收器,它只能如实地记录所接收到的光信号,因此在不同光源下所得到的图像在我们人类看起来会有色彩的偏差,下图所展示就是由于光源的不同造成同一物体色差不同的例子。
为了能够让照相机等成像设备可以具有类似于人眼的视觉调节能力,在不同的光照情况下,使所获取的图像颜色保持一致,对所获得图像所做的处理就叫做白平衡。在专业的摄像领域,相机可以通过调节自身光敏器件对可见光中不同颜色单色光的敏感性来实现对图像的白平衡,以达到摄影师所想要的效果。对于已经获取的图像,如果因为光照原因出现色彩的偏差的话,我们有时候也寄希望于通过现有图像来得到图像获取时的光照信息,基于这些信息来对图像进行调整以获得在某种标准光源下的图像,于是就产生了很多白平衡的算法,其中灰度世界算法和镜面法是较为常用白平衡算法。
原理
Von Kries色适应理论。Von Kries提出,可用一个对角矩阵变换来描述两种光照条件下同一物体表面颜色之间的关系[1]。该理论认为,对于同一个观察者而言,假设在光源A下面,一个物体的RGB值为RGB1=[R1,G1,B1],如果在光源B下面同一个物体的RGB值为RGB2=[R2,G2,B2],那么RGB1与RGB2之间存在这如下转换关系。RGB2’=[kr,0,0;0,kg,0;0,0,kb]RGB1',其中kr、kg和kb分别为R、G、B三个通道的校正系数。我们接下来将要介绍的灰度世界算法和镜面法的理论都是建立在这一原理的基础上的,需要注意的是,这个理论在某些条件下是不适用的。
灰度世界法
该理论假设:对于一副有着丰富色彩的图片,图像上R、G、B三个通道的平均值应该等于一个被称为“灰色”的值K[2]。理论中最重要的一点就是“灰色”的定义和选择问题。有多种方法对理论中的“灰色”进行定义,在此不详细讨论这一点。至于“灰色”的选择,一种方法是将其定义为各通道最大值的一半,还可以将待处理图片三个通道均值的均值作为“灰色”值K。当确定了灰色值K之后,将待处理图片转换到经典光源下的各个校正系数分别为:kr=K/Rmean,kg=K/Gmean,kb=K/Bmean,其中Rmean,Gmean和Bmean分别为图像R、G、B通道的均值。
//图像白平衡
//该代码实现白平衡算法中的灰度世界法,能有效改善图像发红发蓝发绿的现象;
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat g_srcImage,dstImage;
vector<Mat> g_vChannels;
g_srcImage = imread("1.jpg");
imshow("原图",g_srcImage);
//waitKey(0);
//分离通道
split(g_srcImage,g_vChannels);
Mat imageBlueChannel = g_vChannels.at(0);
Mat imageGreenChannel = g_vChannels.at(1);
Mat imageRedChannel = g_vChannels.at(2);
double imageBlueChannelAvg=0;
double imageGreenChannelAvg=0;
double imageRedChannelAvg=0;
//求各通道的平均值
imageBlueChannelAvg = mean(imageBlueChannel)[0];
imageGreenChannelAvg = mean(imageGreenChannel)[0];
imageRedChannelAvg = mean(imageRedChannel)[0];
//计算标准灰度
double K = (imageRedChannelAvg+imageGreenChannelAvg+imageRedChannelAvg)/3;
//求出个通道所占增益
double Kb = K/imageBlueChannelAvg;
double Kg = K/imageGreenChannelAvg;
double Kr = K/imageRedChannelAvg;
//更新白平衡后的各通道BGR值
addWeighted(imageBlueChannel,Kb,0,0,0,imageBlueChannel);
addWeighted(imageGreenChannel,Kg,0,0,0,imageGreenChannel);
addWeighted(imageRedChannel,Kr,0,0,0,imageRedChannel);
merge(g_vChannels,dstImage);//图像各通道合并
imshow("白平衡后图",dstImage);
waitKey(0);
return 0;
}
运行效果:
后续更新其他方法。。。。。
最后
参考链接:
https://www.cnblogs.com/ggYYa/p/5707259.html