1、论文去雾总体思路
DehazeNet是2016年华南理工大学的研究者提出的一个端到端的深度学习模型,该模型主要通过输入的原始有雾图像拟合出该图所对应的medium transmission map(透射率t值图),并使用引导滤波对t值进行refine,接着通过medium transmission map中前0.1%的值所对应的原始图像的RGB值的均值求取全局大气光值,利用现有的大气散射模型完成图像去雾操作。
文章的主要贡献:
1、通过特殊的网络设计构建了一个端到端的网络,利用原始雾天图像直接拟合对应的透射率图像t,进而达到去雾的目的
2、提出了一个非线性的双边整流线性激活函数模块(BReLu),并验证了它的有效性(减少搜索空间,加速模型收敛)
3、建立了DehazeNet与现有的假设先验之间的联系,并解释了通过自动学习来优化和改善之前的先验假设
2、既有模型简介
2.1 大气散射模型
由上图可知,阳光在物体表面形成反射光 J(x),反射光在穿过雾霾的过程中发生散射,只有部分能量 J(x)t(x) 能到达摄像头。与此同时,阳光也在悬浮颗粒表面散射形成大气光 α 被摄像头接收。因此,摄像头中的成像 I(x) 可由两部分组成,透射的物体亮度 J(x)t(x) 和散射的大气光照 α(1-t(x))。
大气散射模型是图像去雾的核心公式,由上述描述可知,最终到达镜头呈现出来的图像包含两部分:透射的物体亮度 J(x)t(x)以及散射的大气光照 α(1-t(x)),具体公式如下所示:
2.2 既有先验模型
(1)暗通道先验
参考之前的文章:Single Image Haze Removal Using Dark Channel Prior(暗通道先验)
(2)最大对比度方法
雾霾会降低物体成像的对比度:Σx‖ΔI(x)‖=tΣx‖ΔJ(x)‖≤Σx‖ΔJ(x)‖。因此,基于这个推论可利用局部对比度来近似估计雾霾的浓度。同时,也可以通过最大化局部对比度来还原图像的颜色和能见度
(3)颜色衰减先验
颜色衰减先验(CAP)是一种与暗通道先验(DCP)相似的先验特征。观察发现雾霾会同时导致图像饱和度的降低和亮度的增加,整体上表现为颜色的衰减。根据颜色衰减先验,亮度和饱和度的差值被应用于估计雾霾的浓度
(4)色调视差
3、DehazeNet总体概况
模型的整体架构包含四个大块,分别是特征提取,主要是通过卷积+maxout激活函数;多尺度特征映射,主要借鉴xception网络,使用3、5、7三种不同大小的卷积获取不同感受野的特征并进行通道拼接;局部极值,利用maxpooling完成极值的求解;非线性回归,使用一个6*6的卷积+BReLU完成非线性映射。
3.1 特征提取
传统图像提取特征都会需要一定的假设和先验,但是这些手工设计的或者假设的特征并不是在所有情况下都适用。在观察了暗通道先验、最大对比度先验、颜色衰减先验的实现原理后,作者提出可以使用相对应的卷积核去卷积原始图像并加上非线性激活后的特征等效代替上述先验特征。此处使用maxout激活函数主要是将通道分段,提取不同的通道的最大值,结合不同的卷积核,可以得到类似暗通道先验、最大对比度先验、颜色衰减先验等的效果,并且可以带来更强的拟合性能。
此处的卷积使用的是5*5的卷积核,输入是3通道输出是原始输入图片的宽(输入数据大小16*16),激活函数是maxout,该激活函数和普通的激活函数不太一样,如下为对比
对于普通的激活函数,z=w*x+b而言,out=f(z),其中f就是我们常用的激活函数,比如ReLU,Sigmod等
针对maxout不一样的点在于,如果我们设置maxout的组数K为5,则会在每个神经元的前面多出一层,这一层有5个神经元,如下图所示。
那么maxout的计算公式就变成了:
z1=w1x+b1
z2=w2x+b2
z3=w3x+b3
z4=w4x+b4
z5=w5*x+b5
最终的输出为out = max(z1,z2,z3,z4,z5)
差别就在于:常规的激活函数主要针对单个神经元,比如ReLU,输出的max(0,x);而针对maxout这样的激活函数,是将多个神经元分为一组,整体求最大值。maxout相对其它激活拥有更好的拟合效果
3.2 多尺度映射
多尺度特征在图像去雾中应用广泛,原因是它可以获取尺度不变性,使得获取的特征更加鲁棒,受inception模块的启发,作者使用3*3,5*5以及7*7的卷积核去获取不同的特征,并进行聚合,增强特征对多尺度物体的泛化能力。
3.3 局部极值
使用局部极值的原因类似于其它先验算法里面的假定局部透射率不变作用一样,文中使用maxpool去代替之前的局部透射率不变先验操作,这里使用的是7*7的局部区域。
3.4 非线性回归
图像恢复领域,最后一层的输出值一般是上限和下限处于一个小范围的,sigmoid以及relu都不太适合作为激活函数,前者由于梯度爆炸问题,后者由于无上限都不适合,本文提出使用BReLU激活函数,限制激活后的值处于tmin以及tmax之间,实际有点类似Hardtanh函数,作者在实现的时候也是继承这个函数去实现的。
3.5 网络设计结构
3.6 存在的问题以及后续改进
1、全局大气光值A不能当作一个常量对待,后续可以像学习透射率转换参数t一样包含在统一的网络中进行学习
2、大气散射模型也可以通过模型直接学习,完全摒弃人工设计
4、参考源码
https://github.com/zlinker/DehazeNet/blob/master/DehazeNet.py
https://github.com/thuBingo/DehazeNet_Pytorch
深度学习(二十三)Maxout网络学习
下述代码是实现DehazeNet的网络结构,总体比较简单,需要引起注意的是maxout以及BReLU的实现。
class BRelu(nn.Hardtanh):
def __init__(self, inplace=False):
super(BRelu, self).__init__(0., 1., inplace)
def extra_repr(self):
inplace_str = 'inplace=True' if self.inplace else ''
return inplace_str
class DehazeNet(nn.Module):
def __init__(self, input=16, groups=4):
super(DehazeNet, self).__init__()
self.input = input
self.groups = groups
self.conv1 = nn.Conv2d(in_channels=3, out_channels=self.input, kernel_size=5)
self.conv2 = nn.Conv2d(in_channels=4, out_channels=16, kernel_size=3, padding=1)
self.conv3 = nn.Conv2d(in_channels=4, out_channels=16, kernel_size=5, padding=2)
self.conv4 = nn.Conv2d(in_channels=4, out_channels=16, kernel_size=7, padding=3)
self.maxpool = nn.MaxPool2d(kernel_size=7, stride=1)
self.conv5 = nn.Conv2d(in_channels=48, out_channels=1, kernel_size=6)
self.brelu = BRelu()
for name, m in self.named_modules():
if isinstance(m, nn.Conv2d):
nn.init.normal(m.weight, mean=0, std=0.001)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
def Maxout(self, x, groups):
x = x.reshape(x.shape[0], groups, x.shape[1] // groups, x.shape[2], x.shape[3])
x, y = torch.max(x, dim=2, keepdim=True)
out = x.reshape(x.shape[0], -1, x.shape[3], x.shape[4])
return out
def forward(self, x):
out = self.conv1(x)
out = self.Maxout(out, self.groups)
out1 = self.conv2(out)
out2 = self.conv3(out)
out3 = self.conv4(out)
y = torch.cat((out1, out2, out3), dim=1)
y = self.maxpool(y)
y = self.conv5(y)
y = self.brelu(y)
y = y.reshape(y.shape[0], -1)
return y
文中生成数据集的小tips:
由上述文献可知:使用一张无雾的图片J(x),随机设置透射率参数t,并将全局大气光A设置为1,可以直接获取带雾图片,顺带还可以获取相应透射率参数作为训练获取的gt值。