冲中值滤波或二者滤波方式的图像去雾效果的钻。一年去雾算法研究之下结论。

一、前言  

  从极度开头的Crimm
Imageshop中最为简单易行的去雾功能开始,到前不久为止研究的成百上千去雾算法,再至近年来同有些情侣的关于去雾经验的交流,感觉好对这个点的研讨已止步了,现对这些算法做个大概的总。

  实际上很久以前,当自己长接触图像去雾技术时,最先实现的凡基于中值滤波的图像去雾,并且也时有发生早晚之效用,在自身的Imageshop的合并软件被之去雾方案就是是的贯彻,不过大效果没本文好。

   
 本博客中共于来了6种出去雾功能的算法:

   
 而基于双方滤波的方案,也是坏已经耳闻过,前不久起心上人传于自己同篇国内的两端滤波去雾的论文,总体思路与基于中值的近乎,想想干脆拿当时简单独厕同开个比较吧。

  (1)冲何凯明博士提出的暗通道去雾算法;

老二、算法的流程

   
 (2)根据中值滤波(也不过下高斯\均值\两者之类的)的去雾;

     算法的卓绝基础之规律还是因大气散射模型的,即:

   
 (3)据悉均值滤波的实时去雾算法;

                   
 图片 1

  (4)根据多规格Retinex图像增强技术;

  已了解条件虽是输入图像I(X),求J(x);

  (5)因自适应直方图均衡化算法;

   
 在参考论文一致栽才幅图像去雾方法面临凡通过中值滤波的计来去雾的,而舆论因双方滤波的实时图像去雾技术研究选用了双方滤波,如果您要是兑现代码,可能要简单首论文做起来看,因为以舆论1遭遇之描述没有言语明白怎么通过获得的雾浓度数据来博取无雾的图像。

  (6)根据自适应对比度及色阶增强的图像算法;

   
 简单的吧,算法的流程可讲述如下:

  其中前面三栽算法属于基于去雾物理模型的,后三种植属于常见图像增强手段。

  1、定义F(X)=A(1-t(x)),称之为大气光幕或者也雾浓度。

   
 我们先说说后三栽吧。基于Retinex的算法对于整体偏暗的图像来十分好的增进作用,用于去雾方面只是可用于静态的图像,原因出:(1)
MSRCR是根据数高斯歪曲的,里面有很多底浮点计算,速度是个瓶颈;(2)对于有雾图,有或会见产出了增强气象,使之图像出现噪点;(3)对于我比较正常的觊觎,处理后底效用人的视觉看来很不自。

   
 2、计算图片 2,并运用和何博士论文中好像的主意测算全局大气光值A。

   
 第5同第6种算法i是民俗的增高算法,对于图像整体特点于单一的图去雾的意义还是相当显眼的,但是就有限个算法为参数的熏陶比较特别,特别是取样数或说是Tile的轻重,不同的Tile会造成局部图像的了增强(偏白或偏黑),并且算法的复杂度也比较大,内部的分块处理啊非合乎吃并行处理,严重限制了该以实时去雾方面的应用。

   
 3、计算图片 3,即对M(x)进行着值滤波。

     
第2种植基于中值滤波的计于一部分论文里也时有提到,实际我所以高斯或者均值之类的模糊代替高斯,也发生肯定之去雾能力,如果是因此中值,可能还会产出图像周边发生肯定的交界效果,如下图所显示,注意看建筑顶部的几乎独角的岗位:

   
 4、计算图片 4,注意式子中的绝对值。

 
  图片 5  

   
 5、计算图片 6,式中P为控制去雾程度之因子,取值范围[0,1]。

   
 还发出个问题便是虽然发迅速的中值算法,但是考虑到现在的工业应用场合常见的拍卖大小,实时性还是难以保证,因此,我当这个算法也惟有留在纸面上,创造不了以价值。 

   
 6、通过式子图片 7博去雾后底图像。

   
 第3首算法提出的实时算法,其基本就是是一个boxblur,约占整个过程耗时一半横,但实在能够不辱使命实时的力量。对于只有幅图像的去雾效果呢是一定之科学的,但是用于连续的视频流去雾似乎能发现各帧之间的过渡不是特地的当然。

   
 上面的多算式是从不同论文里截图的,因此表达上有些前后未平等,但切莫影响高手理解其含义。

   
 在的话说哪里凯明的去雾算法吧,我今天看来,还是这个算法极其平稳、最保险。一凡是以此算法的原理性经得起推敲,二是彼功能综合来说要比较任何的算法都也好,特别是用于连续的视频流。我觉着这要还是得益于那个透射率图如比其他的且也细。你若看中值或者特别实时的,就可清楚他们相应之透射率图都充分粗劣。
