图像去雾
刷博客的时候,无意中看到一篇介绍图像去雾的博客,讲到何凯明的《Single Image Haze Removal Using Dark Channel Prior》这篇文章,2009年CVPR的最佳论文,简单看了下介绍,瞬间就对作者佩服的五体投地,感叹这才叫做研究。
论文《Single Image Haze Removal Using Dark Channel Prior》可以在这里下载到,并且里面还有论文相关的幻灯片和其他参考论文等信息。
1. 论文的主要介绍
1.1 暗通道先验
暗通道先验是基于户外无雾图像的观察,在大部分不包含天空的图像中,在r,g,b三个通道中,至少有一个通道的最小灰度值非常小。用公式表示为,图像的暗通道J定义为:
$$
J^{dark}(x)=\min_{y\in{r,g,b}}(\min_{y\in\Omega(x)}(J^c(y))
$$
其中,$J^c$表示J的颜色通道,$\Omega(x)$表示以x为中心的窗口。
观察发现,对于户外无雾图片,$J^{dark}$值是非常小的,由此,称这个统计规律为暗通道先验。
1.2 图像去雾
在计算机视觉和计算机图形学中,通常使用下面的模型描述有雾图像:
$$
I(x)=J(x)t(x) + A(1-t(x))
$$
其中,I(x)就是观察到的含雾图像,J(x)是不包含雾的图像,A是全球大气光成分系数,t(x)表示透射率。图像去雾的问题实际上是根据已知的I(x)来求J(x)。
1.3 计算透射率
首先,假设大气光成分系数A是已知的,进一步的,假设在图像的一个小窗口内$\Omega(x)$,透射率t(x)是一个常数,对有雾图像模型的窗口内,使用min操作,得到:
$$
\min_{y\in\Omega(x)}(I^c(y)) = \tilde{t}(x)\min_{y\in\Omega(x)}(J^c(y))+(1-\tilde{t}(x))A^c
$$
min操作是在三个色彩通道上独立进行的,所以等式可以化简为:
$$
\min_{y\in\Omega(x)}(\frac{I^c(y)}{A^c}) = \tilde{t}(x)\min_{y\in\Omega(x)}(\frac{J^c(y)}{A^c})+(1-\tilde{t}(x))
$$
对上面等式中三个色彩通道使用min操作,得到
$$
\min_c(\min_{y\in\Omega(x)}(\frac{I^c(y)}{A^c})) = \tilde{t} \min_c( (x)\min_{y\in\Omega(x)}(\frac{J^c(y)}{A^c})) + (1-\tilde{t}(x))
\tag{公式8}
$$
根据暗通道先验,无雾图像J的暗通道$J^{dark}$趋向于0:
$$
J^{dark}(x) = \min_c( \min_{y\in\Omega(x)}(J^c(y))) = 0
$$
$A^c$一直是一个正数,可得:
$$
\min_c(\min_{y\in\Omega(x)}(\frac{I^c(y)}{A^c})) = 0
\tag{公式10}
$$
将公式10代入公式8中,得到:
$$
\tilde{t}(x) = 1 - \min_c(\min_{y\in\Omega(x)}(\frac{I^c(y)}{A^c}))
\tag{公式11}
$$
由此,得到透射率$\tilde{t}(x)$。
前面有说道,暗通道先验在天空的区域效果不好,不过幸运的是,有雾图像中天空的颜色通常都跟大气光成分A非常相似,由此,在天空区域有:
$$
\min_c(\min_{y\in\Omega(x)}(\frac{I^c(y)}{A^c})) \rightarrow 1 \text{, and } \tilde{t}(x) \rightarrow 0,
$$
在天空区域,图像的透射率趋向于0,这样,公式11就很好的概况了没有天空区域和有天空区域。
在现实生活中,图像中少量的雾能够反映物体的深度信息,所以,我们可以保留一点雾来让图像更加自然一些。
$$
\tilde{t}(x) = 1 - \omega\min_c(\min_{y\in\Omega(x)}(\frac{I^c(y)}{A^c}))
$$
$\omega$一般取0.95。
1.4 大气光成分系数
大气光成分系数一般是借助暗通道图获得的,首先在暗通道图中找出前0.1%的像素位置,再在这些位置中找出最高亮度的点作为大气光成分系数A。
1.5 恢复无雾图像
现在,I、A、T都已知,则无雾图像为:
$$
J(x) = \frac{I(x) - A}{max(t(x), t_0)} + A
$$
其中,$max(t(x), t_0)$主要是防止t值很小时,J值偏大,使得图像过白,一般设置$t_0$为0.1。
2. 我的一个实现
看我文章后,我自己用Python写了一个程序简单实现下。程序放在Github了。同时,我用Flask搭了一个简单的服务,可以直接上传有雾图片得到去雾后的图片,感兴趣的可以去http://tools.pfchai.com看看。