项目主页:CAIP2017 (baidut.github.io)

项目代码:AndyHuang1995/Image-Contrast-Enhancement: Python implementation of "A New Image Contrast Enhancement Algorithm Using Exposure Fusion Framework", CAIP2017 (github.com)

笔者按:最近风格化的项目暂且告一段落,开始往HDR的方向进发。在开始阶段先不追求真HDR,只是尝试对图像的对比度进行改善(过曝和欠曝的优化),偶然在github上看到了这篇文章,其主页的效果非常吸引人,整个算法框架也肥肠简单,所以就看一下这篇论文,顺便把论文笔记记录下来,可能会顺便放一些自己的思考进去。

摘要

算法步骤大体分为4步。

第一步,设计了一个用于图像alpha融合的权重矩阵

第二步,使用相机响应模型生成多曝光图像

第三步,找到最佳曝光率,使得原图中曝光不佳的区域well exposed

第四步,根据前面估计得到的权重矩阵,融合两个图像

1 引言

其实最早的对比度增强方法是依赖于某些非线性的映射函数来实现的,比方说指数函数,对数函数等等。这种方法对于不同场景往往需要拟合不同的函数,很不科学。

最近的对比度增强方法主要分为三个分支:

1 基于直方图的方法——因为不同灰度level的pixel分布是肥肠不均匀的,所以通过适当的均衡就可以达到对比度提升的效果

2 基于retinex理论的方法——是一种基于人的视觉模型的理论,将场景照明分为了反射光和场景光。但实际应用中往往会出现环状伪影。

3 基于去雾理论的方法——个人认识:确实可以提升对比度,但是这类算法其初衷往往是去雾,在有雾的区域确实可以实现对比度提升,但是和这篇文章能达到的提升暗部亮度的效果是不一样的。

其实除了作者提的这三个方向,也有一些类似于本文的思路,基于fusion的对比度提升算法,比如著名的Google HDR

后面就简单说了一下在这个领域其实没有特别统一的评价标准,以及描述了一下本文提出的算法框架。

2 方法论

2.1 算法框架

这个算法框架肥肠简单,基本思路就是一个欠曝图像,一个过曝图像,二者做一个alpha混合。(这里说的过曝和欠曝是相对而言的,并非绝对的过曝、欠曝)。

图像对比度增强 python 图像对比度增强的目的_图像处理

把这个过程写成式子就是

图像对比度增强 python 图像对比度增强的目的_计算机视觉_02

R是结果,W是权重,P是不同的曝光图像,N代表有N个level的曝光图像,c是颜色通道。 

需要注意的是,对于同一个pixel,不同的曝光set下,其权重之和为1

现在,这个问题就分解成为了两个子问题:

1)求不同曝光的图像Pi

2)求这些照片对应的权重

在作者之前的工作中,曾经提出过一个相机响应模型

图像对比度增强 python 图像对比度增强的目的_计算机视觉_03

其中ki是曝光率,g是brightness transform function,简称BTF。 

在本文中,作者进一步简化了式子(1),让N=2,则(1)式写为

图像对比度增强 python 图像对比度增强的目的_图像对比度增强 python_04

即,作者假设原照片是欠曝的,需要搞一个过曝图像,两者来混合。(如fig.2)

在这个式子中,W,g,k都是未知的,后面就来解决这三个未知数。

2.2 权重W估计

简单来说,well exposed的像素,权重就应该大。

并且由于作者假设,原图像是相对欠曝的,那么可以得到一个推论——较亮的区域其曝光应该是相对正常的(见fig.2中上图)。因而,作者定义,

图像对比度增强 python 图像对比度增强的目的_图像处理_05

其中T是场景照明(scene illumination),μ是一个控制系数。

可惜的是,这里的T仍然是未知的。所以接着我们要估计T。

这里作者又提出一个先验:即理想的照明场是具有局部一致性(local consistency)的——即,在结构上,和局部的明度成正相关,但是并不具有具体的纹理信息。说人话,就是这个照明场应该是笼统的,平滑的,亮的地方亮一坨,暗的地方暗一坨,并不会因为你穿了条纹毛衣就出现纹理。

为了估计这个照明场T,首先初始化一个illumination map L

图像对比度增强 python 图像对比度增强的目的_sed_06

