图像去雾哪家强?之前我们已经讨论过了著名的基于暗通道先验的图像去雾(Kaiming He, 2009)算法,如果你用兴趣可以参考:

  • 暗通道优先的图像去雾算法(上)
  • 暗通道优先的图像去雾算法(下)

此外,网上也有很多同道推荐了一篇由韩国学者所发表的研究论文《Optimized contrast enhancement for real-time image and video dehazing》(你也可以从文末参考文献【1】给出的链接中下载到这篇经典论文),其中原作者就提出了一个效果相当不错的图像去雾算法。最近有朋友在我们的图像处理算法研究学习群中也提到了该算法,恰巧想到主页君也很久未发图像相关之文章了,今天遂心血来潮,向大家科普一下这个新算法。

欢迎关注白马负金羁的博客 http://blog.csdn.net/baimafujinji,为保证公式、图表得以正确显示,强烈建议你从该地址上查看原版博文。本博客主要关注方向包括:数字图像处理、算法设计与分析、数据结构、机器学习、数据挖掘、统计分析方法、自然语言处理。


算法核心1:计算大气光值

通常,图像去雾问题的基本模型可以用下面这个公式来表示(这一点在基于暗通道先验的图像去雾中我们也使用过):

I(p)=t(p)J(p)+(1−t(p))A

其中,J(p)=(Jr(p),Jg(p),Jb(p))T 表示原始图像(也就是没有雾的图像);I(p)=(Ir(p),Ig(p),Ib(p))T 表示我们观察到的图像(也就是有雾的图像)。r、g、b 表示位置 p 处的像素的三个分量。A=(Ar,Ag,Ab)T 是全球大气光,它表示周围环境中的大气光。 
此外,t(p)∈[0,1] 是反射光的透射率, 由场景点到照相机镜头之间的距离所决定。因为光传播的距离越远,那么通常光就约分散而且越发被削弱。所以上面这个公式的意思就是,本来没有被雾所笼罩的图像 J 与大气光 A 按一定比例进行混合后就得到我们最终所观察到的有雾图像。

大气光 A 通常用图像中最明亮的颜色来作为估计。因为大量的灰霾通常会导致一个发亮(发白)的颜色。然而,在这个框架下,那些颜色比大气光更加明亮的物体通常会被选中,因而便会导致一个本来不应该作为大气光参考值的结果被用作大气光的估计。为了更加可靠的对大气光进行估计,算法的作者利用了这样一个事实:通常,那些灰蒙蒙的区域(也就是天空)中像素的方差(或者变动)总体来说就比较小。

基于这个认识,算法的作者提出了一个基于四叉树子空间划分的层次搜索方法。如下图所示,我们首先把输入图像划分成四个矩形区域。然后,为每个子区域进行评分,这个评分的计算方法是“用区域内像素的平均值减去这些像素的标准差”(the average pixel value subtracted by the standard deviation 
of the pixel values within the region)。记下来,选择具有最高得分的区域,并将其继续划分为更小的四个子矩形。我们重复这个过程直到被选中的区域小于某个提前指定的阈值。例如下图中的红色部分就是最终被选定的区域。在这被选定的区域里,我们选择使得距离 ||(Ir(p),Ig(p),Ib(p))−(255,255,255)|| 最小化的颜色(包含 r,g,b 三个分量)来作为大气光的参考值。注意,这样做的意义在于我们希望选择那个离纯白色最近的颜色(也就是最亮的颜色)来作为大气光的参考值。

我们假设在一个局部的小范围内,场景深度是相同的(也就是场景内的各点到相机镜头的距离相同),所以在一个小块内(例如32×32)我们就可以使用一个固定的透射率 t,所以前面给出的有雾图像与原始(没有雾的)图像之间的关系模型就可以改写为

J(p)=1t(I(p)−A)+A

可见,在求得大气光 A 的估计值之后,我们希望复原得到的原始(没有雾的)图像 J(p) 将依赖于散射率 t。 
总的来说,一个有雾的块内,对比度都是比较低的,而被恢复的块内的对比度则随着 t 的估计值的变小而增大,我们将设法来估计一个最优的 t 值,从而使得去雾后的块能够得到最大的对比度。

