图像处理之去雾——基于图像暗通道的去雾算法

本文主要介绍一种常用的图像去雾算法,算法原文作者是何凯明,该文章获得2009年CVPR最佳论文。原文地址http://research-srv.microsoft.com/en-us/um/people/kahe/publications/pami10dehaze.pdf
本文基于学习和分享的目的,探讨图像去雾算法。

首先介绍一下理论基础:
暗通道:何博士对大量的户外图像进行分析后,发现一个普遍存在的规律。在晴空图像的patches中,至少有一个通道的某些像素的值很小,接近零。换句话解释:在一幅晴空图像的非天空部分的局部区域内,存在一些像素至少一个颜色通道具有很低的值。该区域内各个通道的最小值接近零。

上面的公式表述了这种统计规律,y是像素索引,位于以像素x为中心的窗口内,c代表图像的通道(真彩色图像对应得值为红、绿、蓝),J是求得的暗通道图像。
暗通道的求法:先对图像每个像素三个通道的值取最小,得到最小通道图像,再对该图像做滤波,窗口大小根据具体情况选取。

根据先验知识可知,晴朗区域的暗通道值接近0

建筑物、汽车等的阴影;彩色地物或者是树干、石头等,这些地物都符合该先验知识,因而这一假设在大部分情况下成立。

为了说明该先验知识的通用性,作者做了很多实验,在论文中有体现。本文只展示做的一组实验如下:

图像处理之去雾——基于图像暗通道的去雾算法_第1张图片

对应的暗通道计算结果如下,可以看到除了云区其他部分区域暗通道值都很低:


图像处理之去雾——基于图像暗通道的去雾算法_第2张图片


上述暗通道图像均使用的窗口大小为15*15。

计算机视觉和计算机图形学常用的雾图像成像模型如下:

其中  其中,I(X)就是待去雾的图像,J(x)是我们要恢复的无雾的图像,A是环境光, t(x)为透射率。现在的已知I(X),求目标值J(x)。

利用暗通道先验知识,可以对其进行化简:

将式(1)左右两边分别除以环境光得到:

                                                    

    其中上标c表示R/G/B三个通道。

    首先假设在每一个窗口内透射率t(x)为常数,定义他为,对式(7)两边求两次最小值运算,得到下式:

                                  

    根据前述的暗原色先验理论有:

                                               

     由此可知:

                                                         

    将式(10)带入式(8)得到:

                                                 

    进而可以估计透射率的值。

    在现实生活中,即使是晴天,也存在气溶胶的影响。因而在式(11)中引入一个在[0,1] 之间的因子,则式(11)修正为:

                                               

     原文使用以下值进行实验:  ω=0.95。

下一步求环境光A,具体步骤如下:

      (1) 从暗通道图像中取前0.1%的像素。

         (2) 记录第一步得到的像素区域,在原始有雾图像I中寻找对应位置,其中最高亮度的点的值,作为每个通道的A值。

     下面进行图像去雾:由式(1)可知:  J = ( I - A)/t + A  

     当投射率t(x)的值很小时,会导致J的值偏大,这里使用阈值法,对于小于t0的t(x)取值为t0

     因此,最终的恢复公式如下:

                                


由于得到的暗通道图像比较粗糙,容易产生边缘现象。作者使用soft matting算法,但是计算量太大,限制了可以处理的图像的大小。2011年,何博士又发了一篇文章 guided Filter,该方法可以使用原图像的RGB彩色图作为导向图,对透射率图像进行精细化处理。然后再做图像恢复,可以得到更精细地效果。

原始图像:

图像处理之去雾——基于图像暗通道的去雾算法_第3张图片
暗通道图像:

图像处理之去雾——基于图像暗通道的去雾算法_第4张图片
精细化后的透视率图:

图像处理之去雾——基于图像暗通道的去雾算法_第5张图片
结果:
图像处理之去雾——基于图像暗通道的去雾算法_第6张图片


其中计算暗通道的matlab代码如下:

function tgt = dark_channel(IM)


[h, w, c] = size(IM);

%最小值滤波的半径为7像素
win_step = 7;
min_pixel = min(IM,[],3);

dark_mini = ones(h,w);
%忽略了边缘
for i = 1+win_step:h-win_step
    for j = 1+win_step:w-win_step
        local_min = min_pixel(i,j);
        for m = i-win_step:i+win_step
            for n = j- win_step:j+win_step
                if(dark_mini(m,n) > local_min)
                    dark_mini(m,n) = local_min;
                end
            end
        end
    end
end


tgt = dark_mini;
imwrite(tgt,'dark.png','png');




你可能感兴趣的:(Image,Processing)