自动白平衡

颜色恒常性

颜色恒常性(Color constancy)是指当照射物体表面的颜色光发生变化时,人们对该物体表面颜色的知觉仍然保持不变的知觉特性。即在不同光照色温条件下,人眼看到的同一个物体,主观感觉上颜色是相同的。这被称为视觉颜色恒常性。

详细地说,就是某一个特定物体,由于环境(尤其特指光照环境)的变化,该物体表面的反射谱会有不同。人类的视觉识别系统能够识别出这种变化,并能够判断出该变化是由光照环境的变化而产生的,当光照变化在一定范围内变动时,人类识别机制会在这一变化范围内认为该物体表面颜色是恒定不变的。这是大脑对外界环境感知的反应。当外界环境信息不足时,无法建立正确的色彩恒常感知。

色温

光源的色温定义为与此光源发出相似的光的黑体辐射体的开尔文温度。黑体(Black body),是一个物理学中的理想化的物体,它能够吸收外来的全部电磁辐射,并且不会有任何的反射与透射。黑体对于任何波长的电磁波的吸收系数为1,透射系数为0。物理学家以此作为热辐射研究的标准物体。它能够完全吸收外来的全部电磁辐射,并且不会有任何的反射与透射,这种物体就是绝对黑体,简称黑体。黑体不是黑色的物体,例如太阳可以近似看做是一个黑体。

太阳表面温度约为 5500K,这个温度的黑体发出的光,基本就是白色。在色彩空间中我们需要定义一个白点,而常见的一些标准白点,就是以 5500K 左右的黑体辐射(也就是我们的太阳)为基础的。CIE 委员会规定的几种标准白点中,D50、D55 和 D65 是常用的白点,参照了 5000K、5500K 和 6500K 的黑体辐射来定义,模拟了不同条件下(比如地平线方向的光照、上下午的室外、正午室外)的光照。色彩空间 sRGB 所依赖的白点就是 D65。

对于色温,通常有几个误解。第一个误解是混淆了色温和情感上的温度倾向。我们必须理解,色温是根据黑体辐射温度来定义的,是物理上的温度,而不是情感上的温度。从我们的情感上来说,橙色红色给人感觉温暖,蓝色给人感觉寒冷。但从色温的定义来看,红色橙色是温度较低的黑体发出的颜色,而温度高的黑体颜色反而是蓝色。(暖色调色温低,冷色调色温高)

第二个误解是混淆了色温针对的对象。狭义上来说,色温是针对光源的。比如晴朗正午的室外,光源是太阳(以及部分蓝天),这个时候的光源接近标准光源 D65,色温接近 6500K;又比如说傍晚日落,经过大气层的散射,阳光中的蓝光大大减少,光线颜色偏黄,光源颜色也许接近 3500K 的黑体。

1700 K:火柴光
1850 K:蜡烛
2800 K:钨灯(白炽灯)的常见色温
3000 K:卤素灯及黄光日光灯的常见色温
3350 K:演播室“CP”灯
3400 K:演播室台灯,、照相泛光灯(不是闪光灯)等…
4100 K:月光、浅黄光日光灯
5000 K:日光
5500 K:平均日光、电子闪光(因厂商而异)
5770 K:有效太阳温度
6420 K:氙弧灯
6500 K:最常见的白光日光灯色温
9300 K:电视屏幕(模拟)

参考博文:
色温、白平衡与色彩恒常性
颜色恒常性与自动白平衡

自动白平衡

图像传感器只是记录了所有投射到其上的光线,其本身并不能分辨投射到其上的色光是由物体本身的色彩反射而成,还是由偏色的环境光造成,所以传感器是没有颜色恒常性能力,不能够适应这种色光的变化 所以当它真实呈现出所拍摄到的图像时,就出现了偏色。

为了使得摄像机也具有颜色恒常性能力,需要使用自平衡技术。自动白平衡,即将在不同光源照射下的白色,还原为标准光源照射下人眼视觉效果中的白色。

我们可以用一个标准白点(比如D65)作为光源,照射到物体上。我们认为这个时候物体表现出来的「颜色」就是物体「本来」的颜色,可以定义为物体的「固有色」。固有色的光谱功率分布曲线与物体本身的反射率曲线两者是很接近的。