然后为了使T满足上述要求,这里设置了一个能量方程,通过优化这个能量方程来得到T

图像对比度增强 python 图像对比度增强的目的_sed_07

其中 ||∗||2 和 ||∗||1 是 L2 和 L1 范数,∇是一个一阶导数算子,实际上就是梯度。λ是控制参数。

在式子(6)中,第一项保证了T与L的结构相似度,第二项保证了T具有局部一致性。

然鹅鹅鹅鹅鹅鹅,在式(6)中,又有一个未知量M,并且这个M实际上对于scene illumination map的refine很重要。

仔细看第二项,∇仅仅是一个一阶导数算子,它并无法分辨当前的梯度到底是主要边缘,还是局部纹理。所以应该仔细设计M——包含重要边缘的local patch中,M应该小一点,这样在最小化式子(6)的时候,第二项的权重就会减小,就会对T的梯度信息要求不那么严格,这样就可以让T保留重要的边缘信息;而仅仅包含纹理的local patch中,M则应该大一点,这样在最小化式子(6)的时候,第二项的权重就会增加,就会严格要求T是平坦的,进而忽略纹理信息。

M被定义为:

图像对比度增强 python 图像对比度增强的目的_权重_08

即,作者认为,总梯度大的地方,包含重要边缘,梯度要大一些,M应该小一些,总梯度小的地方反之(这里是否合理?)

为了简便和降低复杂度,结合(6)和(7),我们写出这个能量方程的完整形式:

图像对比度增强 python 图像对比度增强的目的_sed_09

可以看到主要变化是第二项中又增加了一个分母,是L中该点的梯度:这也很好理解,Md是一个local patch上的权重,而这个权重应该也和当前点有关。在某个给定的local patch中,如果该点正好在边缘上,梯度较大,那么第二项的权重减小, T也可以保留一个较大的梯度;还是在这个给定的local patch里,如果该点正好不在边缘上,那么第二项权重增加,T就不能保留太多梯度信息。

换言之,Md蕴含的的是Local patch的总信息,而第二项的分母蕴含的是当前的pixel的信息。

(不过还是吐槽一下,为什么不把这个分母和Md写到一起)

式子(8)其实就是一个二次函数,可以直接通过二次方程的相关定理得到最小值

作者给了一个矢量形式的能量方程(再吐槽一下,这个式子并没有上面的式子看起来清晰易懂,实际解起来也未必有上面的快)

图像对比度增强 python 图像对比度增强的目的_sed_10

其中🚫符号代表逐元素除法,I是单位矩阵,算子Diag(v)是用向量v构造对角矩阵,Dd是从具有前向差分的离散梯度算子中得到托普利兹矩阵。我们的光照图估计方法与 [5] 中的主要区别在于权重矩阵 M 的设计。我们采用了一种简化的策略,可以产生与 [5] 中类似的结果。在这里可以借用其他基于 Retinex 的方法中的光照分解技术来找到权重矩阵 W。

2.3 相机响应模型(g估计)

作者的早期工作中提出了这个模型

图像对比度增强 python 图像对比度增强的目的_权重_11

可以看为一个gamma模型,建议参数a = −0.3293,b = 1.1258

2.4 曝光率估计(k估计)

这里,为了估计得到最佳的曝光率,首先要知道原图像中哪些像素是well-exposed的,哪些像素是under-exposed的。这里引用上面2.2中求得的T,则将under-exposed的像素定义为T<0.5的像素:

图像对比度增强 python 图像对比度增强的目的_sed_12

在不同的曝光条件下,图像的亮度曝光很大,但颜色基本相同,因此在估计曝光率的时候,通常只考虑亮度分量。这里将亮度分量定义为三个通道的几何平均值:

图像对比度增强 python 图像对比度增强的目的_图像对比度增强 python_13

(这里为什么不干脆转换到类似Lab、YUV或者HSV空间之后单独对表示亮度的轴进行处理?)

(另外,上述2.2节,在优化T的时候,按理说应该三个通道最终只得到一个T,那么根据式子(11),应该只有一个Q,这里为什么会有Qr、Qg、Qb三个分量?) 

对于这里为什么用几何平均值而不是其它的平均值,作者给出了解释:用几何平均值的话,可以得到与式子(10)中所述的相机响应模型相一致的形式:

