图像去雾算法的原理、实现、效果

图像的去雾算法原理及实现:

本文主要是实现的是基于暗通道处理的去雾。有部分是看论文直接翻译而来,如有错误,欢迎评论区指出,当然您也可以直接阅读原文。

一、原理

暗通道先验解释:

说明:何凯明博士的论文中统计了5000多副图像的特征,证明了暗通道先验理论的普遍性,因此我们可以粗略的认为是一条定理。

先看什么是暗通道先验:

在绝大多数图像局部区域里,有一些像素总会有至少一个颜色通道具有很低的值,该区域光强度的最小值是个很小的数。暗通道的数学定义,对于任意的输入图像J,其暗通道可以用下式表达:

                                    

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

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

暗通道先验的理论指出:

                                                     

这个可以自己去试一下的。

 有了这个先验,接着就需要进行一些数学方面的推导来最终解决问题。

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

                             

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

将其稍作处理,变形为:

                                 

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

首先假设在每一个窗口内透射率t(x)为常数,定义他为

,并且A值已经给定,然后两边求两次最小值运算,得到下式:

                                        

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

                                                 

   可得:

                                                                            

则透射率

的预估值:

                                                     

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

                                                            

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

1.求暗通道

//计算暗通道
//J^{dark}(x)=min( min( J^c(y) ) )
Mat DarkChannelPrior(Mat img)
{
	Mat dark = Mat::zeros(img.rows, img.cols, CV_32FC1);//新建一个所有元素为0的单通道的矩阵

	for (int i = 0; i<img.rows; i++)
	{
		for (int j = 0; j<img.cols; j++)
		{
			dark.at<float>(i, j) = min(
				min(img.at<Vec<float, 3>>(i, j)[0], img.at<Vec<float, 3>>(i, j)[1]),
				min(img.at<Vec<float, 3>>(i, j)[0], img.at<Vec<float, 3>>(i, j)[2])
				);//就是两个最小值的过程
		}
	}
	erode(dark, dark_out1, Mat::ones(_PriorSize, _PriorSize, CV_32FC1));
	//这个函数叫腐蚀 做的是窗口大小的模板运算 ,对应的是最小值滤波,即 黑色图像中的一块块的东西

	return dark_out1;//这里dark_out1用的是全局变量,因为在其它地方也要用到
}

2.A值计算:

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

具体步骤如下:

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

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

3.计算预估的透射率图

  在

式中,每个通道的数据都需要除以对应的A值,即归一化,对对比度低的图像可以获得很好的去雾高对比度图。但是/A操作可能会导致t的值小于0,这种情况就可以把t的值直接设置为0来解决。

       针对上面说的,要值得一提的是,严格的来说是要对原始图像的每个通道进行归一化后,再取每个通道R/G/B值的最小值得到中间图,然后对这个中间图进行指定半径的最小值滤波后,通过

式得到粗糙的透射率图。那么这样就需要增加不少计算,我在实际中发现如果直接用前面的暗通道图/A进行操作,两者的效果区别不明显,因此,可用这种简便的方式。

      到这一步,我们就可以进行无雾图像的恢复了。由式可知:  J = ( I - A)/t + A  

     现在I,A,t都已经求得了,因此,完全可以进行J的计算。

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

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

                                              

去雾的效果:

原图:

去雾后:

二、各参数对去雾结果的影响

第一:窗口的大小。这个对结果来说是个关键的参数,窗口越大,其包含暗通道的概率越大,暗通道也就越黑。建议是窗口大小在11-51之间,即半径在5-25之间。

第二:ω也有着明显的意义,其值越小,去雾效果越不明显。

三、代码

小博的环境是vs2017+opencv3.40:

实现代码:     https://download.csdn.net/download/m0_37407756/33494088                  

  • 19
    点赞
  • 279
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向阳+

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值