自动白平衡(Auto White Balance)要做的,就是在不同的光线条件下,根据当时得到的物体颜色,尽量恢复物体的「固有色」,或者说,尽量减小光源颜色对物体颜色的影响。

灰度世界法

灰度世界算法基于一个假说:任一幅图像,当它有足够的色彩变化,则它的RGB分量的均值会趋于相等。这是一个在自动白平衡方面应用极为广泛的理论。如上图一个颜色足够充足的画面里,假说RGB三个通道的均值是相同的。

对此算法的流程如下:

  • 计算各个颜色通道的平均值;
  • 寻找一个参考值K,一般情况选取Gmean;
  • 计算Rgain = Gmean/Rmean, Bgain = Gmean/Bmean;
  • 对图像中的每个像素都乘以对应的gain值进行校正;

完美反射法

完全反射也是基于一个假说:基于这样一种假设,一幅图像中最亮的像素相当于物体有光泽或镜面上的点,它传达了很多关于场景照明条件的信息。如果景物中有纯白的部分,那么就可以直接从这些像素中提取出光源信息。因为镜面或有光泽的平面本身不吸收光线,所以其反射的颜色即为光源的真实颜色,这是因为镜面或有光泽的平面的反射比函数在很长的一段波长范围内是保持不变的。完美反射法就是利用用这种特性来对图像进行调整。算法执行时,检测图像中亮度最高的像素并且将它作为参考白点。基于这种思想的方法都被称为是完美反射法,也称镜面法。通俗的意思就是整个图像中最亮的点就是白色或者镜面反射出来的,那么最亮的点就是光源的属性,但是该点本身应该是白点,以此为基础就可计算出gain值从而进行校正。

具体步骤以红色通道为例:

  • 图像相关信息统计

R m a x = m a x ( R i j ) G m a x = m a x ( G i j ) B m a x = m a x ( B i j ) Rmax = max(R_{ij})\\ Gmax = max(G_{ij})\\ Bmax = max(B_{ij}) Rmax=max(Rij)Gmax=max(Gij)Bmax=max(Bij)

A m a x = m a x ( R m a x , G m a x , B m a x ) Amax = max(Rmax,Gmax,Bmax) Amax=max(Rmax,Gmax,Bmax)

  • RGB通道增益计算

R g a i n = A m a x / R m a x G g a i n = A m a x / G m a x B g a i n = A m a x / B m a x Rgain = Amax / Rmax\\ Ggain = Amax / Gmax\\ Bgain = Amax / Bmax\\ Rgain=Amax/RmaxGgain=Amax/GmaxBgain=Amax/Bmax

  • 校正

R ’ = R ∗ R g a i n G ′ = G ∗ G a i n B ′ = B ∗ B g a i n R’ = R*Rgain\\ G' = G*Gain\\ B' = B*Bgain R=RRgainG=GGainB=BBgain

灰度世界和完美反射结合法

结合以上两种方法,用二次函数进行映射,形如:

R ′ = u R 2 + v R R' = uR^2+vR R=uR2+vR
为了使灰度世界假设成立,必须满足:

R m e a n ′ = G m e a n R'_{mean} = G_{mean} Rmean=Gmean

u R m e a n 2 + v R m e a n = G m e a n uR^2_{mean}+vR_{mean} = G_{mean} uRmean2+vRmean=Gmean
为了使完美反射假设成立,必须满足

u R m a x 2 + v R m a x = max ⁡ ( R m a x , G m a x , B m a x ) uR^2_{max}+vR_{max} = \max(R_{max},G_{max},B_{max}) uRmax2+vRmax=max(Rmax,Gmax,Bmax)
于是有:

[ R m e a n 2 R m e a n R m a x 2 R m a x ] [ u v ] = [ G m e a n max ⁡ ( R m a x , G m a x , B m a x ) ] \left[ \begin{matrix} R^2_{mean} & R_{mean}\\ R^2_{max} & R_{max} \end{matrix} \right] \left[ \begin{matrix} u\\ v \end{matrix} \right] = \left[ \begin{matrix} G_{mean}\\ \max(R_{max},G_{max},B_{max}) \end{matrix} \right] [Rmean2Rmax2RmeanRmax][uv]=[Gmeanmax(Rmax,Gmax,Bmax)]
用最小二乘法计算u和v