不过何的算法来一个致命的弱项,速度挺缓慢,因为不管用soft
matting或者guide
filter都发生正值大量之浮点运算,这严重的限量了该用于工业CCD的实时处理。

   
 如果是使双边滤波算子,则步骤3和4遭受的median运算符需修改也bilaterfilter,其他的步子同。

   
 鉴于斯,作者吧试着对代码进行好层次的优化,包括SSE处理、并行运行等,但出于算法本身的依次执行,无法全程并行,偶尔一个不怎么函数可以相互,但由该本身执行就专门快,比如不要5ms,你失去用并行算法可能耗时还会见大片段。因此,一直尚未呀好之提高,对于同合乎1024*768之彩图进行去雾需要90ms,这必然无法满足需求。

  算法的法则我操不干净,反正看之逾多更迷糊了。

   
 最近,在考虑,既然暗通道去雾的透射率图于其它的算法都来之巧夺天工,如果方便的骤降一点点其精度,其去雾的效应理论及应该不见面出无限死之界别,于是我想到了相同种植方法,即求取透射率的上不是对准原图进行求取,而是先对原图进行下采样,比如缩小为原图的1/4,计算产生小图的透射率,之后于经过插值的计的得原图大概的透射率,则该吗可以取力量。经过实践,这种艺术大大的提高了执行进度,而且意义以及老之方案基本一致,对于1024*768底图像大约只有待30ms了,如果越来越赢得1/9的缩放,则光待约20ms,完全好满足工业实时性要求大的场子。

其三、算法的效益

   
当然,如果你的缩小系数不是特意深之说话,比如缩小为本来的0.5尺寸,可能有限不善缩放所用之耗时还抵了算小图的透射率图所变来之致富,因此必须合理选择这个下采样率。

     
算法的功力或有点出乎意料,有些图取了相当不错的效力。

   
去雾还有一些其他人做的论文,比较经典仍有fattal论文:Single Image
Dehazing

 图片 8  图片 9  图片 10

                 Jean-Philippe
Tarel: Fast Visibility Restoration from a Single Color or Gray Level
Image

 图片 11  图片 12  图片 13

  最新的准2013年的 Gaofeng MENG:
Efficient Image Dehazing with Boundary Constraint
and Contextual
Regularization (国产的)

 图片 14  图片 15  图片 16

   
有趣味之爱侣可协调失去研究研究。 

 图片 17  图片 18  图片 19

   
我做了一个程序,集成了上述6种图像去雾的算法:
图像去雾综合版

 图片 20  图片 21  图片 22

 

 图片 23  图片 24  图片 25

图片 26 
 

           原图                          
   去雾图                          
 对应之大量光幕

 

 
 这里的大气光幕和何凯明的论文被的透射率图不是同一个概念,因此无有所可比性。

*********************************笔者:
laviewpbt   时间: 2014.1.12   联系QQ:  33184777
 转载请保留本行信息************************

 
 以大气光幕的公式中,我们来看出大局大气光A的熏陶,但是上述计算F(X)的长河真的无提到到A,很是无语啊。

 

 
 从效果及看,我所列举的这些事例都或对的,特别是率先帧图,用何凯明的暗通道我一直尚未调出这种效果。

 
 上述都是因此中值滤波做的效应,在有些图像对应大气光幕图上得望,图像的边缘处来有聊圆弧,这些还是矩形半径中值滤波的阳划痕,而根据双方滤波的我哉尽过,并无像参考论文2说之那么有略改进,感觉彼此彼此,而且有些图还会见现出突变,因此自觉着写这些论文纯粹是为发论文。 

季、代码实现细节

   
 在代码实现上,个人感觉没有啊困难,先要暗通道,然后便是几乎单中值滤波或者是两者滤波,求全局大气光的经过还关乎到最好小值滤波,主要的代码如下:

