2020CVPR_Zero-Reference Deep Curve Estimation for Low-Light Image Enhancement 网络Zero-DCE
1. motivation
受到图像编辑软件的启发
2. Contribution
(1)无监督
(2)设计图像高阶曲线适应适合像素级映射,通过迭代自身
(3)设计了四个无参考损失函数
3. Network
3.1 DCE-Net
DCE-Net: 是由6个Conv2D(3x3)+ relu,分别输出为x1,x2, x3, x4, x5, x6,最后的卷积由Conv2d(3x3)+tan激活函数组成,因为要分为8个调整参数,所以最后的输出channel=24
之后进高阶曲线调整
3.2 LE(Light-Enhancement Curve)
设计的高阶曲线必须满足的条件:(1)每个像素归一化(0,1) (2)像素应该单调,这样可以保持和附近像素的差异(对比度) (3)简单、可微(因为需要反向传播)
需要n次迭代(代码中迭代了8次):
α设置为像素级参数调整
4. Loss
4.1 L-spa :空间一致性损失
i 代表像素, Ω代表区域(上下左右),K代表区域总数(4)
代码对于Yi - Yj 左是用二维卷积操作中卷积核实现:
kernel_left = torch.FloatTensor([[0, 0, 0], [-1, 1, 0], [0, 0, 0]]).cuda().unsqueeze(0).unsqueeze(0)
代码实现:
(1) 首先计算low和enhanced后图片按照dim=1,计算通道均值并保持维度一致
(2) 采用了一个二维平均池化nn.AvgPool2d(4),得到org_pool,enhance_pool
(3) 利用二维卷积操作F.conv2d分别计算Yi - Yj (=a) 、Ii - Ij(=b) 的上下左右
(4) 按照上下左右计算a - b 再平方
(5)对(4)累加
4.2 L-exp: 曝光控制损失
E:代表平均曝光水平,作者在代码中E=0.6,但是论文中提到其实E取【0.4,0.7】没有区别
M:表示大小为16×16的非重叠局部区域的数量
代码实现:
(1) 对于enhanced, 首先按照dim=1 取得每个通道的均值x
(2) 对于(1)进行了一个二维平均池化nn.AvgPool2d(16)得到mean,卷积核设置的是16(我猜测因为图片大小256,这样得到一个四维的值[[[[x]]]])
(3) mean - E 平方后取平均
class L_exp(nn.Module): def __init__(self, patch_size, mean_val): super(L_exp, self).__init__() # print(1) self.pool = nn.AvgPool2d(patch_size) self.mean_val = mean_val def forward(self, x): b, c, h, w = x.shape # 对输入张量 x 在通道维度上进行平均操作,得到一个形状为 (b,1,h,w) 的张量,表示每个像素的颜色平均值(黑白图像) x = torch.mean(x, 1, keepdim=True) # 利用 nn.AvgPool2d() 函数在空间维度上对这个张量进行平均操作,得到一个形状为 (1,1,1,w) 的张量, # 表示每个均值区域的平均颜色。其中,patch_size 参数指定了每个均值区域的大小。 mean = self.pool(x) print(mean.shape) # 计算每个均值区域与给定平均颜色之间的差异,并通过 mean() 函数对所有元素求平均,得到色差损失 d = torch.mean(torch.pow(mean - torch.FloatTensor([self.mean_val]).cuda(), 2)) return d
4.3 L-col: 颜色一致性损失 对对增强后的图像进行颜色一致性损失 J代表增强后的图像,pq代表两个通道
Jp表示增强图像中p通道的平均强度值,(p,q)表示一对通道
代码实现:
(1) 先按照dim[2,3] 得到每个通道的均值mean_rgb
(2) 按照dim=1采用torch.split,分离三个通道得到mr, mg, mb
(3) 分别计算两个通道之间的差值进行平方,得到Drg,Drb, Dgb
(4)计算一个彩色差 k,通过组合Drg、Drb 和 Dgb 各自的平方和,再求开根号即可
4.4 L-tv: 光照平滑损失 : 是对进行高阶曲线像素映射系数进行计算Loss
N为迭代次数,∇x和∇y分别表示水平和垂直梯度操作。