matlab code

function out = awb(img_raw,bayer,method, params)
    %%
    if bayer == "grbg"
        Gr = img_raw(1:2:end,1:2:end);
        R  = img_raw(1:2:end,2:2:end);
        B  = img_raw(2:2:end,1:2:end);
        Gb = img_raw(2:2:end,2:2:end);
    elseif bayer == "gbrg"
        Gb = img_raw(1:2:end,1:2:end);
        B  = img_raw(1:2:end,2:2:end);
        R  = img_raw(2:2:end,1:2:end);
        Gr = img_raw(2:2:end,2:2:end);
    elseif bayer == "rggb"
        R  = img_raw(1:2:end,1:2:end);
        Gr = img_raw(1:2:end,2:2:end);
        Gb = img_raw(2:2:end,1:2:end);
        B  = img_raw(2:2:end,2:2:end);
    elseif bayer == "bggr"
        B  = img_raw(1:2:end,1:2:end);
        Gb = img_raw(1:2:end,2:2:end);
        Gr = img_raw(2:2:end,1:2:end);
        R  = img_raw(2:2:end,2:2:end);
    end
    %% The Gray world
    if method == "the_gray_world"
        Gmean       = mean((Gr(:)+Gb(:))/2);
        Rmean       = mean(R(:));
        Bmean       = mean(B(:));
        Rgain       = Gmean/Rmean;
        Bgain       = Gmean/Bmean;

        if bayer == "grbg"
            gain    = [1 Rgain; Bgain 1];
        elseif bayer == "gbrg"
            gain    = [1 Bgain; Rgain 1];
        elseif bayer == "rggb"
            gain    = [Rgain 1; 1 Bgain];
        elseif bayer == "bggr"
            gain    = [Bgain 1; 1 Rgain];
        end
        gain        = repmat(gain,size(img_raw)/2);
        img_raw     = min(img_raw .* gain,2^params.bits-1);
        img         = demosaic(uint16(img_raw/4),bayer);
        figure;imshow(uint8(img))
%         imwrite(uint8(img),[params.outDataPath,'the_gray_world.bmp']);
        imwrite(max(0,min(1,(double(img)/255).^0.45)),[params.outDataPath,'the_gray_world.bmp'])
    end
    %% Perfect Reflector Assumption
    if method == "perfect_reflector_assumption"
        Rmax            = max(R(:));
        Gmax            = max((Gr(:)+Gb(:))/2);
        Bmax            = max(B(:));
        Amax            = max(max(Rmax,Gmax),Bmax);
        Rgain           = Amax/Rmax;
        Ggain           = Amax/Gmax;
        Bgain           = Amax/Bmax;
        if bayer == "grbg"
            gain        = [1 Rgain; Bgain 1];
        elseif bayer == "gbrg"
            gain        = [1 Bgain; Rgain 1];
        elseif bayer == "rggb"
            gain        = [Rgain 1; 1 Bgain];
        elseif bayer == "bggr"
            gain        = [Bgain 1; 1 Rgain];
        end
        gain            = repmat(gain,size(img_raw)/2);
        img_raw         = min(img_raw .* gain,2^params.bits-1);
        img             = demosaic(uint16(img_raw/4),bayer);
        figure;imshow(uint8(img))