下面是原作者给出的大气光计算函数代码(C/C++版)

<code class="language-c++ hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">void dehazing::AirlightEstimation(IplImage* imInput)
{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nMinDistance = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">65536</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nDistance;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nX, nY;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nMaxIndex;double dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];double dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];double dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];float afMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">{0}</span>;float afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span>] = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">{0}</span>;float nMaxScore = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nWid = imInput->width;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nHei = imInput->height;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nStep = imInput->widthStep;<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">4</span> <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-blockIplImage *iplUpperLeft = cvCreateImage(cvSize(nWid/2, nHei/2),IPL_DEPTH_8U, 3);</span>IplImage <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*iplUpperRight</span> = cvCreateImage(cvSize(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),IPL_DEPTH_8U, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);IplImage <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*iplLowerLeft</span> = cvCreateImage(cvSize(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),IPL_DEPTH_8U, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);IplImage <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*iplLowerRight</span> = cvCreateImage(cvSize(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),IPL_DEPTH_8U, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>);IplImage <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*iplR</span> = cvCreateImage(cvSize(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),IPL_DEPTH_8U, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);IplImage <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*iplG</span> = cvCreateImage(cvSize(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),IPL_DEPTH_8U, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);IplImage <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*iplB</span> = cvCreateImage(cvSize(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),IPL_DEPTH_8U, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> divide cvSetImageROI(imInput, cvRect(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));cvCopyImage(imInput, iplUpperLeft);cvSetImageROI(imInput, cvRect(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>+nWid<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%2</span>, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, nWid, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));cvCopyImage(imInput, iplUpperRight);cvSetImageROI(imInput, cvRect(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>+nHei<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%2</span>, nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, nHei));cvCopyImage(imInput, iplLowerLeft);cvSetImageROI(imInput, cvRect(nWid/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>+nWid<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%2</span>, nHei/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>+nHei<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">%2</span>, nWid, nHei));cvCopyImage(imInput, iplLowerRight);<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> compare to threshold(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>) --> bigger than threshold, divide the block<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nHei<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nWid</span> > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>){<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> compute the mean <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">and</span> std-dev in the <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-block// upper left <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-blockcvCvtPixToPlane(iplUpperLeft, iplR, iplG, iplB, 0);</span>cvMean_StdDev(iplR, dpMean, dpStds);cvMean_StdDev(iplG, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);cvMean_StdDev(iplB, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> dpScore: mean - std-devdpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = (float)(dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]);nMaxScore = afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];nMaxIndex = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> upper right <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-blockcvCvtPixToPlane(iplUpperRight, iplR, iplG, iplB, 0);</span>cvMean_StdDev(iplR, dpMean, dpStds);cvMean_StdDev(iplG, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);cvMean_StdDev(iplB, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = (float)(dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] > nMaxScore){nMaxScore = afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];nMaxIndex = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;}// lower left <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-blockcvCvtPixToPlane(iplLowerLeft, iplR, iplG, iplB, 0);</span>cvMean_StdDev(iplR, dpMean, dpStds);cvMean_StdDev(iplG, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);cvMean_StdDev(iplB, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = (float)(dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] > nMaxScore){nMaxScore = afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];nMaxIndex = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>;}// lower right <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-blockcvCvtPixToPlane(iplLowerRight, iplR, iplG, iplB, 0);</span>cvMean_StdDev(iplR, dpMean, dpStds);cvMean_StdDev(iplG, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>);cvMean_StdDev(iplB, dpMean+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>, dpStds+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = dpMean[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]-dpStds[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>] = (float)(dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>]+dpScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>]);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>] > nMaxScore){nMaxScore = afScore[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];nMaxIndex = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;}// <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> the <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-block, which has maximum scoreswitch (nMaxIndex){</span>case <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>:AirlightEstimation(iplUpperLeft); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;case <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:AirlightEstimation(iplUpperRight); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;case <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>:AirlightEstimation(iplLowerLeft); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;case <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>:AirlightEstimation(iplLowerRight); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">break</span>;}}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span>{<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">select</span> the atmospheric light value in the <span class="hljs-sub" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sub</span>-blockfor(nY=0;</span> nY<nHei; nY++){<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(nX=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; nX<nWid; nX++){<span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-r, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-g, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-bnDistance = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sqrt</span>(float(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-(uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>])<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*float</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-(uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>])+float(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-(uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*float</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-(uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])+float(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-(uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>])<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*float</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>-(uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>])));<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nMinDistance > nDistance){nMinDistance = nDistance;m_anAirlight[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>] = (uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>];m_anAirlight[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>] = (uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>];m_anAirlight[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>] = (uchar)imInput->imageData[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nStep</span>+nX<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*3</span>+<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>];}}}}cvReleaseImage(&iplUpperLeft);cvReleaseImage(&iplUpperRight);cvReleaseImage(&iplLowerLeft);cvReleaseImage(&iplLowerRight);cvReleaseImage(&iplR);cvReleaseImage(&iplG);cvReleaseImage(&iplB);
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li><li style="box-sizing: border-box; padding: 0px 5px;">117</li><li style="box-sizing: border-box; padding: 0px 5px;">118</li><li style="box-sizing: border-box; padding: 0px 5px;">119</li><li style="box-sizing: border-box; padding: 0px 5px;">120</li><li style="box-sizing: border-box; padding: 0px 5px;">121</li><li style="box-sizing: border-box; padding: 0px 5px;">122</li><li style="box-sizing: border-box; padding: 0px 5px;">123</li><li style="box-sizing: border-box; padding: 0px 5px;">124</li><li style="box-sizing: border-box; padding: 0px 5px;">125</li><li style="box-sizing: border-box; padding: 0px 5px;">126</li><li style="box-sizing: border-box; padding: 0px 5px;">127</li><li style="box-sizing: border-box; padding: 0px 5px;">128</li><li style="box-sizing: border-box; padding: 0px 5px;">129</li><li style="box-sizing: border-box; padding: 0px 5px;">130</li><li style="box-sizing: border-box; padding: 0px 5px;">131</li><li style="box-sizing: border-box; padding: 0px 5px;">132</li><li style="box-sizing: border-box; padding: 0px 5px;">133</li><li style="box-sizing: border-box; padding: 0px 5px;">134</li><li style="box-sizing: border-box; padding: 0px 5px;">135</li><li style="box-sizing: border-box; padding: 0px 5px;">136</li><li style="box-sizing: border-box; padding: 0px 5px;">137</li><li style="box-sizing: border-box; padding: 0px 5px;">138</li><li style="box-sizing: border-box; padding: 0px 5px;">139</li><li style="box-sizing: border-box; padding: 0px 5px;">140</li><li style="box-sizing: border-box; padding: 0px 5px;">141</li><li style="box-sizing: border-box; padding: 0px 5px;">142</li><li style="box-sizing: border-box; padding: 0px 5px;">143</li><li style="box-sizing: border-box; padding: 0px 5px;">144</li><li style="box-sizing: border-box; padding: 0px 5px;">145</li><li style="box-sizing: border-box; padding: 0px 5px;">146</li><li style="box-sizing: border-box; padding: 0px 5px;">147</li><li style="box-sizing: border-box; padding: 0px 5px;">148</li><li style="box-sizing: border-box; padding: 0px 5px;">149</li><li style="box-sizing: border-box; padding: 0px 5px;">150</li><li style="box-sizing: border-box; padding: 0px 5px;">151</li><li style="box-sizing: border-box; padding: 0px 5px;">152</li><li style="box-sizing: border-box; padding: 0px 5px;">153</li><li style="box-sizing: border-box; padding: 0px 5px;">154</li><li style="box-sizing: border-box; padding: 0px 5px;">155</li><li style="box-sizing: border-box; padding: 0px 5px;">156</li><li style="box-sizing: border-box; padding: 0px 5px;">157</li><li style="box-sizing: border-box; padding: 0px 5px;">158</li><li style="box-sizing: border-box; padding: 0px 5px;">159</li><li style="box-sizing: border-box; padding: 0px 5px;">160</li><li style="box-sizing: border-box; padding: 0px 5px;">161</li><li style="box-sizing: border-box; padding: 0px 5px;">162</li><li style="box-sizing: border-box; padding: 0px 5px;">163</li></ul>

或者你也可以使用下面这个Matlab的实现,显而易见代码更加简单(源码由图像算法研究学习群里“薛定谔的猫”提供,略有修改):

<code class="language-matlab hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">
<span class="hljs-function" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">function</span> <span class="hljs-title" style="box-sizing: border-box;">airlight</span> = <span class="hljs-title" style="box-sizing: border-box;">est_airlight</span><span class="hljs-params" style="color: rgb(102, 0, 102); box-sizing: border-box;">(img)</span></span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">%compute atmospheric light A through hierarchical</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">%searching method based on the quad-tree subdivision</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">global</span> best;
<span class="hljs-matrix" style="box-sizing: border-box;">[w,h,z]</span> = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">size</span>(img);
img = double(img);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> w*h > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">200</span>lu = img(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(w/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(h/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),:);ru = img(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(w/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(h/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>):h,:);lb = img(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(w/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>):w,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(h/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>),:);rb = img(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(w/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>):w,<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">floor</span>(h/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>):h,:);lu_m_r = mean(mean(lu(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)));lu_m_g = mean(mean(lu(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)));lu_m_b = mean(mean(lu(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)));ru_m_r = mean(mean(ru(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)));ru_m_g = mean(mean(ru(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)));ru_m_b = mean(mean(ru(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)));lb_m_r = mean(mean(lb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)));lb_m_g = mean(mean(lb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)));lb_m_b = mean(mean(lb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)));rb_m_r = mean(mean(rb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)));rb_m_g = mean(mean(rb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)));rb_m_b = mean(mean(rb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)));lu_s_r = std2(lu(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));lu_s_g = std2(lu(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));lu_s_b = std2(lu(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>));ru_s_r = std2(ru(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));ru_s_g = std2(ru(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));ru_s_b = std2(ru(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>));lb_s_r = std2(lb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));lb_s_g = std2(lb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));lb_s_b = std2(lb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>));rb_s_r = std2(rb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>));rb_s_g = std2(rb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>));rb_s_b = std2(rb(:,:,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>));   score0 = lu_m_r + lu_m_g + lu_m_b - lu_s_r - lu_s_g - lu_s_b;score1 = ru_m_r + ru_m_g + ru_m_b - ru_s_r - ru_s_g - ru_s_b;    score2 = lb_m_r + lb_m_g + lb_m_b - lb_s_r - lb_s_g - lb_s_b;    score3 = rb_m_r + rb_m_g + rb_m_b - rb_s_r - rb_s_g - rb_s_b;    x = <span class="hljs-matrix" style="box-sizing: border-box;">[score0,score1,score2,score3]</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> max(x) == score0est_airlight(lu);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">elseif</span> max(x) == score1est_airlight(ru);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">elseif</span> max(x) == score2est_airlight(lb);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">elseif</span> max(x) == score3est_airlight(rb);   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:w<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span> = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>:hnMinDistance = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">65536</span>;distance = <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sqrt</span>((<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span> - img(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>,<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>)).^<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> +  (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span> - img(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>,<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>)).^<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span> + (<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span> - img(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>,<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>)).^<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> nMinDistance > distancenMinDistance = distance;best = img(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">i</span>,<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">j</span>,:);<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span>airlight =best;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">end</span>
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li></ul>

算法核心2:透射率的计算

我们首先给出图像对比度度量的方法(论文中,原作者给出了三个对比度定义式,我们只讨论其中第一个):

CMSE=∑p=1N=(Jc(p)−J¯c)2N

其中 c∈{r,g,b} 是颜色通道的索引标签,J¯c 是Jc(p)的平均值,并且p=1,⋯,N,N 是块中像素的数量。

根据之前给出的有雾图像与原始(没有雾的)图像之间的关系模型

J(p)=1t(I(p)−A)+A

我们可以把上述对比度定义式重新为

CMSE=∑p=1N=(Ic(p)−I¯c)2t2N

其中  I¯c  是 Ic(p) 的平均值,而且你会发现上述式子也告诉我们对比度是关于  t  的递减函数。

既然我们希望通过增强对比度的方法来去雾,那么不妨将一个区块B内三个颜色通道上的MSE对比度加总,然后再取负,如下

Econtrast=−∑c∈{r,g,b}∑p∈B(Jc(p)−J¯c)2NB=−∑c∈{r,g,b}∑p∈B(Ic(p)−I¯c)2t2NB

由于加了负号,所以取对比度最大就等同于取上式最小。

另外一方面,因为对比度得到增强,可能会导致部分像素的调整值超出了0和255的范围,这样就会造成信息的损失以及视觉上的瑕疵。所以算法作者又提出了一个信息量损失的计算公式:

于是我们把所有问题都统一到了求下面这个式子的最小值问题上

E=Econtrast+λLEloss

其中, λL  是一个权重参数用于控制信息损失和对比度之间的一个相对重要性。With a small value  λL , the restored images have significantly increased contrast, but they lose information and contain unnaturally dark pixels due to the truncation of pixel values. On the contrary, with a large value of  λL , we can prevent the information loss but cannot remove haze fully. 总的来说,  λL=  5 strikes a balance between the information loss prevention and the haze removal effectively.

下面是基于OpenCV实现的示例代码:

<code class="language-c++ hljs perl has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">float dehazing::NFTrsEstimationColor(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*pnImageR</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*pnImageG</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*pnImageB</span>, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nStartX, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nStartY, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nWid, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nHei)
{<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nCounter;   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nX, nY;     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nEndX;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nEndY;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nOutR, nOutG, nOutB;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nSquaredOut;                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nSumofOuts;                 <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nSumofSquaredOuts;          float fTrans, fOptTrs;          <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nTrans;                     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nSumofSLoss;                float fCost, fMinCost, fMean;   <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> nNumberofPixels, nLossCount;nEndX = __min(nStartX+m_nTBlockSize, nWid); nEndY = __min(nStartY+m_nTBlockSize, nHei); nNumberofPixels = (nEndY-nStartY)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*(</span>nEndX-nStartX) * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>;  fTrans = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>.<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>f;  nTrans = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">427</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(nCounter=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>; nCounter<<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>; nCounter++){nSumofSLoss = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;nLossCount = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;nSumofSquaredOuts = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;nSumofOuts = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(nY=nStartY; nY<nEndY; nY++){<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(nX=nStartX; nX<nEndX; nX++){nOutB = ((pnImageB[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nWid</span>+nX] - m_anAirlight[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>])<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nTrans</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*m_anAirlight</span>[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>])>><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>; <span class="hljs-regexp" style="color: rgb(0, 136, 0); box-sizing: border-box;">//</span> (I-A)/t + A --> ((I-A)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*k</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*128</span> + A<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*128</span>)/<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span>nOutG = ((pnImageG[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nWid</span>+nX] - m_anAirlight[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nTrans</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*m_anAirlight</span>[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>])>><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>;nOutR = ((pnImageR[nY<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nWid</span>+nX] - m_anAirlight[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>])<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*nTrans</span> + <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">128</span><span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*m_anAirlight</span>[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>])>><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">7</span>;     <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nOutR><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>){nSumofSLoss += (nOutR - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*(</span>nOutR - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>);nLossCount++;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nOutR < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){nSumofSLoss += nOutR * nOutR;nLossCount++;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nOutG><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>){nSumofSLoss += (nOutG - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*(</span>nOutG - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>);nLossCount++;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nOutG < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){nSumofSLoss += nOutG * nOutG;nLossCount++;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nOutB><span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>){nSumofSLoss += (nOutB - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>)<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*(</span>nOutB - <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">255</span>);nLossCount++;}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nOutB < <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>){nSumofSLoss += nOutB * nOutB;nLossCount++;}nSumofSquaredOuts += nOutB * nOutB + nOutR * nOutR + nOutG * nOutG;;nSumofOuts += nOutR + nOutG + nOutB;}}fMean = (float)(nSumofOuts)/(float)(nNumberofPixels);  fCost = m_fLambda1 * (float)nSumofSLoss/(float)(nNumberofPixels) - ((float)nSumofSquaredOuts/(float)nNumberofPixels - fMean<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*fMean</span>); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span>(nCounter==<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span> || fMinCost > fCost){fMinCost = fCost;fOptTrs = fTrans;}fTrans += <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>.<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>f;nTrans = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>)(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>f/fTrans<span class="hljs-variable" style="color: rgb(102, 0, 102); box-sizing: border-box;">*128</span>.0f);}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> fOptTrs;
}
</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li></ul>

