整理的比较好的图像去雾算法
Posted 刘二毛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整理的比较好的图像去雾算法相关的知识,希望对你有一定的参考价值。
2016.03,24 再补充几个搜索到的资料:
论文的翻译,不太好,凑合看 http://wenku.baidu.com/link?url=SwSoHn-7IfxY7pp-VEway9fRMM5AOlc1j2xvIQytUivfqSSHm-j5moJVr3EYDOUblLo-VMDOF2sxCvNGYgFBUNJ4-zIhBEJTwn7ATfXcO7q
论文的原文: http://wenku.baidu.com/view/5391746365ce0508773213b9.html
用opencv实现的,有代码和详细的解释,但是效率非常低,代码有很大的改进空间,仅作参考吧
http://www.cnblogs.com/changkaizhao/p/3266798.html
1 首先是何博士2009年在CVPR上的一篇paper
转自
http://blog.csdn.net/baimafujinji/article/details/27206237?ticket=ST-264104-uEM9GFfaos96lqSCMO4R-passport.csdn.net
论文中解释为什么能用暗通道来去雾:在不包括天空的绝大部分局部区域,总会存在一些我们称之为“dark pixels”的像素,至少有一个颜色通道具备很低的强度值。在被雾干扰的图像里,这些暗像素的强度值会被大气中的白光成分所充斥而变得较高。 因此,这些暗像素能够直接用来评估雾光的透射信息
方程右边的第一项J(x)t(x) 叫做直接衰减项,第二项A(1-t(x)) 则是大气光成分。直接衰减项描述的是景物光线在透射媒介中经衰减后的部分,而大气光则是由前方散射引 起的,会导致景物颜色的偏移。
现在结果已经比较细腻了,但是显然图像有些暗。何博士在论文中也有提及直接暗通道算法的结果会是比较暗的。下一篇文章中,我们将给出在MATLAB中实现的源代码,并对过暗的图像增加曝光和自动色阶,从而得到完美的去雾图像。
补充:http://www.cnblogs.com/Imageshop/category/535365.html
何的算法效果以及普遍的实用性都比其他的去雾算法要好,而主要的问题就是其速度还是不够快,有着太多的浮点计算。鉴于此,作者也多次试着对代码进行深层次的优化,包括SSE处理、并行运行等,但由于算法本身的顺序执行,无法全程并行,偶尔一个小函数可以并行,但由于其本身执行就特别快,比如不要5ms,你去用并行算法可能耗时还会大一些。因此,一直没有什么大的进步,对于一副1024*768的彩图进行去雾需要90ms,这肯定无法满足需求。
最近,在思考,既然暗通道去雾的透射率图比其他的算法都来的精细,如果适当的降低一点点其精度,其去雾的效果理论上应该不会有太大的区别,于是我想到了一种方式,即求取透射率的时候不是对原图进行求取,而是先对原图进行下采样,比如缩小为原图的1/4,计算出小图的透射率,之后在通过插值的方式的获取原图大概的透射率,则应该也可以获得效果。经过实践,这种方式大大的提高了执行速度,而且效果和原始的方案基本一致,对于1024*768的图像大约只需要(I3CPU)30ms了,如果进一步取1/9的缩放,则只需要大约20ms,完全可以满足工业实时性要求高的场合。
当然,如果你的缩小系数不是特别大的话,比如缩小为原来的0.5大小,可能两次缩放所用的耗时还抵消了计算小图的透射率图所换来的盈利,因此必须合理选择这个下采样率。
要实现这样的速度,当然还是需要很高的优化技巧的,这些东西还是有所保留比较好。
2Optimized contrast enhancement for real-time image and video dehazing
这个算法的原理来自于文章《Optimized contrast enhancement for real-time image and video dehazing》,作者是韩国人。
这个算法也是基于大气散射模型:
和现在一些常见的去雾文章有明显的不同的是,这篇文章的并不是基于暗通道原理的,也不是把重点强调在透射率图的细化上,而是提出了一种新的得到粗透射率图的方法。并且文章分别讲到了静态图像和视频图像的去雾,这里我只研究了静态图的去雾。
对于透射率图,文章提出了一个cost function,这个cost function是基于以下两点考虑的:
1、对于有雾图像,其整体的对比比较低,因此去雾后的对比度要尽量的高,文中给出了三种测评一幅图像对比度的方式,这里选用的是第一种:
公式具体的意义可见论文。注意上面的公式都是对去雾图进行的处理。
2、 由于对比度得到增强,可能会导致部分像素的调整值超出了0和255的范围,这样就会造成信息的损失以及视觉上的瑕疵。因此提出了一个信息量损失的计算公式:
一个好的透射率图应该使得总的损失最小:
其中Lamda值用于控制对比度和信息损失之间的重要性。
进行上述过程还有一个重要的前提就是:对于一小块图像,我们认为他的透射率是一样的,以下作者提供的代码表面了这一点:
for(nY=0; nY<nHei; nY+=m_nTBlockSize)
for(nX=0; nX<nWid; nX+=m_nTBlockSize)
fTrans = NFTrsEstimationPColor(pnImageR, pnImageG, pnImageB, pnImageRP, pnImageGP, pnImageBP, pfTransmissionP, __max(nX, 0), __max(nY, 0), nWid, nHei);
for(nYstep=nY; nYstep<nY+m_nTBlockSize; nYstep++)
for(nXstep=nX; nXstep<nX+m_nTBlockSize; nXstep++)
pfTransmission[nYstep*nWid+nXstep] = fTrans;
其中的NFTrsEstimationPColor是用来估计一个块的最佳透射率值,作者在编程时,是将透射率按照0.1的间距进行取样,然后找到使得上式最小值得那个透射率作为这个块的透射率。
nEndX = __min(nStartX+m_nTBlockSize, nWid); // End point of the block
nEndY = __min(nStartY+m_nTBlockSize, nHei); // End point of the block
nNumberofPixels = (nEndY-nStartY)*(nEndX-nStartX);
fTrans = 0.3f; // Init trans is started from 0.3
nTrans = 427; // Convert transmission to integer
for(nCounter=0; nCounter<7; nCounter++)
nSumofSLoss = 0;
nLossCount = 0;
nSumofSquaredOuts = 0;
nSumofOuts = 0;
for(nY=nStartY; nY<nEndY; nY++)
for(nX=nStartX; nX<nEndX; nX++)
nOut = ((pnImageY[nY*nWid+nX] - m_nAirlight)*nTrans + 128*m_nAirlight)>>7; // (I-A)/t + A --> ((I-A)*k*128 + A*128)/128
nSquaredOut = nOut * nOut;
if(nOut>255)
nSumofSLoss += (nOut - 255)*(nOut - 255);
nLossCount++;
else if(nOut < 0)
nSumofSLoss += nSquaredOut;
nLossCount++;
nSumofSquaredOuts += nSquaredOut;
nSumofOuts += nOut;
fMean = (float)(nSumofOuts)/(float)(nNumberofPixels);
fCost = m_fLambda1 * (float)nSumofSLoss/(float)(nNumberofPixels)
- ((float)nSumofSquaredOuts/(float)nNumberofPixels - fMean*fMean);
if(nCounter==0 || fMinCost > fCost)
fMinCost = fCost;
fOptTrs = fTrans;
fTrans += 0.1f;
nTrans = (int)(1.0f/fTrans*128.0f);
朋友们有没有看到上面的代码中的最小透射率是0.3,我个人认为这个只能够有效的避免天空部位被过增强。
文中提到了这个方法也可以看成是何凯明的暗通道去雾算法的一个更广义的定义。
在这个文章,还提出了另外一个和其他算法不同的东西,就是全局大气光A的获取,其主要原理是: the variance of pixel values is generally low in hazy regions, e.g. sky. 具体的操作流程是:
we first divide an input image into four rectangular regions. We then define the score of each region as the average pixel value subtracted by the standard deviation of the pixel values within the region. Then, we select the region with the highest score and divide it further into four smaller regions.We repeat this process until the size of the selected region is smaller than a pre-specified threshold. Within the selected region, we choose the color vector, which minimizes the distance ||(R,G,B) -(255,255,255)||as the atmospheric light. By minimizing the distance from the pure white vector(255,255,255), we attempt to choose the atmospheric light that is as bright as possible.
结合上述描述以及论文配套的代码可以很容易的理解这里的道理。论文的配套代码的实现也很好。
具体的流程还是请各位仔细的阅读论文及其代码,经过我自己的优化和实践,这个算法确实能得到很不错的效果,在速度上也能够达到实时。
在贴一些效果图(有的时候只有看到这些图,才很有成就感)。
论文及原作者的代码下载地址:http://mcl.korea.ac.kr/projects/dehazing/#userconsent# (这个源代码是OPENCV写的)
以上是关于整理的比较好的图像去雾算法的主要内容,如果未能解决你的问题,请参考以下文章