图像对比度增强 python 图像对比度增强的目的_计算机视觉_14

在得到亮度分量后,作者给出了一个先验:曝光良好的图像其蕴含的信息量更大。B蕴含的信息量可表示如下:

图像对比度增强 python 图像对比度增强的目的_权重_15

那我们要做的就是通过求得一个k,来使得图像所能蕴含的信息量最大,这个过程可以写作优化一下方程:

图像对比度增强 python 图像对比度增强的目的_图像处理_16

作者额外提到,在优化式子(15)求解时,可以将图像resize到很小的程度(文中给的时50*50)以加速这个过程,因为resize这个行为不会对信息量产生过大的影响。

3 实验 

3.1 实现细节(参数选择)

Eq.4中的μ:当μ=0的时候,R=P,即不执行增强。当μ=1的时候,图像中under-exposed的图像和well-exposed的像素都会得到增强。当μ>1的时候,像素可能会产生过饱和现象,而算法结果也有可能损失细节。建议值:μ=0.5

其它的建议参数:

λ=1

ε=0.001

μ=0.5

size of ω(x) = 5

在Eq.8、9的优化求解T的过程中,也可以将图像下采样来求T,而后再resize回去。

个人思考/疑问

Q1

在式(7)中,作者提出,在一个local patch上,求Md的时候,这个local patch中的总梯度越大,那么就认为这个区域包含的重要边缘越多,就要在优化过程中降低对梯度的约束的权重,使得优化得到的答案也具有更丰富的梯度信息。

这里有一个问题,就是说,如果对于local的肥肠复杂的纹理,举个例子:波点卫衣,是不是也会导致生成的scene illumination map保留很多的梯度信息(而这真的是我们所需要的吗)?

关于解决方法,个人有一点愚见,即在local patch上为梯度设计权重时,要考虑到local patch的梯度的连通性,连通性越大,则表示这个边缘才是主要边缘。而连通性很小的时候,则因该认为是噪声,或者重复性纹理,不应该认为其是主要边缘。

Q2

在Eq.7和Eq.8中,主要变化是第二项中除了Md又增加了一个分母。Md蕴含的的是Local patch的总信息,而这个分母蕴含的是当前的pixel的信息。

式子7和8应该是可以写在一起的,即,把Eq.7改写为:

 

图像对比度增强 python 图像对比度增强的目的_sed_17

而相应地,Eq.8改写为

图像对比度增强 python 图像对比度增强的目的_权重_18

Q3

关于二次项形式和矢量形式哪个快,这里只是提出一个疑问,稍后实现代码的时候会做一个比较。

Q4

在定义亮度的时候,为什么不转到LAB等颜色空间表示?令人疑惑。似乎只是为了让整个式子能够满足2.3中提出的相机响应函数?

Q5

在优化T的时候,按理说应该三个通道最终只得到一个T,那么根据式子(11),应该只有一个Q,这里为什么会有Qr、Qg、Qb三个分量?

这是本文最大的疑问。因为根据Eq5,三个通道只能估计得到一个L,而后面T的优化过程中,T又只和L有关,也就是说,三个通道公用一个T。根据Eq11,每个T又对应一个Q,那么三个Q从何而来?

个人在后面尝试实现的时候会将图像转到YUV或其它几个空间,但后用单独的亮度通道进行实现。

Q6

这个方法只提到了对图像中欠曝区域的增强(提亮),并没有将对over-exposed的像素的高光抑制。后面将会尝试将Eq.11反向选择生成Q,并生成一个高光压制的版本,然后将整个algorithm扩展到三个图像的fusion,观察效果。

其它在实验结果中值得注意的方法

(1)Dong, X., Wang, G., Pang, Y., Li, W., Wen, J., Meng, W., Lu, Y.: Fast efficient
algorithm for enhancement of low lighting video. In: 2011 IEEE International Con-
ference on Multimedia and Expo. pp. 1–6. IEEE (2011)

(2)Wang, S., Zheng, J., Hu, H.M., Li, B.: Naturalness preserved enhancement algo-
rithm for non-uniform illumination images. IEEE Transactions on Image Process-
ing 22(9), 3538–3548 (2013)