在原文中,作者还提供了并行实现的算法(如果你参考作者的源码,你会发现他使用了OpenMP)用于实时对视频进行去雾,这已经超出本文的研究范围,我们不做深究。


实验效果

作者的项目主页(文献[2])中提供有一个基于OpenCV的实现,不过由于OpenCV代码配置起来太麻烦,所以我并未采用。非常感谢图像算法研究群里的同学分享给我MATLAB版的代码(我略有修改)。其实这个算法用MATLAB来写真的非常方便,大约不超过150行即可搞定,特别是MATLAB2014之后集成了导向滤波算法,所以一个函数调用直接搞定,省去很多麻烦。下面是我基于这个MATLAB版程序给出一些测试结果,可供参考(由于我和原作者所使用的参数可能存在差异,所以效果并不保证完全相同)。

主要结论:

  • 算法对于天空部分的处理相当到位,更优于Kaiming He的暗通道先验算法;
  • 对比度过大时,图像很容易发暗,可以后期将图片稍微调亮一些。
  • 算法本身是从对比增强的角度来进行去雾操作的,所以你可以看出结果自动带对比度增强加成,所以这个算法所取得的结果通常更加鲜亮。

=========== 
无冥冥之志者,无昭昭之明,无惛惛之事者,无赫赫之功。