void _stdcall HazeRemovalBasedOnMedianBlur(unsigned char * Scan0, int Width,int Height,int Stride,int DarkRadius,int MedianRadius,int P)
{
    int  X, Y, Diff,Min,F;
    unsigned char* Pointer, *DarkP, *FilterP,* FilterPC;
    unsigned char * DarkChannel = (unsigned char*)malloc(Width * Height);
    unsigned char * Filter = (unsigned char*)malloc(Width * Height);
    unsigned char * FilterClone = (unsigned char*)malloc(Width * Height);

    for (Y = 0; Y < Height; Y++)
    {
        Pointer = Scan0 + Y * Stride;
        DarkP = DarkChannel + Y * Width;             // 由实际图像计算得到的图像暗通道     
        for (X = 0; X < Width; X++)
        {
            Min = *Pointer;
            if (Min > *(Pointer + 1)) Min = *(Pointer + 1);
            if (Min > *(Pointer + 2)) Min = *(Pointer + 2);
            *DarkP = (unsigned char)Min;
            DarkP++;
            Pointer += 3;
        }
    }
    memcpy(Filter, DarkChannel, Width * Height);                        // 求全局大气光A时会破坏DarkChannel中的数据

    MinValue(DarkChannel, Width, Height,Width,DarkRadius);                // 求取暗通道值

    // 利用暗通道来估算全局大气光值A
    int Sum, Value,Threshold = 0;
    int SumR = 0, SumG = 0, SumB = 0, AtomR, AtomB, AtomG, Amount = 0;
    int* Histgram = (int*)calloc(256 , sizeof(int));    
    for (Y = 0; Y < Width * Height; Y++) Histgram[DarkChannel[Y]]++;
    for (Y = 255, Sum = 0; Y >= 0; Y--)
    {
        Sum += Histgram[Y];
        if (Sum > Height * Width * 0.01)
        {
            Threshold = Y;                                        // 选取暗通道值中前1%最亮的像素区域为候选点
            break;
        }
    }
    AtomB = 0; AtomG = 0; AtomR = 0;
    for (Y = 0, DarkP = DarkChannel; Y < Height; Y++)
    {
        Pointer = Scan0 + Y * Stride;
        for (X = 0; X < Width; X++)
        {
            if (*DarkP >= Threshold)                            //    在原图中选择满足候选点的位置的像素作为计算全局大气光A的信息                        
            {
                SumB += *Pointer;
                SumG += *(Pointer + 1);
                SumR += *(Pointer + 2);
                Amount++;
            }
            Pointer += 3;
            DarkP++;
        }
    }
    AtomB = SumB / Amount;
    AtomG = SumG / Amount;
    AtomR = SumR / Amount;

    memcpy(DarkChannel,Filter, Width * Height);                        // 恢复DarkChannel中的数据
    MedianBlur(Filter,Width,Height,Width,MedianRadius,50);          // 步骤1:使用中值滤波平滑,这样处理的重要性是在平滑的同时保留了图像中的边界部分,但是实际这里用中值滤波和用高斯滤波效果感觉差不多
    memcpy(FilterClone, Filter, Width * Height);

    DarkP = DarkChannel;
    FilterP = Filter;
    for (Y = 0; Y < Height * Width; Y++)              //利用一重循环来计算提高速度
    {
        Diff = *DarkP - *FilterP;                    //通过对|DarkP -FilterP |执行中值滤波来估计的局部标准差,这样可以保证标准差估计的鲁棒性
        if (Diff < 0) Diff = -Diff;
        *FilterP = (unsigned char)Diff;
        DarkP++;
        FilterP++;
    }
    MedianBlur(Filter,Width,Height,Width,MedianRadius,50);

    FilterPC = FilterClone;
    FilterP = Filter;
    for (Y = 0; Y < Height * Width; Y++)
    {
        Diff = *FilterPC - *FilterP;                    // 步骤2:然后考虑到有较好对比度的纹理区域可能没有雾, 这部分区域就不需要做去雾处理
        if (Diff < 0) Diff = 0;                            // 这里可以这样做是因为在最后有个max(....,0)的过程,
        *FilterP = (unsigned char)Diff;
        FilterPC++;
        FilterP++;
    }

    DarkP = DarkChannel;
    FilterP = Filter;

    for (Y = 0; Y < Height * Width; Y++)
    {
        Min = *FilterP * P / 100;
        if (*DarkP > Min) 
            *FilterP = Min;                                // 获得满足约束条件的大气光幕
        else
            *FilterP = *DarkP;
        DarkP++;
        FilterP++;
    }

    FilterP = Filter;
    for (Y = 0;Y < Height; Y++)
    {
        Pointer = Scan0 + Y * Stride;
        for (X = 0; X < Width; X++)
        {
            F = *FilterP++;
            if (AtomB != F) 
                Value = AtomB *(*Pointer - F) /( AtomB - F);
            else
                Value=*Pointer;
            *Pointer++ = Clamp(Value);
            if (AtomG != F) 
                Value =  AtomG * (*Pointer - F) /( AtomG-F);
            else
                Value =  *Pointer;
            *Pointer++ = Clamp(Value);
            if (AtomR != F) 
                Value =  AtomR *(*Pointer - F) /( AtomR-F);
            else
                Value =  *Pointer;
            *Pointer++ = Clamp(Value);
        }
    }
    free(Histgram);
    free(Filter);
    free(DarkChannel);
    free(FilterClone);
}

   关于中值滤波或者两者滤波的速算法,可以当本人博客中找到大量底有关信息。

   
 在次的耗时达到,主要还是2次中值处理达成,借助于C++的有些优化(比如内嵌SSE代码,C#做不交)中值的快慢也一定快了,我于是1024*768底灰度图测试耗时盖为60ms(未考虑用多线程,因为十分程序用几近线程编码上会复杂不少),对彩色图用这种方法去雾,I3CPU上1024*768底总耗时大概为140ms,想使实时,换换I7的CPU试试吧(传说着本身的那么篇实时错过雾的章的算法在I3上20ms,I7上出测试表明只设3暨4ms)。

   
 由于算法的最终一步的公式问题,在好几参数情况下图像会油然而生黑快或者白块,目前欠问题没解决。
有趣味对改算法进行更为测试的校友可协调研究下。

     相关测试代码下载:

   
  http://files.cnblogs.com/Imageshop/HazeRemovalBasedOnMedianBlur.rar

     图片 27

 图片 28

*********************************作者:
laviewpbt   时间: 2013.12.5   联系QQ:  33184777
 转载请保留本行信息*************************

 

admin

网站地图xml地图