C++据悉中值滤波或双方滤波方式的图像去雾效果的钻。

一、前言  

  实际上很久以前,当自身第一接触图像去雾技术时,最先实现的凡冲中值滤波的图像去雾,并且为产生得的力量,在我之Imageshop的拼软件受到之去雾方案就是这的贯彻,不过那个效果没本文好。

   
 而根据双方滤波的方案,也是雅已经耳闻了,前不久发意中人传于本人平篇国内的双面滤波去雾的舆论,总体思路与基于中值的接近,想想干脆把当时简单单在一块儿开只比较吧。

第二、算法的流水线

     算法的无限基础的规律还是基于大气散射模型的,即:

                   
 

  已领略条件就是是输入图像I(X),求J(x);

   
 在参考论文相同种植就幅图像去雾方法倍受是透过中值滤波的点子来去雾的,而舆论因双方滤波的实时图像去雾技术研究选用了两岸滤波,如果你一旦兑现代码,可能得简单首论文做起来看,因为于舆论1中的讲述没有讲明白哪些通过获取的雾浓度数据来赢得无雾的图像。

   
 简单的来说,算法的流水线可讲述如下:

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

   
 2、计算,并应用和何博士论文中接近的艺术计算全局大气光值A。

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

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

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

   
 6、通过式子收获去雾后的图像。

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

   
 如果是应用双边滤波算子,则步骤3跟4负之median运算符需修改为bilaterfilter,其他的手续同。

  算法的法则我讲讲不到底,反正看之更加多逾迷糊了。

其三、算法的法力

     
算法的效用还是多少意外,有些图取了相当不错的功能。

     

     

     

     

     

     

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

 
 这里的豁达光幕和何凯明的论文被之透射率图无是同一个定义,因此不持有可比性。

 
 以大气光幕的公式中,我们看出出大局大气光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

     

 

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