精华内容
下载资源
问答
  • 暗通道去雾

    2014-10-04 23:18:54
    根据博客上的算法自己写的暗通道去雾,效果还行
  • 暗通道去雾算法

    2018-10-30 12:25:48
    何凯明的暗通道去雾算法,算法简单明了,代码清晰易懂。
  • 暗通道去雾MATLAB

    2017-07-25 16:50:05
    MATLAB暗通道去雾函数,完全按何凯明博士论文做的。
  • 在实验中,首先对10000张样本图片采用暗通道去雾算法进行预处理,之后分别使用有无暗通道去雾算法预处理的样本图片训练模型,最后比较这两种模型在不同场景下的模型检测准确率。实验结果表明,使用暗通道去雾预处理...
  • 基于暗通道去雾算法去雾算法简介在人工智能高速发展的今天,CNN涉足领域越来越广,在去雨去雾亦有所成绩。近些年关于去雨去雾,去模糊的算法论文都是基于神经网络实现,然而基于监督学习类的算法需要采集样本,但是...

    基于暗通道去雾算法

    去雾算法简介

    在人工智能高速发展的今天,CNN涉足领域越来越广,在去雨去雾亦有所成绩。近些年关于去雨去雾,去模糊的算法论文都是基于神经网络实现,

    5df3a59869e6e9a59ef02f265d96b3ab.png

    然而基于监督学习类的算法需要采集样本,但是由于实际样本不容易采集需要,通过图像处理叠加雾霾,导致实际效果与真实世界雾霾有较大区别,因此这类算法效果在实验室环境下表现非常棒但是实际应用却表现不够理想。因此作者对去雾去雨类算法还是乐忠于普通图像处理算法。

    本文推荐何凯明大神在09年发布 Single Image Haze Removal Using Dark Channel Prior[1]的论文,该算法原理是基于暗通道的去雾原理,其构建的去雾算法数学模型和真实世界雾霾模型相近,因此能在去雾效果上表现十分理想,由于是采用普通图像处理因此该不依赖任何深度学习框架,容易实现。并且绝大多数场景表现很好,个别场景只需要调整参数就能获得理想效果。

    算法原理

    暗通道 暗通道是何凯明在分析大量雾霾图片后提出来的一个概念。在真实世界相机距离成像物体有远有近,当雾霾浓度分布均匀时近处的物体成像受到雾霾影响小色彩还原高,而远处物体成像色彩还原度就很低,因此远处物体呈现白色亮度高,而近处物体相反亮度较低。故而参考近处物体亮度对大气光强,以及透射率进行建模实现去雾功能。

    原图暗通道图

    c9caa0d9f8cbbf97d98b992ccb97d3f0.png

    6d9fc81893434d67209e51f317d632c3.png

    像素成像建模

    a99fcac8c0f124b8734cb39134c69093.png

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

    最终的恢复公式如下:

    290da49ce78a9bc02c71bce2e934432c.png

    本文在anhenghuang/dehaze[2]代码基础上进行优化改进,并改写成C++版本方便使用

    改进亮度计算 对大气光强计算进行改进采用最亮部分的1%求取平均值作为大气光强。C++代码采用直方图统计方法计算大气光强

        •采用小核 采用小核计算时能够能细腻的处理暗通道边界情况减小暗景物周边白斑现象

    去雾前去雾后优化后

    95ef769bef557abdad0786e67ee5dd22.png

    878e30cfa4c3d882987c09b63e1b9a87.png

    f2e53f16f24d42b7e8afe8b96e46de4a.png

    46cbe6d948e089e13036712f822779c7.png

    c7f60933bdb0f717257bcfb6477027a8.png

    fb7073b6d822f9a8f4dce5b995bbae2b.png

    68f73043b80ffb10d13050f015c71639.png

    1e0ec6f4536b19cc10e5a9641961389e.png

    1abdb9f38185fd3e021fe0adeb15240b.png

    11c7ded9388eeca765cad736f3aee4d6.png

    f9916e3d2642f2f4febe7cf105c3671b.png

    70ad87807e4b0ea6d579ef240c3e2a8f.png

    879e1257eea83a9749a1fca6f18334df.png

    9bca9212d76d7948f287fd159eddba90.png

    be0f680595a11ef66e6925f2b0859364.png

    c9caa0d9f8cbbf97d98b992ccb97d3f0.png

    9f951813c737096748a39bd90c7e69cc.png

    480cb0076f1a0bc6cdcba966539a6c50.png

    a5449f89468b83718bcd2d4b95c32a81.png

    fc3d4651a65c9c54f1bea97cd58c267b.png

    0502a72f6c07e4b1d1a5b3b900c8e594.png

    4241d02100e6c3b1b027866b6cd7346b.png

    2b1ddb191718a38eb7e8cc5c85387fdf.png

    8d44a36caa53adc155248dbc5c5af253.png

    机票直达

    我的去雾算法[3]

    References

    [1] Single Image Haze Removal Using Dark Channel Prior: http://www.jiansun.org/papers/Dehaze_CVPR2009.pdf[2] anhenghuang/dehaze: https://github.com/anhenghuang/dehaze/[3] 我的去雾算法: https://github.com/mm1327/dehazer

    展开全文
  • 暗通道去雾

    2020-03-29 17:39:31
      根据论文的介绍,暗通道去雾算法是基于一个关键的观察:在没有雾霾的室外图像中,大多数局部区域包含一些像素,这些像素在至少一个颜色通道中具有非常低的强度(原文:It is based on a key observation - most ...

    一、算法背景

      暗通道先验去雾算法是大神何恺明2009年发表在CVPR上的一篇论文,还获得了当年的CVPR最佳论文。

      根据论文的介绍,暗通道去雾算法是基于一个关键的观察:在没有雾霾的室外图像中,大多数局部区域包含一些像素,这些像素在至少一个颜色通道中具有非常低的强度(原文:It is based on a key observation - most local patches in haze-free outdoor images contain some pixels which have very low intensities in at least one color channel)。因此,基于这个先验知识,可以直接评估出雾霾的厚度,并恢复出高质量的图像,同时还能得到高质量的深度图。

      在计算机视觉领域,对于雾霾图像的模型定义为:
    在这里插入图片描述

      这个模型可以这样理解,I表示带有雾霾的图像,J表示没有雾霾的图像,t表示透射率,描述了光通过介质投射到摄像头过程中没有被散射的部分,A表示全局大气光照。公式的第一项叫做直接衰减项(direct attenuation),用来描述图像场景中,光在介质中经过衰减的部分;第二项表示大气光照(airlight),它由图像采集装置前方的散射引起,会导致景物色调的偏移。当大气是均匀的时候,透射率t可以表示为如下公式:
    在这里插入图片描述
    其中β是大气的散射系数。这个公式表明,随着景深的增加,场景的亮度呈指数衰减。


      所以,从图像处理的角度讲,雾霾图像模型表示,在RGB颜色空间中,向量A、I、J是共面且终点是共线的,如下图所示:
    在这里插入图片描述
    所以,透射率t就可以表示为:
    在这里插入图片描述
    其中,c ∈ {r, g, b},表示图像颜色通道的下标。

      算法提出的背景模型如此,暗通道去雾算法则是在这个模型上,提出了一个新的先验知识-暗通道先验,从户外雾霾图像中直接估算透射率t。在知乎上看到一张图有点意思哈,应该可以帮助理解,作者见水印:
    在这里插入图片描述

    二、算法原理

    2.1 算法提出

      暗通道先验法是基于一个观察结果:在大多数非天空的区域中,至少有一个颜色通道在某些像素处具有非常低的强度。换句话说,这样一个区域中的最小强度值应该非常低,所以对于一幅图像J,定义了其暗通道去雾算法的模型:
    在这里插入图片描述
    其中,Jc表示无雾图像J三个颜色通道的暗原色,Ω(x)表示以x为中心的局部区域块,作者的观察发现,除了天空区域,Jdark的强度是非常低、趋于0的,Jdark叫做无雾图像J的暗通道,上面的这个观察叫做暗通道先验法。

      论文提到,暗通道的低强度的原因主要有三个:a)、阴影,如城市景观图像中的汽车、建筑物和窗户内部的阴影,或景观图像中的树叶、树木和岩石的阴影等;b)、有颜色的物体或者其表面,任何颜色通道中缺少颜色的对象(例如,绿草/树/植物、红色或黄色的花/叶、蓝色的水面)都会导致暗通道中的值较低;c)、深色物体或表面,深色树干和石头等。由于自然的室外图像通常充满阴影和色彩,这些图像的暗通道真的很暗!

      作者收集了很多图像并计算了他们的暗通道图像,如下:
    在这里插入图片描述
    在这里插入图片描述
    可以看到,暗通道中大约75%的像素值为零,90%的像素强度低于25,大多数暗通道的平均亮度都很低,这意味着只有一小部分室外无霾图像偏离了暗通道先验理论。

    2.2 透射率估算

      论文给出的透射率t的计算公式如下:
    在这里插入图片描述
    其中,ω的值是基于应用的,论文中所有实验的值取0.95。这部分的推导如下:

      首先假设大气光A是给定的、局部区域Ω(x)也是恒定的,对雾霾图像模型取最小值操作(注意这里是对三个通道独立操作):
    在这里插入图片描述
    等价于
    在这里插入图片描述
    对上式三个通道图像取最小值操作,得到:
    在这里插入图片描述
    根据暗通道先验理论,Jdark是趋于0的:
    在这里插入图片描述
    Ac是一个正数,所以可以表示为:
    在这里插入图片描述
    最后,推导得到:
    在这里插入图片描述
    事实上,在这里插入图片描述 是归一化的雾霾图像的暗通道,它直接给出了透射率的估值。暗通道先验法对于天空区域而言不是好的先验模型,但天空的颜色通常与雾霾图像中的大气光A非常相似,所以在天空区域有:
    在这里插入图片描述
    由于天空是无限的并且趋向于零传输,所以不需要事先分离天空区域,可将其与非天空区域的处理等同。同时,论文还引入常数ω(0<ω≤1),为了让处理结果看起来更自然一些,理由是现实生活中,即使是晴天白云,空气中也会存在一些颗粒,看远方的物体还是能够感觉到雾的影响,另外,雾的存在可以让人们感觉到景深的存在,所以需要保留一部分的雾:
    在这里插入图片描述

    2.3 软抠图(Soft Matting)

      作者注意到雾模型公式与图像抠图(抠图…怪怪的翻译)方程形式比较类似,所以才采用了软抠图算法来优化透射率。首先用t(x)来表示精确的透射率,那么估算的透射率与之差值为:
    在这里插入图片描述
    其中,L表示抠图拉普拉斯矩阵(the Matting Laplacian matrix),而λ是一个正则化参数,上式的第一项是一个平滑项,第二项是一个数据项,L矩阵的第(i,j)项定义为:
    在这里插入图片描述
    其中,IiIj是输入图像在ij处像素的颜色;δij表示Kronecker delta,μkΣk表示区域wk内的颜色的均值矩阵和协方差矩阵;U3是一个3×3的单位矩阵;ε是一个正则化参数;|wk|表示区域wk内的像素的个数。

      通过求解下列稀疏线性系统,可以得到最优t
    在这里插入图片描述
    其中,U是和L一样大小的单位矩阵,这里λ取一个很小的值(10-4)。

      我们使用soft matting来细化已经填充了整个图像的粗糙的t,下图c就是soft matting的结果,b是数据项。
    在这里插入图片描述

    2.4 恢复场景亮度

      得到透射率图后,可以根据雾霾模型公式恢复出场景的亮度,但是,当t(x)接近0的时候,直接衰减项J(x)t(x)也是接近0,直接恢复J会容易受噪声干扰,因此需要对t做一个下界t0的限制(论文取0.1),这意味着,在非常密集的雾霾区域,会保留少量的雾霾。最终,J(x)表示为:
    在这里插入图片描述

      由于场景的亮度通常不如大气中的光线明亮,所以去除雾霾后的图像看起来很暗淡,因此一般是对图像做一个曝光调整。

    2.5 估算大气光

      雾霾图像的暗通道很好地近似于雾霾的密集度(见下图(b))。可以利用暗通道来改进大气光估计。首先选择暗通道中最亮的0.1%的像素。这些像素是最不透明的(在下图(b)中以黄线为界)。在这些像素中,选择输入图像I中强度最高的像素作为大气光。这些像素位于下图(a)中的红色矩形中,但这些像素可能不是整个图像中最亮的。这种基于暗通道先验的简单方法比“最亮像素”方法具有更强的鲁棒性。
    在这里插入图片描述

    2.6 实验结果

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
      这些实验结果都是论文里的图像,实际上,后面的研究也提出了soft matting的结果还是有点粗糙的,而且速度也是不够快,所以2011年,作者又提出导向滤波来获得更细腻的结果,导向滤波的运算主要集中在方框滤波(均值滤波),因此可以考虑通过积分图等的方法来优化,而且另一个重要的应用前提是opencv集成了挺多快速算法的,用起来也方便。

    三、参考

    [1] Single Image Haze Removal Using Dark Channel Prior

    知君书记本翩翩,
    为许从戎赴朔边。
    红粉楼中应计日,
    燕支山下莫经年。
    – 唐 杜审言 《赠苏绾书记》

    展开全文
  • 何凯明博士暗通道去雾算法的 matlab 源码,打开文件内的 test.m 文件即可运行。
  • 针对暗通道先验去雾算法大部分的时间都消耗在对透射率的优化上的问题, 对暗通道去雾算法进行了改进, 提出了边缘优化的暗通道去雾算法。使用边缘算子从粗略估计的透射率中提取边缘, 对边缘及周围扩展区域内的像素采用...
  • 暗通道去雾算法 python实现

    千次阅读 2017-09-25 10:58:59
    暗通道去雾算法的python实现

    深度神经网络教你如何图像去雾:

    https://www.leiphone.com/news/201610/RC7IylYdZge7idm9.html

    参考:http://blog.csdn.net/songhhll/article/details/12612681

     

      关于何博士的一些资料和论文,大家可以访问这里:http://research.microsoft.com/en-us/um/people/kahe/

         最开始接触何的这篇论文是在2011年,说实在的那个时候,只是随便浏览了下,看到里面的soft matting过程比较复杂,并且执行速度非常慢,就没有什么大的兴趣。最近又偶尔拾起,仔细研读,觉得论文的推理步骤特别清晰,讲解很到位。恰好适逢浏览到其另外一篇文章《Guided Image Filtering》 ,其中提到了可以用导向滤波来代替soft matting的过程,且速度很快,因此,我对去雾的兴趣算法又大大提高了。  

         本文主要上是对《Single Image Haze Removal Using Dark Channel Prior》的翻译、整理、及部分解释。如果您的英文水平好,建议看原文可能来的更爽些。

        一、论文思想的简单描述 

         首先看看暗通道先验是什么:

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

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

                                        

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

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

          暗通道先验的理论指出:

                                                                           

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

     

    这个有完整代码,有导向滤波器(guided filter)代码:

     

    http://blog.csdn.net/chongshangyunxiao321/article/details/50997111

     

     

    python3版本:

     

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from PIL import Image
    from guidedfilter import *
    
    def getDark(input_img, filter, frame):
      """get dark image from the input image"""
      size = input_img.size
      output = []
    
      for x in range(size[1]):
        temp = []
        for y in range(size[0]):
          temp.append(min(input_img.getpixel((y, x))))
    
        output.append(temp)
    
      output = filter2d(output, filter, frame)
    
      output_img = Image.new('L', size)
    
      for x in range(size[1]):
        for y in range(size[0]):
          output_img.putpixel((y, x), output[x][y])
    
      return output_img
    
    def getLight(srcImage, darkImage, cut):
      """get atmospheric light from the picture"""
      size = darkImage.size
      light = []
    
      for x in range(size[0]):
        for y in range(size[1]):
          light.append(darkImage.getpixel((x, y)))
    
      light.sort()
      light.reverse()
    
      threshold = light[int(cut * len(light))]
    
      atmosphere = {}
    
      for x in range(size[0]):
        for y in range(size[1]):
          if darkImage.getpixel((x, y)) >= threshold:
            atmosphere.update({(x, y): sum(srcImage.getpixel((x, y))) / 3.0})
    
      pos = sorted(atmosphere.items(), key = lambda item: item[1], reverse = True)[0][0]
    
      return srcImage.getpixel(pos)
    
    def getTransmission(input_img, light, omiga):
      """get transmission from the picture"""
      size = input_img.size
      output = []
    
      for x in range(size[1]):
        temp = []
        for y in range(size[0]):
          temp.append(min(input_img.getpixel((y, x))) / float(min(light)))
    
        output.append(temp)
    
      transmission = []
    
      for x in range(size[1]):
        temp = []
        for y in range(size[0]):
          temp.append(1 - omiga * minimizeFilter(output, (x, y), (10, 10)))
    
        transmission.append(temp)
    
      return transmission
    
    def getRadiance(input_img, transmission, light, t0):
      """get radiance from the picture"""
      size = input_img.size
      output = Image.new('RGB', size)
    
      for x in range(size[1]):
        for y in range(size[0]):
          r, g, b = input_img.getpixel((y, x))
    
          r = int((r - light[0]) / float(max(t0, transmission[x][y])) + light[0])
          g = int((g - light[1]) / float(max(t0, transmission[x][y])) + light[1])
          b = int((b - light[2]) / float(max(t0, transmission[x][y])) + light[2])
    
          output.putpixel((y, x), (r, g, b))
    
      return output
    
    def ensure(n):
      if n < 0:
        n = 0
    
      if n > 255:
        n = 255
    
      return int(n)
    
    if __name__ == '__main__':
      image = Image.open('image/huoche.jpg')
      image = image.convert('RGB')
    
      dark = getDark(image, minimizeFilter, (10, 10))
    
      dark.save('3_dark.png')
    
      light = getLight(image, dark, 0.001)
    
      transmission = getTransmission(image, light, 0.9)
    
      tranImage = Image.new('L', image.size)
      grayImage = image.convert('L')
    
      for x in range(image.size[0]):
        for y in range(image.size[1]):
          tranImage.putpixel((x, y), int(transmission[y][x] * 255))
    
      guided = guidedFilter(grayImage, tranImage, 25, 0.001)
    
      guidedImage = Image.new('L', image.size)
    
      for x in range(image.size[0]):
        for y in range(image.size[1]):
          guidedImage.putpixel((x, y), ensure(guided[y][x]))
          guided[y][x] /= 255.0
    
      #guidedImage.show()
      guidedImage.save('3_guided.png')
    
      output = getRadiance(image, guided, light, 0.1)
    
      output.save('3_haze.png')

     

     

     

     

     

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from PIL import Image
    import numpy as np
    
    def filter2d(input_img, filter, frame):
      """filter of the 2-dimension picture"""
      size = len(input_img), len(input_img[0])
      output = []
    
      for i in range(size[0]):
        temp = []
        for j in range(size[1]):
          temp.append(filter(input_img, (i, j), frame))
    
        output.append(temp)
    
      return output
    
    def minimizeFilter(input_img, point, size):
      """minimize filter for the input image"""
      begin = np.int32((point[0] - size[0] / 2, point[0] + size[0] / 2 + 1))
      end = np.int32((point[1] - size[1] / 2, point[1] + size[1] / 2 + 1))
    
      l = []
    
      for i in range(*begin):
        for j in range(*end):
          if (i >= 0 and i < len(input_img)) and (j >= 0 and j < len(input_img[0])):
            l.append(input_img[i][j])
    
      return min(l)
    
    def convertImageToMatrix(image):
      size = image.size
      out = []
    
      for x in range(size[1]):
        temp = []
        for y in range(size[0]):
          temp.append(image.getpixel((y, x)))
    
        out.append(temp)
    
      return out
    
    def boxFilter(im, radius):
      """box filter for the image of the radius"""
      height, width = len(im), len(im[0])
    
      imDst = []
      imCum = []
    
      for x in range(height):
        imDst.append([0.0] * width)
        imCum.append([0.0] * width)
    
      #cumulative sum over Y axis
      for i in range(width):
        for j in range(height):
          if j == 0:
            imCum[j][i] = im[j][i]
          else:
            imCum[j][i] = im[j][i] + imCum[j - 1][i]
    
      #difference over Y axis
      for j in range(radius + 1):
        for i in range(width):
          imDst[j][i] = imCum[j + radius][i]
    
      for j in range(radius + 1, height - radius):
        for i in range(width):
          imDst[j][i] = imCum[j + radius][i] - imCum[j - radius - 1][i]
    
      for j in range(height - radius, height):
        for i in range(width):
          imDst[j][i] = imCum[height - 1][i] - imCum[j - radius - 1][i]
    
      #cumulative sum over X axis
      for j in range(height):
        for i in range(width):
          if i == 0:
            imCum[j][i] = imDst[j][i]
          else:
            imCum[j][i] = imDst[j][i] + imCum[j][i - 1]
    
      #difference over X axis
      for j in range(height):
        for i in range(radius + 1):
          imDst[j][i] = imCum[j][i + radius]
    
      for j in range(height):
        for i in range(radius + 1, width - radius):
          imDst[j][i] = imCum[j][i + radius] - imCum[j][i - radius - 1]
    
      for j in range(height):
        for i in range(width - radius, width):
          imDst[j][i] = imCum[j][width - 1] - imCum[j][i - radius - 1]
    
      return imDst
    
    def dot(matrix1, matrix2, operation):
      """dot operation for the matrix1 and matrix2"""
      out = []
      size = len(matrix1), len(matrix1[0])
    
      for x in range(size[0]):
        temp = []
        for y in range(size[1]):
          temp.append(operation(matrix1[x][y], matrix2[x][y]))
    
        out.append(temp)
    
      return out
    
    def guidedFilter(srcImage, guidedImage, radius, epsilon):
      """guided filter for the image
         src image must be gray image
         guided image must be gray image
      """
    
      size = srcImage.size
      src = convertImageToMatrix(srcImage)
      guided = convertImageToMatrix(guidedImage)
    
      one = []
    
      for x in range(size[1]):
        one.append([1.0] * size[0])
    
      n = boxFilter(one, radius)
    
      plus = lambda x, y: x + y
      minus = lambda x, y: x - y
      multiple = lambda x, y: x * y
      divide = lambda x, y: x / y
    
      meanI = dot(boxFilter(src, radius), n, divide)
      meanP = dot(boxFilter(guided, radius), n, divide)
      meanIP = dot(boxFilter(dot(src, guided, multiple), radius), n, divide)
    
      covIP = dot(meanIP, dot(meanI, meanP, multiple), minus)
    
      meanII = dot(boxFilter(dot(src, src, multiple), radius), n, divide)
      varI = dot(meanII, dot(meanI, meanI, multiple), minus)
    
      epsilonMatrix = []
    
      for x in range(size[1]):
        epsilonMatrix.append([epsilon] * size[0])
    
      a = dot(covIP, dot(varI, epsilonMatrix, plus), divide)
      b = dot(meanP, dot(a, meanI, multiple), minus)
    
      meanA = dot(boxFilter(a, radius), n, divide)
      meanB = dot(boxFilter(b, radius), n, divide)
    
      return dot(dot(meanA, src, multiple), meanB, plus)
    
    if __name__ == '__main__':
      a=(-5,6)
      import numpy as np
      a=np.int32(a)
      for i in range(*a):
        print(i)
    

     

     

     

     

     

    原文:http://blog.csdn.net/zmshy2128/article/details/53443227

    这个代码有问题,下面一行报错了:

    res = np.minimum(I, I[[0] + range(h - 1), :])

     

     

        何凯明博士的去雾文章和算法实现已经漫天飞了,我今天也就不啰里啰唆,直接给出自己python实现的完整版本,全部才60多行代码,简单易懂,并有简要注释,去雾效果也很不错。

        在这个python版本中,计算量最大的就是最小值滤波,纯python写的,慢,可以进一步使用C优化,其他部分都是使用numpy和opencv的现成东东,效率还行。

    import argparse
    import time
    
    import cv2
    import numpy as np
    
    
    def zmMinFilterGray(src, r=5):
        '''最小值滤波,r是滤波器半径'''
        '''if r <= 0:
            return src
        h, w = src.shape[:2]
        I = src
        res = np.minimum(I  , I[[0]+range(h-1)  , :])
        res = np.minimum(res, I[range(1,h)+[h-1], :])
        I = res
        res = np.minimum(I  , I[:, [0]+range(w-1)])
        res = np.minimum(res, I[:, range(1,w)+[w-1]])
        return zmMinFilterGray(res, r-1)'''
        return cv2.erode(src, np.ones((2 * r + 1, 2 * r + 1)))  # 使用opencv的erode函数更高效
    
    
    def guidedfilter(I, p, r, eps):
        '''引导滤波,直接参考网上的matlab代码'''
        height, width = I.shape
        m_I = cv2.boxFilter(I, -1, (r, r))
        m_p = cv2.boxFilter(p, -1, (r, r))
        m_Ip = cv2.boxFilter(I * p, -1, (r, r))
        cov_Ip = m_Ip - m_I * m_p
    
        m_II = cv2.boxFilter(I * I, -1, (r, r))
        var_I = m_II - m_I * m_I
    
        a = cov_Ip / (var_I + eps)
        b = m_p - a * m_I
    
        m_a = cv2.boxFilter(a, -1, (r, r))
        m_b = cv2.boxFilter(b, -1, (r, r))
        return m_a * I + m_b
    
    
    def getV1(m, r, eps, w, maxV1):  # 输入rgb图像,值范围[0,1]
        '''计算大气遮罩图像V1和光照值A, V1 = 1-t/A'''
        V1 = np.min(m, 2)  # 得到暗通道图像
        V1 = guidedfilter(V1, zmMinFilterGray(V1, 7), r, eps)  # 使用引导滤波优化
        bins = 2000
        ht = np.histogram(V1, bins)  # 计算大气光照A
        d = np.cumsum(ht[0]) / float(V1.size)
        for lmax in range(bins - 1, 0, -1):
            if d[lmax] <= 0.999:
                break
        A = np.mean(m, 2)[V1 >= ht[1][lmax]].max()
    
        V1 = np.minimum(V1 * w, maxV1)  # 对值范围进行限制
    
        return V1, A
    
    
    def deHaze(m, r=81, eps=0.001, w=0.95, maxV1=0.80, bGamma=False) -> object:
        Y = np.zeros(m.shape)
        V1, A = getV1(m, r, eps, w, maxV1)  # 得到遮罩图像和大气光照
        for k in range(3):
            Y[:, :, k] = (m[:, :, k] - V1) / (1 - V1 / A)  # 颜色校正
        Y = np.clip(Y, 0, 1)
        if bGamma:
            Y = Y ** (np.log(0.5) / np.log(Y.mean()))  # gamma校正,默认不进行该操作
        return Y
    
    # cap = cv2.VideoCapture(0)
    cap = cv2.VideoCapture("quwu.mp4")
    
    count = 0
    ok_count = 0
    
    need_save = False
    f_index = 0
    
    while True:
        ret, img_raw = cap.read()
    
        cv2.imshow("img_1", img_raw)
    
        img_1=img_raw.astype(np.float32) / 255
        img_raw = (img_1) ** 0.5
        img_show=img_raw*255
        img_show=img_show.astype(np.uint8)
        cv2.imshow("img_raw", img_show)
    
        img = deHaze(img_1) * 255
    
    
        img = np.clip(img, 0, 255)
        img_2 = img.astype(np.uint8)
    
        cv2.imshow("an1", img_2)
    
    
        start=time.time()
    
        img = deHaze(img_raw) * 255
        print("an2",time.time()-start)
    
        img = np.clip(img, 0, 255)
        img_2 = img.astype(np.uint8)
    
    
        cv2.imshow("an2",img_2)
        cv2.waitKey(1)
    

     

     

    展开全文
  • 本程序采用何凯明博士的暗通道去雾原理,编译环境VS2008 + opencv2.4.6 编程语言C++,内附整个工程文件,配置好环境可直接运行。
  • 暗通道去雾代码及改进代码

    热门讨论 2014-06-27 10:29:32
    暗通道去雾代码及改进代码,拥有对色彩方面的改进
  • 本算法是基于何凯明暗通道去雾算法,编码的MATLAB代码,对比度强的图片效果明显,还可在主函数中调整高低频参数来调整实验结果。
  • 暗通道去雾原理

    2018-10-28 19:30:56
    基于暗通道去雾算法,亲测可用。测试平台为:visual studio2015+opencv
  • 在接下来的博客中,我会分步介绍各个图像去雾算法的研究和对比,在这里,首先介绍最经典的何凯明博士的暗通道去雾算法了,后面的博客有关于何博士算法的改进,有其他去雾算法的测试对比。 暗通道去雾算法 暗通道...

    图像去雾最好的算法原型最好的莫过于何凯明博士的论文--好好阅读,必有灵感

    在接下来的博客中,我会分步介绍各个图像去雾算法的研究和对比,在这里,首先介绍最经典的何凯明博士的暗通道去雾算法了,后面的博客有关于何博士算法的改进,有其他去雾算法的测试对比。

    暗通道去雾算法

    暗通道去雾算法,在其他博客都有详细的介绍,在这里我也是借鉴其他各位总结的东西,写点内容。

           一、实验原理

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

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

                                                                                              (1)

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

          暗通道先验的理论指出:

                                                                                                                             (2)

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

                                                                                                     (3)

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

                                                                                       (4)

     如上所述,上标C表示R/G/B三个通道的意思。首先假设在每一个窗口内透射率t(x)为常数,定义它为 \widetilde{t}(x),并且A值已经给定,然后对式(4)两边求两次最小值运算,得到下式:

                    (5)

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

                                                                              (6)

     因此,可推导出:

                                                                                                     (7)

     把式(7)带入式(5)中,得到:

                                                                              (8)

     这就是透射率 \widetilde{t}(x) 的预估值。

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

                                                                             (9)

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

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

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

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

         到这一步,我们就可以进行无雾图像的恢复了。由式(3)可知: J = ( I - A)/t + A  ,现在I,A,t都已经求得了,因此,完全可以进行J的计算。当投射图t 的值很小时,会导致J的值偏大,从而使淂图像整体向白场过度,因此一般可设置一阈值T0,当t值小于T0时,令t=T0,本文中所有效果图均以T0=0.1为标准计算。

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

                                                                                              (10)

    二、实验步骤

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

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

    3、由(9)式算出投射图。

    具体代码如下:

    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);
    
    }

     三、最终实验结果

    可以清楚的看出来,左边的是原图,右边是去雾后的图片,去雾效果还算理想。

    另外附上何博士的原文地址:

    http://xueshu.baidu.com/s?wd=paperuri%3A%2882db63209f43fcf5add7b429e6b37e23%29&filter=sc_long_sign&tn=SE_xueshusource_2kduw22v&sc_vurl=http%3A%2F%2Fieeexplore.ieee.org%2Fxpls%2Ficp.jsp%3Farnumber%3D5206515&ie=utf-8&sc_us=6975395480982385039

    展开全文
  • opencv C++ 实现暗通道去雾
  • 暗通道去雾算法Opencv实现

    热门讨论 2013-08-23 22:24:19
    用OpenCV2.3.1实现的暗通道去雾算法。压缩文件是一个工程文件,解压后工程文件内附“说明文档.txt”粘贴代码即可使用.本人练手拙作,注释比较详细,工程内另附Matlab代码,整个OpenCV代码的实现过程依据的就是那段...
  • 基于何恺明的暗影通道去雾实现,matlab源码全上传,直接可用。
  • 暗通道去雾matlab

    2017-10-23 11:22:10
    基于何凯明博士的去雾论文,matlab实现,里面包含了测试程序及图像
  • 1. 暗通道去雾方法 这种方法目前研究的比较多。虽然大家认为去雾已经被研究烂了,但是从工程实践的角度看,仍然存在很多问题。却不说暗通道先验对天空本身的不合理假设,就单说时间复杂度。对于视频图像处理来说,...
  • 瞎搞系列-暗通道去雾

    2018-03-10 20:27:12
    瞎搞系列-暗通道去雾1. 算法背景基于暗通道先验的去雾算法实际上是一种统计算法,发现了无雾图像中局部存在一些像素,这些像素至少有一个颜色通道的亮度值非常非常低但是当图像区域白色的时候,这种算法则存在缺陷2....
  • 基于暗通道先验的去雾算法,去雾算法目前也有着众多其他的方式,不过我所接触的,很多都是以这个为基础,因此,先弄会这个为研究其他的去雾算法能奠定坚实的基础。
  • 暗通道去雾(dark channel defog)算法封装成类,调用方便,main.cpp中给出了类的实例用法
  • C#完成图片暗通道去雾算法 public class DefogHelper { public DefogHelper() { } /// /// 完成功用:完成基于暗通道的去雾算法。(假如要用32位的将ImageMaster_64.dll改成ImageMaster_32.dll即可) /// /// 图像...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 434
精华内容 173
关键字:

暗通道去雾