起因
最近在做一个图像处理的算法,因为图像太暗,所以需要对图像的亮度进行增强(不考虑噪声的放大)。尝试了网上搜索到的各种方法后,发现它们存在两个问题:容易造成原本较亮的地方过曝,并且参数不好设置。尝试了一些暗光增强的paper的算法后,发现它们又太慢了。这时我想到曾经看过的一篇paper说过,有一种亮度增强的算法是基于去雾来做的,步骤很简单:
1. 将RGB图像取反(关于图像取反,请参考我的这篇博客OpenCV图像取反);
2. 对取反后的图像进行去雾;
3. 将去雾后的图像取反。
其背后的理念是:暗光图像取反后,原本接近黑色的像素就会变成接近白色,整张图像就会类似于有雾的图像。于是对这样的图像进行去雾后,白色的像素就变暗了,再反色后,像素就变亮了!没毛病!
快速去雾算法
说起去雾,恐怕大多数人的第一反应就是鼎鼎大名的何恺明博士的暗通道先验去雾算法。我的第一反应也是这个。但是在了解之后,我发现这种方法速度太慢了,难以应用到我的算法中。于是我开始搜索快速的去雾算法,很快找到了这篇论文《基于单幅图像的快速去雾算法》刘倩, 陈茂银, 周东华(这篇文章中也提到了暗通道先验去雾算法的速度太慢),速度很快,只有O(1)复杂度。
这篇论文我并没有仔细看,而是秉承“拿来主义”的精神,直接根据论文提供的算法流程实现了代码。原因是它的算法流程太简单了,在轻松地实现了代码之后,就没有再看的欲望了~这里贴一下它的算法流程,你们自己看:
源码解释
我把实现的代码放到了GitHub:IBEABFHR(原谅我这个取名废),请点进去看效果图,我这里就不重复放了。我感觉效果还是很好的,暗处的亮度增强得很好,亮处虽然有过曝,但并不是很明显。而且控制亮度的参数很好调整,只要随便找一张图像调整好参数,就可以应用于所有图片了。
运行速度
代码是用OpenCV实现的,同时支持彩色图像和灰度图像。在我的电脑上(CPU: E3-1230 v3)测试,运行100次取平均值,速度如下:
分辨率 | 类型 | 时间 |
---|---|---|
1024×768 | 灰度图像 | 8.77ms |
1024×768 | 彩色图像 | 16.24ms |
1920×1080 | 灰度图像 | 22.61ms |
1920×1080 | 彩色图像 | 40.60ms |
4160×2340 | 灰度图像 | 104.57ms |
4160×2340 | 彩色图像 | 186.14ms |
但是如果你只使用我的算法一次,可能速度要慢得多,原因是第一次取反操作因为未知原因耗费了额外的时间。关于这点,请参看我的这篇博客OpenCV图像取反。
参数调整
这个算法总共有两个可变参数。一个是在step 3中进行均值滤波时的所用的滤波半径radius
,另一个是在step 5中用的ρ
。
radius
参数在某些图像上可以控制对比度,数值越大,对比度越强,但在某些图像上不起作用。这个参数取值不能太小,否则增强后的图像会出现光晕。一般不应小于50或者图像宽度和高度最大值的的1/20。
ρ
控制图像增强的亮度,数值越大,增强后的图像越亮。一般的取值范围为[1.0, 2.0]。在我的实现中,我使用了一种简单选择的策略,请参看源代码,仅供参考。
关于参数的效果及设置,我参考了这篇博客一种可实时处理 O(1)复杂度图像去雾算法的实现,在此进行感谢。