• 暗通道图像去雾


    一、          实验原理

    在绝大多数非天空的局部区域里,某一些像素总会有至少一个颜色通道有很低的值。换言之,该区域光强度的最小值是个很小的数。

      我们给暗通道一个数学定义,对于任意的输入图像J,其暗通道可以用下式表达:

    clip_image002[9]

          式中Jc表示彩色图像的每个通道 Ω(x)表示以像素X为中心的一个窗口。 

       式(5)的意义用代码表达也很简单,首先求出每个像素RGB分量中的最小值,存入一副和原始图像大小相同的灰度图中,然后再对这幅灰度图进行最小值滤波,滤波的半径由窗口大小决定,一般有WindowSize = 2 * Radius + 1;         

          暗通道先验的理论指出:

    clip_image004[9]

         实际生活中造成暗原色中低通道值主要有三个因素:a)汽车、建筑物和城市中玻璃窗户的阴影,或者是树叶、树与岩石等自然景观的投影;b)色彩鲜艳的物体或表面,在RGB的三个通道中有些通道的值很低(比如绿色的草地/树/植物,红色或黄色的花朵/叶子,或者蓝色的水面);c)颜色较暗的物体或者表面,例如灰暗色的树干和石头。总之,自然景物中到处都是阴影或者彩色,这些景物的图像的暗原色总是很灰暗的。

    首先,在计算机视觉和计算机图形中,下述方程所描述的雾图形成模型被广泛使用:

    clip_image006[9]

    其中,I(X)就是我们现在已经有的图像(待去雾的图像),J(x)是我们要恢复的无雾的图像,A是全球大气光成分, t(x)为透射率。现在的已知条件就是I(X),要求目标值J(x),显然,这是个有无数解的方程,因此,就需要一些先验了。

      将式(1)稍作处理,变形为下式:

    clip_image008[9]

        如上所述,上标C表示R/G/B三个通道的意思。

        首先假设在每一个窗口内透射率t(x)为常数,定义他为clip_image010[14],并且A值已经给定,然后对式(7)两边求两次最小值运算,得到下式:

    clip_image012[9]

        上式中,J是待求的无雾的图像,根据前述的暗原色先验理论有:

    clip_image014[9]

         因此,可推导出:

    clip_image016[9]

        把式(10)带入式(8)中,得到:

    clip_image018[9]

        这就是透射率clip_image010[15]的预估值。

        在现实生活中,即使是晴天白云,空气中也存在着一些颗粒,因此,看远处的物体还是能感觉到雾的影响,另外,雾的存在让人类感到景深的存在,因此,有必要在去雾的时候保留一定程度的雾,这可以通过在式(11)中引入一个在[0,1] 之间的因子,则式(11)修正为:

    clip_image020[9]

         本文中所有的测试结果依赖于:  ω=0.95

         上述推论中都是假设全球大气光A值时已知的,在实际中,我们可以借助于暗通道图来从有雾图像中获取该值。具体步骤如下:

         1 从暗通道图中按照亮度的大小取前0.1%的像素。

             2 在这些位置中,在原始有雾图像I中寻找对应的具有最高亮度的点的值,作为A值。

         到这一步,我们就可以进行无雾图像的恢复了。由式(1)可知:  J = ( I - A)/t + A  ,现在I,A,t都已经求得了,因此,完全可以进行J的计算。

         当投射图t 的值很小时,会导致J的值偏大,从而使淂图像整体向白场过度,因此一般可设置一阈值T0,当t值小于T0时,令t=T0,本文中所有效果图均以T0=0.1为标准计算。

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

    clip_image022[9]

     

    二、实验步骤

    1、找出每个像素的RGB三通道的最小值、形成图像的暗通道图像。

    2、在暗通道图片中每个像素的周围15*15的矩形中找像素最小的值,作为该像素的值。

    3、由12式算出投射图。

    具体代码如下:

    void dark_channel(unsigned char* des,const unsigned char* img,int width,int height)

    {

             int A = 0;

             for(int y = 0; y < height; y++)

                       {

                                for(int x = 0; x < width; x++)

                                {

                                         int B = img[y * width * 3 + x * 3 + 0];

                                         int G = img[y * width * 3 + x * 3 + 1];

                                         int R = img[y * width * 3 + x * 3 + 2];

                                         if(B<G)

                                                   des[y * width + x]=B;

                                         else

                                                   des[y * width + x]=G;

                                         if(R<des[y * width + x])

                                                   des[y * width + x]=R;

                                }

                       }

             for(int y = 0; y < 5; y++)

                       {

                                for(int x = 0; x < width; x++)

                                {

                                                   if(des[y * width + x]>A)

                                                            A=des[y * width + x];

                                }

                       }                

             int patch= 6;

             printf("A的值%d",A);

             double w=0.95*A/255;

             unsigned char* ocl = new unsigned char[width * height];

             memcpy(ocl,des,width * height);

             for(int y = patch; y < height-patch; y++)

                       {

                                for(int x = patch; x < width-patch; x++)

                                {

                                         for(int i = -patch; i < patch+1; i++)

                                         {

                                                   for(int j = -patch; j < patch+1; j++)

                                                   {

                                                            if(des[(y + i) * width + (x + j)]<ocl[y * width + x])

                                                                     ocl[y * width + x]=des[(y + i) * width + (x + j)];

                                                   }

                                         }

                                         ocl[y * width + x]=int(255-w*ocl[y * width + x]);

                                }

                       }

             memcpy(des,ocl,width * height);

    }

    二、          实验结果

    clip_image024[9]clip_image026[9]

  • 相关阅读:
    微信公众号开发的经验与坑
    微信公众号开发经验总结
    微信H5中禁止分享好友及分享到朋友圈的方法
    js 实现纯前端将数据导出excel两种方式,亲测有效
    JavaScript数组的一些方法、数学对象、定时器
    几种动态轨迹可视化效果实现方案-echarts、mapv、deck.gl
    前端大牛的博客收集
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/hustlx/p/5264607.html
Copyright © 2020-2023  润新知