%         imwrite(uint8(img),[params.outDataPath,'perfect_reflector_assumption.bmp'])
        imwrite(max(0,min(1,(double(img)/255).^0.45)),[params.outDataPath,'perfect_reflector_assumption.bmp'])
    end
    %% merge The Gray world and Perfect Reflector Assumption
    if method == "merge_gr_ra"
        Gmean                    = mean((Gr(:)+Gb(:))/2);
        Rmean                    = mean(R(:));
        Bmean                    = mean(B(:));
        Rmax                     = max(R(:));
        Gmax                     = max((Gr(:)+Gb(:))/2);
        Bmax                     = max(B(:));
        Amax                     = max(max(Rmax,Gmax),Bmax);
        
        G2mean                   = mean((Gr(:).^2+Gb(:).^2)/2);
        R2mean                   = mean(R(:).^2);
        B2mean                   = mean(B(:).^2);
        R2max                    = max(R(:).^2);
        G2max                    = max((Gr(:).^2+Gb(:).^2)/2);
        B2max                    = max(B(:).^2);
        
        uvR                      = [R2mean Rmean; R2max Rmax]\[Gmean;Amax];
        uvB                      = [B2mean Bmean; B2max Bmax]\[Gmean;Amax];
        uvG                      = [G2mean Gmean; G2max Gmax]\[Gmean;Amax];
        if bayer == "grbg"
            img_raw(1:2:end,1:2:end) = uvG(1)*img_raw(1:2:end,1:2:end).^2+uvG(2)*img_raw(1:2:end,1:2:end);
            img_raw(1:2:end,2:2:end) = uvR(1)*img_raw(1:2:end,2:2:end).^2+uvR(2)*img_raw(1:2:end,2:2:end);
            img_raw(2:2:end,1:2:end) = uvB(1)*img_raw(2:2:end,1:2:end).^2+uvB(2)*img_raw(2:2:end,1:2:end);
            img_raw(2:2:end,2:2:end) = uvG(1)*img_raw(2:2:end,2:2:end).^2+uvG(2)*img_raw(2:2:end,2:2:end);
        elseif bayer == "gbrg"
            img_raw(1:2:end,1:2:end) = uvG(1)*img_raw(1:2:end,1:2:end).^2+uvG(2)*img_raw(1:2:end,1:2:end);
            img_raw(1:2:end,2:2:end) = uvB(1)*img_raw(1:2:end,2:2:end).^2+uvB(2)*img_raw(1:2:end,2:2:end);
            img_raw(2:2:end,1:2:end) = uvR(1)*img_raw(2:2:end,1:2:end).^2+uvR(2)*img_raw(2:2:end,1:2:end);
            img_raw(2:2:end,2:2:end) = uvG(1)*img_raw(2:2:end,2:2:end).^2+uvG(2)*img_raw(2:2:end,2:2:end);
        elseif bayer == "rggb"
            img_raw(1:2:end,1:2:end) = uvR(1)*img_raw(1:2:end,1:2:end).^2+uvR(2)*img_raw(1:2:end,1:2:end);
            img_raw(1:2:end,2:2:end) = uvG(1)*img_raw(1:2:end,2:2:end).^2+uvG(2)*img_raw(1:2:end,2:2:end);
            img_raw(2:2:end,1:2:end) = uvG(1)*img_raw(2:2:end,1:2:end).^2+uvG(2)*img_raw(2:2:end,1:2:end);
            img_raw(2:2:end,2:2:end) = uvB(1)*img_raw(2:2:end,2:2:end).^2+uvB(2)*img_raw(2:2:end,2:2:end);
        elseif bayer == "bggr"
            img_raw(1:2:end,1:2:end) = uvB(1)*img_raw(1:2:end,1:2:end).^2+uvB(2)*img_raw(1:2:end,1:2:end);
            img_raw(1:2:end,2:2:end) = uvG(1)*img_raw(1:2:end,2:2:end).^2+uvG(2)*img_raw(1:2:end,2:2:end);
            img_raw(2:2:end,1:2:end) = uvG(1)*img_raw(2:2:end,1:2:end).^2+uvG(2)*img_raw(2:2:end,1:2:end);
            img_raw(2:2:end,2:2:end) = uvR(1)*img_raw(2:2:end,2:2:end).^2+uvR(2)*img_raw(2:2:end,2:2:end);
        end
        img_raw                  = min(img_raw,2^params.bits-1);
        img                      = demosaic(uint16(img_raw/4),bayer);
        img                      = min(img,255);
        figure;imshow(uint8(img))
        imwrite(max(0,min(1,(double(img)/255).^0.45)),[params.outDataPath,'merge.bmp'])
    end
    out = img_raw;




  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值