=========== 
如果你是图像处理的同道中人,欢迎加入图像处理学习群(529549320)。为保证本群质量,入群前请先阅读群规(即本博客置顶文章http://blog.csdn.Net/baimafujinji/article/details/50570976),并在博客置顶帖中留言,否则将不予入群,请不要做无谓的尝试。


参考文献与推荐阅读材料

[1] Kim, J.H., Jang, W.D., Sim, J.Y. and Kim, C.S., 2013. Optimized contrast enhancement for real-time image and video dehazing. Journal of Visual Communication and Image Representation, 24(3), pp.410-425. (百度云下载链接) 
[2] 原作者的项目主页——可以下载到基于OpenCV实现的程序源代码 
[3] laviewpbt更早之前发布的一篇研究该算法的文章——该博客上同时包含有很多其他图像去雾方面的文章,推荐有兴趣的读者参考

用于图像去雾的优化对比度增强算法相关推荐

  1. 【Gated Context Aggregation Network for Image Dehazing and Deraining用于图像去雾和去雨的门控上下文聚合网络】,个人笔记,勿喷

    摘要 图像去雾旨在从模糊图像中恢复未损坏的内容.我们没有利用传统的低级或手工图像先验作为恢复约束,例如暗通道和增加的对比度,而是提出了一个端到端的门控上下文聚合网络来直接恢复最终的无雾图像.在这个网络 ...

  2. [Python图像识别] 四十六.图像预处理之图像去雾详解(ACE算法和暗通道先验去雾算法)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  3. Domain Adaptation for Image Dehazing(图像去雾的域自适应算法CVPR2020)

    摘要:现有的去雾方法大多是在合成的雾霾图像上训练去雾模型,但由于域的偏移,对真实的雾霾图像的泛化效果较差.故提出一种领域自适应模式,该模式由一个图像平移模块和两个图像去雾模块组成.具体来说,首先应用一 ...

  4. 综述:视频和图像去雾算法以及相关的图像恢复和增强研究

    综述:视频和图像去雾算法以及相关的图像恢复和增强研究 翻译自IEEE的一篇文章<Review of Video and Image Defogging Algorithms and Relate ...

  5. 【MATLAB图像处理实用案例详解(1)】—— 基于直方图优化的图像去雾技术

    目录 一.背景意义 二.理论基础 2.1 空域图像増强 2.2 直方图均衡化 三.方法选择 3.1 全局直方图算法 3.2 局部直方图算法 3.3 Retinex算法 四.效果演示 五.完整代码 一. ...

  6. 无人机图像处理工具-亮度、对比度、饱和度调整/匀光匀色/图像去雾

    无人机图像处理工具,java写的,已打包为64位可执行文件exe,并且绑定lib文件(jre),无需在电脑上单独安装java运行环境.支持亮度.对比度.饱和度调整,匀光匀色(自动色阶.自动对比度),图 ...

  7. 避免图像去雾算法中让天空部分出现过增强的一种简易方法

    FROM:http://www.chawenti.com/articles/25193.html 在经典的几种去雾算法中,包括何凯明的暗通道去雾.Tarel的基于中值滤波的去雾以及一些基于其他边缘保留 ...

  8. 【第 01 章 基于直方图优化的图像去雾技术-全套系统MATLAB智能驾驶深度学习】

    毋庸置疑的是,在汽车智能技术.汽车新能源技术.汽车电子这个群雄逐鹿的赛道.智能驾驶技术的要求也在不断的提升. 智能车辆教学平台.智能网联教学平台.汽车电子教学设备.在环仿真系统,目前主流的系统有很多, ...

  9. RYF-Net: 深度融合网络用于单幅图像去雾(Deep Fusion Network for Single ImageHaze Removal-IEEE_TIP-2020)

    概述 在本文中提出了一种基于卷积神经网络的体系结构来估计模糊场景的场景传输图(TrMap).本文提出的网络以雾图像为输入,利用本文提出的RNet和YNet分别通过RGB和YCbCr颜色空间提取雾霾相关 ...

最新文章

  1. Mysql8.0.20下载和安装
  2. select自定义箭头样式
  3. postgres主从配置
  4. HTML与XML数据的结合小总结
  5. java解码acc音频文件_(JAVA)将(acc/m4a)音频转换成Mp3格式
  6. mongoVue 对mongodb的操作
  7. COMSOL有限元仿真深度指南:超弹性模型有限元分析入门
  8. mac视频播放器哪个最好用?不妨试试OmniPlayer Pro mac中文版吧
  9. 郁闷,俺被S3C2416 狠狠的暗算了一把。
  10. 华为应聘进展状态码解析(附加性格测试攻略)
  11. 微信公众账号开发教程(四)自定义菜单(含实例源码)——转自http://www.cnblogs.com/yank/p/3418194.html...
  12. 免费4s店汽车保养维修记录查询的方式
  13. 优化嵌入式Linux的启动时间的秘密
  14. 装机之 BIOS、EFI与UEFI详解
  15. 《炬丰科技-半导体工艺》氧化铝陶瓷基板上的紫外激光微加工和化学蚀刻
  16. Eclipse注释中文格式没对齐
  17. PixHawk飞控 配置参数
  18. qt 从文件中读出数据显示在表格中_java如何从文件中读取数据存在数组再显示在表格中!!...
  19. 腾讯音乐的2021主基调:稳与变
  20. java编程输入学生成绩 判断最高分,java代码初学者适用,输入学生成绩,符合要求的过~~~~注意数据范围...

热门文章

  1. 路径java起床战争_我的世界起床战争地图
  2. ThinkPHP5.1 按照汉字的拼音排序
  3. 华为手机助手安卓版_每日咻手机助手app下载-每日咻手机助手安卓版 v1.0.0
  4. 运行jar文件出现了Exception in thread “main java.lang.UnsupportedClassVersionError
  5. Facebook公共主页内容品质和公共主页被封会有联系吗?
  6. oracle产品清单位置无效,[急]oracle打patch出错,求助!!
  7. 图解server端网络架构
  8. HD地址批量生成(java)
  9. android gps 航向,gps航向怎么在webgis系统中表示
  10. Oracle数据库 游标