AWB算法的必要性:对于彩色相机成像而言,AWB算法可以矫正颜色,视觉效果上看,颜色更符合人眼效果。
光学原理:人眼对于颜色具有恒常性。
从数学角度来看:所有AWB算法都是调节R,G,B三通道的增益值;所有手动调节白平衡便是人工输入三通道的增益值。
基于假设:任何一幅图像,R,G,B分量的均值趋于一致;
目标:R_mean=G_mean=B_mean;
具体实现步骤:
先求R,G,B三通道的均值Rmean,Gmean,Bmean;
求解rGain,bGain,调节R,B通道趋于Gmean值;(三通道中G通道所占比例尤为重要,也会影响到灰度);
rGain = Gmean/Rmean;
bGain = Gmean/Bmean;
使用增益值,更新R,B通道;
R_new = RrGain;
B_new = BbGain;
matlab源代码:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%代码---AWB算法的灰度世界算法(GW法)
%Author:Zhu
%时间:2022.7
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc;
clear;
close all;
%%%读取一个RGB图
clc;
image = imread("E:\1.bmp");
[height,width,channels]=size(image);
figure;
imshow(image);
title('Color image');
image_R=image(:,:,1);
image_R=double(image_R);
image_G=image(:,:,2);
image_G=double(image_G);
image_B=image(:,:,3);
image_B=double(image_B);
%%%求解的新通道矩阵
R_image = zeros(height,width);
G_image = zeros(height,width);
B_image = zeros(height,width);
%%%先求三通道R,G,B的平均值
Rmean = mean(mean(image_R));
Gmean = mean(mean(image_G));
Bmean = mean(mean(image_B));
%%%再求三通道与绿色通道的比例关系,这里采用的是全局的比值关系
rGain = Gmean/Rmean;
bGain = Gmean/Bmean;
%%%遍历RGB像素点
for i=1:1:height
for j=1:1:width
R_image(i,j) = rGain*image_R(i,j);
G_image(i,j) = image_G(i,j);
B_image(i,j) = bGain*image_B(i,j);
end
end
B_image = uint8(B_image);
R_image = uint8(R_image);
G_image = uint8(G_image);
%%%将三个矩阵叠加显示颜色
figure;
out_image=cat(3,R_image,G_image,B_image);
imshow(cat(3,R_image,G_image,B_image));
title('GW image');
效果图
C++ 源代码
void AWB_RGB(unsigned char *srcData,unsigned char *rgbData,int height,int width)
{
//输入图像的char以RGB排列,输出也以RGB排列(OpenCV中Mat类型三通道呈一维数组排列,排列顺序是BGR)
//先统计每个通道内的平均值
unsigned long long R_count = 0;
unsigned long long G_count = 0;
unsigned long long B_count = 0;
for(int i = 0; i<height*width*3;i+=3)
{
//r通道总值
R_count = *(srcData + i);
//g通道总值
G_count = *(srcData + i + 1);
//b通道总值
B_count = *(srcData + i + 2);
}
//求解各通道的Gain
float R_Gain = G_count*1.0/R_count;
float B_Gain = G_count*1.0/B_count;
for(int i = 0; i<height*width*3;i+=3)
{
//目前输出以RGB的形式
//更新R通道的值
*(rgbData + i) = (R_Gain*(*(srcData + i)))>255?255:(R_Gain*(*(srcData + i)));
//g通道总值
*(rgbData + i + 1) = *(srcData + i + 1);
//b通道总值
*(rgbData + i + 2) = (B_Gain*(*(srcData + i +2)))>255?255:(B_Gain*(*(srcData + i +2)));
}
}
基于假设:一幅图像中最亮的点包含很多场景信息;亮点相当于有光泽或者镜面上的点;镜面点本身不吸收光线,其反射的颜色即为光源真实颜色;
具体实现步骤:
先求R,G,B三通道最大值Rmax,Gmax,Bmax;
再求rGain,bGain,gGain,对每个通道调节;
rGain = max(Rmax,Gmax,Bmax)/Rmax;
gGain = max(Rmax,Gmax,Bmax)/Gmax;
bGain = max(Rmax,Gmax,Bmax)/Bmax;
使用增益值,更新R,G,B通道;
R_new = R * rGain;
G_new = G * gGain;
B_new = B * bGain;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%代码---AWB算法的完美反射算法
%Author:zhu
%时间:2022.7
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc;
clear;
close all;
%%%读取一个RGB图
clc;
image = imread("E:\1.bmp");
[height,width,channels]=size(image);
figure;
imshow(image);
title('Color image');
image_R=image(:,:,1);
image_R=double(image_R);
image_G=image(:,:,2);
image_G=double(image_G);
image_B=image(:,:,3);
image_B=double(image_B);
%%%求解的新通道矩阵
R_image = zeros(height,width);
G_image = zeros(height,width);
B_image = zeros(height,width);
%%%先求三通道R,G,B的最大值
Rmax = max(max(image_R));
Gmax = max(max(image_G));
Bmax = max(max(image_B));
%%%再求每个通道最大值与最大值之间的比例关系,这里采用的是通道之间最大比例值关系
Gain_R = max([Rmax,Gmax,Bmax])/Rmax;
Gain_G = max([Rmax,Gmax,Bmax])/Gmax;
Gain_B = max([Rmax,Gmax,Bmax])/Bmax;
%%%遍历RGB像素点
for i=1:1:height
for j=1:1:width
R_image(i,j) = Gain_R*image_R(i,j);
G_image(i,j) = Gain_G*image_G(i,j);
B_image(i,j) = Gain_B*image_B(i,j);
end
end
B_image = uint8(B_image);
R_image = uint8(R_image);
G_image = uint8(G_image);
%%%将三个矩阵叠加显示颜色
figure;
out_image=cat(3,R_image,G_image,B_image);
imshow(cat(3,R_image,G_image,B_image));
title('PR image');
效果图
融合GW算法和完美反射法,采用正交分解的思路,对两种算法计算参数
先求R,G,B三通道最大值和平均值Rmax,Gmax,Bmax,Rmean,Gmean,Bmean
Kmean = (Rmean+Gmean+Bmean)/3;
Kmax = (Rmax+Gmax+Bmax)/3;
再求三通道对应的u,v值;
更新R,G,B通道
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%代码---AWB算法的GCPR算法
%Author:zhu
%时间:2022.7
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc;
clear;
close all;
%%%读取一个RGB图
clc;
image = imread("E:\1.bmp");
[height,width,channels]=size(image);
figure;
imshow(image);
title('Color image');
image_R=image(:,:,1);
image_R=double(image_R);
image_G=image(:,:,2);
image_G=double(image_G);
image_B=image(:,:,3);
image_B=double(image_B);
%%%求解的新通道矩阵
R_image = zeros(height,width);
G_image = zeros(height,width);
B_image = zeros(height,width);
%%%先求解每个通道的最大值和平均值
R_mean = mean(mean(image_R));
G_mean = mean(mean(image_G));
B_mean = mean(mean(image_B));
R_max = max(max(image_R));
G_max = max(max(image_G));
B_max = max(max(image_B));
K_mean = (R_mean + G_mean + B_mean)/3;
K_max = (R_max + G_max + B_max)/3;
%%%R通道下正交分解求解u,v
X = [R_mean*R_mean,R_mean;R_max*R_max,R_max]\[K_mean,K_max]';
U_r = X(1);
V_r = X(2);
%%%G通道下正交分解求解u,v
X = [G_mean*G_mean,G_mean;G_max*G_max,G_max]\[K_mean,K_max]';
U_g = X(1);
V_g = X(2);
%%%B通道下正交分解求解u,v
X = [B_mean*B_mean,B_mean;B_max*B_max,B_max]\[K_mean,K_max]';
U_b = X(1);
V_b = X(2);
%%%遍历RGB像素点,求解新的R,G,B值
for i=1:1:height
for j=1:1:width
R_image(i,j)=U_r*image_R(i,j)*image_R(i,j)+V_r*image_R(i,j);
G_image(i,j)=U_g*image_G(i,j)*image_G(i,j)+V_g*image_G(i,j);
B_image(i,j)=U_b*image_B(i,j)*image_B(i,j)+V_b*image_B(i,j);
end
end
R_image = uint8(R_image);
G_image = uint8(G_image);
B_image = uint8(B_image);
%%%将三个矩阵叠加显示颜色
figure;
imshow(cat(3,R_image,G_image,B_image));
title('QCGP image');
图像效果