精华内容
下载资源
问答
  • 基于暗通道先验的去雾算法,去雾算法目前也有着众多其他的方式,不过我所接触的,很多都是以这个为基础,因此,先弄会这个为研究其他的去雾算法能奠定坚实的基础。
  • 何凯明博士的去雾文章和算法实现已经漫天飞了,我今天也就不啰里啰唆,直接给出自己python实现的完整版本,全部才60多行代码,简单易懂,并有简要注释,去雾效果也很不错。 在这个python版本中,计算量最大的就是...
  • 暗通道去雾MATLAB

    2017-07-25 16:50:05
    MATLAB暗通道去雾函数,完全按何凯明博士论文做的。
  • 暗通道去雾

    2018-06-16 14:14:02
    基于matlab的图像去雾算法。I(X)就是我们现在已经有的图像(待去雾的图像),J(x)是我们要恢复的无雾的图像,A是全球大气光成分,t(x)为透射率。现在的已知条件就是I(X),要求目标值J(x)。显然,根据基本的代数知识...
  • 何凯明博士暗通道去雾算法的 matlab 源码,打开文件内的 test.m 文件即可运行。
  • 暗通道去雾+导向滤波

    2016-06-21 21:42:20
    我用的是VS2010+opencv2.49 当然可以根据自己的环境配置一下就可以了。代码里面用的是三通道去雾,效果不错。 效果比单通道好一点。 比softmating 稍微差一点点(看不怎么出来),但是速度比softmating快很多倍。
  • 针对暗通道先验去雾算法大部分的时间都消耗在对透射率的优化上的问题, 对暗通道去雾算法进行了改进, 提出了边缘优化的暗通道去雾算法。使用边缘算子从粗略估计的透射率中提取边缘, 对边缘及周围扩展区域内的像素采用...
  • 暗通道去雾算法Opencv实现

    热门讨论 2013-08-23 22:24:19
    用OpenCV2.3.1实现的暗通道去雾算法。压缩文件是一个工程文件,解压后工程文件内附“说明文档.txt”粘贴代码即可使用.本人练手拙作,注释比较详细,工程内另附Matlab代码,整个OpenCV代码的实现过程依据的就是那段...
  • 包含了暗通道去雾的基础代码和一些测试图像
  • 基于暗通道先验,实现暗通道去雾的快速算法
  • 暗通道去雾

    千次阅读 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

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

    展开全文
  • darkprior_暗通道去雾快速算法_暗通道去雾_暗通道算法_暗通道_furtherzju.zip
  • matlab程序,基于暗通道先验的去雾算法,未经过导向滤波,能够对雾天图像进行去雾
  • 数字图像处理-暗通道去雾与matlab代码实现
  • 暗通道去雾matlab

    2017-10-23 11:22:10
    基于何凯明博士的去雾论文,matlab实现,里面包含了测试程序及图像
  • 本程序采用何凯明博士的暗通道去雾原理,编译环境VS2008 + opencv2.4.6 编程语言C++,内附整个工程文件,配置好环境可直接运行。
  • darkprior_暗通道去雾快速算法_暗通道去雾_暗通道算法_暗通道_furtherzju_源码.zip
  • 暗通道去雾研究笔记

    千次阅读 2020-11-11 19:29:03
    去雾 基于图像增强 不对图像降质本质原因进行研究,认为有雾图像模糊是图像对比度下降。 通过提高对比度来改善图像效果。 该方法不能彻底去除雾气,可能会有雾气残剩、细节模糊、色彩比例失衡等现象。 主要方法包括...

    去雾

    基于图像增强

    不对图像降质本质原因进行研究,认为有雾图像模糊是图像对比度下降。

    通过提高对比度来改善图像效果。

    该方法不能彻底去除雾气,可能会有雾气残剩、细节模糊、色彩比例失衡等现象。

    主要方法包括:直方图均衡化、小波变换等等。

    直方图均衡化

    优点:简单可行,单景深图像复原效果好。局部细节增强。

    缺点:难以反映多景深图像中景深变化,局部块效应出现。

    小波变换

    通过多尺度,图像对比度增强。认为雾对图像高频部分影响较小,对高频部分增强,低频部分削弱。

    优点:对图像细节增强。

    缺点:光照过亮或过暗以及不均匀的现响无法处理。

    边缘增强的局限性可由曲波变换弥补。

    视网膜理论去雾

    利用视觉系统颜色不变性,对因雾气影响而削弱的光照增强,进而使得图像得以增强。

    同态滤波

    针对光照不匀,课对复原出现的黑斑暗影进行消除,对图像原貌保持。两次傅里叶变换,占用内存空间。

    基于图像复原

    对雾气形成探究原因,依靠数学模型,通过估计模型中的参数,利用逆运算,获得与真实图像相近的估计值,从而得到复原后的清晰图像。

    该方法回复过程较为复杂且费时。

    主要方法包括:利用偏微分方程,利用景深估计,利用先验信息

    偏微分方程

    借助大气散射模型,对户外图像局部去雾的能量进行最优化,推导偏微分方程。求阶复原退化前清晰图像。

    视觉效果有明显改善。但计算量过大,需要用户交互,包括获取精神信息以及对大气散射系数修改等。

    景深信息

    景深已知。基于物理模型提高对比度,利用高斯函数,预测光路。

    提高图像清晰度,但需要条件较多,不能自适应,不能用于实时图像处理。

    先验信息

    Tan

    最大化局部对比度去雾方法。无雾图像比有雾图像对比度更明显。

    Fattal

    物体表面反射率和传输值局部统计不相关。

    暗通道先验

    收集大量无雾时清晰图像,发现可利用暗原色统计规律识别雾气浓度。

    可对局部估计雾气浓度,并对颜色修复。

    去雾后图像自然,颜色失真小,清晰度高。

    运算效率低。

    何凯明暗通道去雾

    博客链接

    过程讲解

    opencv部分实现

    优化策略

    概述

    先验知识,无雾图像的暗通道大部分区域的像素值很低,趋近于0。而有雾图像的暗通道图亮度比无雾图像大很多。

    原因

    *1.图像中存在一些颜色鲜艳的物体,比如鲜艳的花朵,树木等,这些景物的特点是 RGB 三通道中有一个通道像素值很高,其他两个通道像素值很低,*这样就会造成求取暗通道时,暗通道图像中该区域各个通道像素值很低。
    2.图像中有些物体因为反射的都是比较暗的光线,造成看上去比较灰暗,不明亮,对其求取暗通道时,三通道的像素值都比较低,该区域像素值就会比较低。
    3.图像中存在一些树木,高山等自然景物和建筑物的一些阴影,该阴影区域像素值很低,求取暗通道后,各个通道的像素值也很低。

    去雾过程

    优化内容摘自:

    求取暗通道

    两次最小值滤波,以此求取有雾图像中每个像素点的RGB最小值;第二次最小值滤波对球的的暗原色图在邻域范围内再进行一次最小值滤波。

    优化

    下采样与双线性插值。分块,每块对应一个透射率,而非逐像素估计,降低事件复杂度。

    滤波窗口大小调节。原固定滤波半径,可根据不同图像场景等选取不同滤波半径。

    估计大气光

    有雾图像求取暗通道,取暗通道中像素值从高到低0.1%的像素点投射到原始图像,找到位置后选取密集区域最大像素点的像素值。

    但如图像中存在大面积白色建筑物时,估计出的透射率不准确。

    优化

    原始有雾图像对应时选取该区域像素点平均值,且增加阈值。

    估计透射率

    需要保留一定程度的雾。作者加入了系数w。

    景深突变处边缘透射率的估计会出现偏差,使得复原后无雾图像在边缘细节表现较为突兀。会产生光晕、白边效应。

    在天空、水面以及白色物体大面积明亮区域,暗原色先验的规律失效,这些区域透射率了估计出现误差,估计值偏小,使得色彩出现明显失真。

    优化透射率

    景深突变处产生 白边。对边缘细节优化,软抠图和导向滤波的方法。

    明亮区域失真处,引入容差机制,对明亮区域进行透射率调整。

    优缺点

    优点

    对大多数自然场景图像有较好的效果。

    实现原理简单,复原效果好,使用场景广泛。

    缺点

    • 算法效率低。softmatting方法实现投射图精细化太过耗时。

    • 色斑色块效应。当像素点的强度接近大气光值时,去雾的图像出现局部的色斑、色偏效应。

      低对比度大片天空的区域可能完全失效。较远天空处出现块效应。

    • 图像亮度降低。

    论文与期刊(各种改进)

    何凯明等提出用引导滤波代替Soft Matting算法对传输图进行优化,但该算法在恢复天空区域的过程中容易出现颜色失真现象。

    Tarel等对图像进行白平衡后,采用中值滤波的变形形式估计大气耗散函数,但该方法易产生光晕现象。

    结合混合双边滤波、均值滤波的暗通道先验算法,以及多尺度Retinex算法等,以提高算法的有效性。

    1.结合导向滤波

    何博士之后提出了导向滤波器改进去雾效果的算法。

    导向滤波

    选择性滤波,与高斯滤波、双边滤波相比,具有导向性。通过输入一幅图像(矩阵)作为导向图,由此滤波器知道哪些地方是边缘,从而保护边缘。再达到滤波的同时,保持边缘细节。

    Guided Filter

    2.结合双边滤波

    软抠图细化介质透射率耗时过多,且景深突变处出现白边,可采用最大值滤波方法对被低估的暗像素点进行修复。

    双边滤波

    非线性滤波方法。与高斯滤波相似,也利用局部加权原理,但有明显区别。双边滤波加权系数由像素间空间距离之差(空间临近度因子)和像素之间的灰度值只差(灰度相似度因子)两个部分组成。

    双边滤波对输入图像进行平滑处理的同时能保持图像的边缘细节信息。对输入图像进行双边滤波后,图像中的每个像素的灰度值是等于其邻域范围内像素的加权平均。加权系数是空间临近度因子和灰度相似度因子的乘积。

    透射率细化

    双边滤波器主要在透射率细化处理时进行改进。先进行最大值滤波,再进行双边滤波,以便更好保持图像边缘部分。

    其他

    大气光A的改进:在暗通道图中取灰度值在区间[220,255]的像素点一是能够解决处理后图像的色偏及天空色斑的问题;二是直接取强度值在[220,255]的像素点,避免了在编码实现中使用排序的方法找出前0. 1%的最亮像素点,降低了计算时间复杂度。

    3.结合K均值

    从暗通道模型出发,首先利用双暗通道拟合进行投射图估计,再采用K均值举类树算法对有雾图像进行区域分类,再针对天空区域估计出大气光强度的算法。

    双暗通道

    邻域15*15的范围同时,选取小邻域对原图进行最小值滤波。得到两个暗通道以及两个相应的透射率,通过线性拟合,从而得到最终的透射率。

    双暗通道你和代替软抠图对透射率进行优化。

    K均值

    K均值聚类方法将有雾图像分割为天空类(包括雾最浓区域)和非天空类。在估计大气光强度A时,在求得的天空区域或雾最浓区域求取原图最大像素值作为大气光A值。

    优点

    增强图像细节信息,降低计算复杂度,提升大气光强度估计值的准确型,有效抑制了高亮区域的失真。

    4.基于亮通道和暗通道结合

    优点

    解决有雾图像恢复时天空区域颜色失真问题。恢复图像细节和颜色,提高图像的视觉效果,优于多尺度Retinex图像去雾算法。

    过程

    1. 对大气光散射模型改进
    2. 运用亮通道先验和暗通道先验结合的方法估计大气光值和透射率
    3. 根据加权引导滤波算法估计透射率,恢复无雾图像
    4. 仿真验证

    亮通道先验

    在大多数的模糊图像中,某些像素总会有至少一个颜色通道具有较大的强度。像素点x处的亮通道强度趋近于无雾图像的大气光强度。

    大气光强度A,不使用固定值A,使用A(x)。根据未知变化而变化,利用亮通道先验求得。

    从亮通道和暗通道两个方面进行大气光值的估计,从而获取A(x)。

    A(x) = alpha * Alight(x) + belta * A0

    两个调整因子来调整大气光。且两值之和小于1.0。求A0时使用平均值。

    加权导向滤波

    5.基于暗通道先验和Retinex理论

    图像增强:Retinex算法

    从大气散射模型出发, 利用暗通道先验知识, 通过灰度开运算估计大气光的取值,同时得到介质传输率的初始估计,并对大气光照进行白平衡处理,从而简化大气散射模型;

    其次, 利用Retinex理论,通过高斯卷积实现介质传输率的粗略估计,并对其灰度值进行线性搬移;

    然后,融合介质传输率的初始估计和粗略估计,利用快速联合双边滤波进行边缘优化,同时对雾图中大片天空区域的介质传输率进行动态修正;

    最后, 利用简化大气散射模型, 通过色调调整获得较好的去雾效果。

    特点

    结合图像增强和图像复原的思想,处理速度较快,有效复原清晰度和对比度。

    6.基于区域对比度约束

    该算法首先将原始图像分割成适当的明暗双区域,并计算相应的对比度比值;

    再使用基于中值滤波的暗通道去雾算法处理图像暗区域部分;

    最后利用亮度精确控制的双直方图均衡算法,以最大程度保持区域对比度不变为约束条件,修正图像较亮区域的亮度分布。

    在信息熵值、平均梯度和亮度标准差方面有明显增益。更多显现细节特征。

    展开全文
  • 本算法是基于何凯明暗通道去雾算法,编码的MATLAB代码,对比度强的图片效果明显,还可在主函数中调整高低频参数来调整实验结果。
  • 暗通道去雾代码及改进代码

    热门讨论 2014-06-27 10:29:32
    暗通道去雾代码及改进代码,拥有对色彩方面的改进
  • 在实验中,首先对10000张样本图片采用暗通道去雾算法进行预处理,之后分别使用有无暗通道去雾算法预处理的样本图片训练模型,最后比较这两种模型在不同场景下的模型检测准确率。实验结果表明,使用暗通道去雾预处理...
  • 本人课程报告的内容,自己实现的基于MATLAB GUI 的暗通道去雾算法,有算法原理解析,希望能有所帮助。补充说明:本程序基于MATLAB2018B编写。
  • 暗通道去雾算法

    2018-10-30 12:25:48
    何凯明的暗通道去雾算法,算法简单明了,代码清晰易懂。
  • 基于暗通道先验算法的图像去雾技术已经日益成熟,但是其处理速度慢、天空区域过曝、处理完的图像色彩变暗等缺点也很明显。本文针对这几方面分别提出了求透射率时的优化、纠正天空等明亮区域的错误估计的透射率、采用...
  • 何凯明的暗通道去雾算法matlab代码,可运行
  • matlab版何恺明老师暗通道去雾法源码
  • 暗通道去雾及C++实现

    千次阅读 2018-12-06 10:46:38
    介绍 图像增强与图像修复二者之间有一定交叉,尽管它们一个...图像去雾就是这两种技术彼此交叉领域中最典型的代表。如果将雾霾看作是一种噪声,那么去除雾霾的标准显然是非常客观的,也就是要将图像恢复至没有雾霾...

    本博文参考和引用:https://www.cnblogs.com/herenzhiming/articles/5280759.html

    介绍

    图像增强与图像修复二者之间有一定交叉,尽管它们一个强调客观标准,一个强调主观标准,但毕竟最终的结果都改善了图像的质量。图像去雾就是这两种技术彼此交叉领域中最典型的代表。如果将雾霾看作是一种噪声,那么去除雾霾的标准显然是非常客观的,也就是要将图像恢复至没有雾霾下所获取的情况。但是如果将在雾霾环境下拍摄的照片就看作是一种图像本来的面貌,那么去雾显然就是人们为了改善主观视觉质量而对图像所进行的一种增强。早期图像去雾的研究并没有得到应有的重视,很多人认为它的实际意义不大,甚至觉得所谓的去雾算法多是些华而不实的花拳绣腿,缺乏学术上的价值。然而,斗转星移,时易世变。一方面随着大气污染的日益严重,设法改善自动获取的图像质量其意义不言而喻。另一方面,随着数码设备的普及,消费类电子产品的市场也催生出许多新的需求,其中人们对所拍照片质量的修正和优化就是一个显而易见的需求。说到图像去雾,就不得不提到由何恺明博士等人提出的基于暗通道的图像去雾算法。这个算法因其新颖的思路和理想的效果而广受关注,相关论文也曾于2009年荣获CVPR最佳论文奖,同时也是该奖设立以来,首次由亚洲学者获颁此殊荣。

    暗通道的概念和意义

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

    C++实现源代码

    main.cpp:

    #include<opencv2/core/core.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    #include<opencv2/highgui/highgui.hpp>
    #include<iostream>
    #include"function.h"
    #include<algorithm>
    #include<set>
    #include<map>
    
    using namespace std;
    using namespace cv;
    //导向滤波器
    
    int main()
    {
    	Mat src = imread("C:/Users/18301/Desktop/1.png");
    	Mat dst;
    	cvtColor(src, dst, CV_BGR2GRAY);
    	Mat dark_channel_mat = dark_channel(src);//输出的是暗通道图像
    	int A = calculate_A(src, dark_channel_mat);
    	Mat tx = calculate_tx(src, A, dark_channel_mat);
    	Mat tx_ = guidedfilter(dst, tx, 30, 0.001);//导向滤波后的tx,dst为引导图像
    	Mat haze_removal_image;
    	haze_removal_image= haze_removal_img(src, A, tx_);
    	namedWindow("去雾后的图像", 0);
    	namedWindow("原始图像", 0);
    	imshow("原始图像", src);
    	imshow("去雾后的图像", haze_removal_image);
    	waitKey(0);
    	return 0;
    }
    
    

    function.h

    #ifndef FUNCTION_H
    #define FUNCTION_H   
    
    #include<opencv2/core/core.hpp>
    #include<opencv2/imgproc/imgproc.hpp>
    #include<opencv2/highgui/highgui.hpp>
    #include<iostream>
    #include<map>
    
    using namespace std;
    using namespace cv;
    //导向滤波,用来优化t(x),针对单通道
    Mat guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps)
    {
    	//转换源图像信息
    	srcImage.convertTo(srcImage, CV_32FC1,1/255.0);
    	srcClone.convertTo(srcClone, CV_32FC1);
    	int nRows = srcImage.rows;
    	int nCols = srcImage.cols;
    	Mat boxResult;
    	//步骤一:计算均值
    	boxFilter(Mat::ones(nRows, nCols, srcImage.type()),
    		boxResult, CV_32FC1, Size(r, r));
    	//生成导向均值mean_I
    	Mat mean_I;
    	boxFilter(srcImage, mean_I, CV_32FC1, Size(r, r));
    	//生成原始均值mean_p
    	Mat mean_p;
    	boxFilter(srcClone, mean_p, CV_32FC1, Size(r, r));
    	//生成互相关均值mean_Ip
    	Mat mean_Ip;
    	boxFilter(srcImage.mul(srcClone), mean_Ip,
    		CV_32FC1, Size(r, r));
    	Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);
    	//生成自相关均值mean_II
    	Mat mean_II;
    	//应用盒滤波器计算相关的值
    	boxFilter(srcImage.mul(srcImage), mean_II,
    		CV_32FC1, Size(r, r));
    	//步骤二:计算相关系数
    	Mat var_I = mean_II - mean_I.mul(mean_I);
    	Mat var_Ip = mean_Ip - mean_I.mul(mean_p);
    	//步骤三:计算参数系数a,b
    	Mat a = cov_Ip / (var_I + eps);
    	Mat b = mean_p - a.mul(mean_I);
    	//步骤四:计算系数a\b的均值
    	Mat mean_a;
    	boxFilter(a, mean_a, CV_32FC1, Size(r, r));
    	mean_a = mean_a / boxResult;
    	Mat mean_b;
    	boxFilter(b, mean_b, CV_32FC1, Size(r, r));
    	mean_b = mean_b / boxResult;
    	//步骤五:生成输出矩阵
    	Mat resultMat = mean_a.mul(srcImage) + mean_b;
    	return resultMat;
    }
    
    //计算暗通道图像矩阵,针对三通道彩色图像
    Mat dark_channel(Mat src)
    {
    	int border = 7;
    	std::vector<cv::Mat> rgbChannels(3);
    	Mat min_mat(src.size(), CV_8UC1, Scalar(0)), min_mat_expansion;
    	Mat dark_channel_mat(src.size(), CV_8UC1, Scalar(0));
    	split(src, rgbChannels);
    	for (int i = 0; i < src.rows; i++)
    	{
    		for (int j = 0; j < src.cols; j++)
    		{
    			int min_val = 0;
    			int val_1, val_2, val_3;
    			val_1 = rgbChannels[0].at<uchar>(i, j);
    			val_2 = rgbChannels[1].at<uchar>(i, j);
    			val_3 = rgbChannels[2].at<uchar>(i, j);
    
    			min_val = std::min(val_1, val_2);
    			min_val = std::min(min_val, val_3);
    			min_mat.at<uchar>(i, j) = min_val;
    
    		}
    	}
    	copyMakeBorder(min_mat, min_mat_expansion, border, border, border, border, BORDER_REPLICATE);
    
    	for (int m = border; m < min_mat_expansion.rows - border; m++)
    	{
    		for (int n = border; n < min_mat_expansion.cols - border; n++)
    		{
    			Mat imageROI;
    			int min_num = 256;
    			imageROI = min_mat_expansion(Rect(n - border, m - border, 2*border+1, 2*border+1));
    			for (int i = 0; i < imageROI.rows; i++)
    			{
    				for (int j = 0; j < imageROI.cols; j++)
    				{
    					int val_roi = imageROI.at<uchar>(i, j);
    					min_num = std::min(min_num, val_roi);
    				}
    			}
    			dark_channel_mat.at<uchar>(m - border, n - border) = min_num;
    		}
    	}
    	return dark_channel_mat;
    }
    
    
    int calculate_A(Mat src,Mat dark_channel_mat)
    {
    	std::vector<cv::Mat> rgbChannels(3);
    	split(src, rgbChannels);
    	map<int, Point> pair_data;
    	map<int, Point>::iterator iter;
    	vector<Point> cord;
    	int max_val = 0;
    	//cout << dark_channel_mat.rows << " " << dark_channel_mat.cols << endl;
    	for (int i = 0; i < dark_channel_mat.rows; i++)
    	{
    		for (int j = 0; j < dark_channel_mat.cols; j++)
    		{
    			int val = dark_channel_mat.at<uchar>(i, j);
    			Point pt;
    			pt.x = j;
    			pt.y = i;
    			pair_data.insert(make_pair(val, pt));
    		}
    	}
    
    	for (iter = pair_data.begin(); iter != pair_data.end(); iter++)
    	{
    		//cout << iter->first << endl;
    		cord.push_back(iter->second);
    	}
    	for (int m = 0; m < cord.size(); m++)
    	{
    		Point tmp = cord[m];
    		int val_1, val_2, val_3;
    		val_1 = rgbChannels[0].at<uchar>(tmp.y, tmp.x);
    		val_2 = rgbChannels[1].at<uchar>(tmp.y, tmp.x);
    		val_3 = rgbChannels[2].at<uchar>(tmp.y, tmp.x);
    		max_val = std::max(val_1, val_2);
    		max_val = std::max(max_val, val_3);
    	}
    	return max_val;
    }
    
    
    Mat calculate_tx(Mat &src, int A, Mat &dark_channel_mat)
    {
    	Mat dst;//是用来计算t(x)
    	Mat tx;
    	float dark_channel_num;
    	dark_channel_num = A / 255.0;
    	dark_channel_mat.convertTo(dst, CV_32FC3, 1 / 255.0);//用来计算t(x)
    	dst = dst / dark_channel_num;
    	tx = 1 - 0.95*dst;//最终的tx图
    
    	return tx;
    }
    
    
    Mat haze_removal_img(Mat &src, int A, Mat &tx)
    {
    	Mat result_img(src.rows, src.cols, CV_8UC3);
    	vector<Mat> srcChannels(3), resChannels(3);
    	split(src, srcChannels);
    	split(result_img, resChannels);
    
    	for (int i = 0; i < src.rows; i++)
    	{
    		for (int j = 0; j < src.cols; j++)
    		{
    			for (int m = 0; m < 3; m++)
    			{
    				int value_num = srcChannels[m].at<uchar>(i, j);
    				float max_t = tx.at<float>(i, j);
    				if (max_t < 0.1)
    				{
    					max_t = 0.1;
    				}
    				resChannels[m].at<uchar>(i, j) = (value_num - A) / max_t + A;
    			}
    		}
    	}
    	merge(resChannels, result_img);
    
    	return result_img;
    }
    #endif
    

    实现结果:
    在这里插入图片描述
    原图像
    在这里插入图片描述
    暗通道图像
    在这里插入图片描述
    t(x)图像
    在这里插入图片描述
    去雾之后的图像

    从结果上来看,结果图像仍有一些边缘存在未去的雾,这里是因为t(x)在计算的时候比较粗糙,何凯明在2013年提出了一篇导向滤波可以很好的解决这个问题,关于导向滤波具体算法请参考:导向滤波算法解析

    在function.h中已经实现导向滤波,主要针对tx,guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps)函数,实现结果如下所示:
    在这里插入图片描述
    导向滤波之后的tx
    在这里插入图片描述
    基于导向滤波后的去雾图像

    相对于上述未进行导向滤波的结果图像,导向滤波后的结果效果有很大改善。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,180
精华内容 472
关键字:

暗通道去雾