CURL: Nerual Curve Layers for Global Image Enhancemet
ICPR 2020
华为诺亚方舟实验室出品
创新点
在 Photoshop 中我们可以通过在调节图像在不同颜色空间中的映射来对图像进行增强,如下图所示,在原图模式下,映射曲线为 y=x,通过鼠标调整曲线后,可能会变成 y=05x,甚至是复杂一些的二次三次的映射
https://www.cambridgeincolour.com/tutorials/photoshop-curves.htm
基于这个启发,作者想是否可以设计了一个神经网络,他预测三个不同的颜色空间(HSV, CIELab, RGB)的映射曲线来对图像进行增强。
个人认为,该方法的优点是传统图像操作与 Ai 的结合,便于落地实现
缺点在于并没有考虑通道之间的交互,效果会差些,我之前的文章有解析过 Image-Adaptive 3DLUTs 的方法则是同时考虑了 RGB 三个通道之间的信息。
网络架构
文中提出的方法架构如下图所示,原图会先输入到一个 TED 的类UNet网络,输出会作为 CURL 的输入,最后获得增强后的图片
TED: Transformed Encoder-Decoder for Local Image Adjustment.
因为在对图像做局部增强时,需要考虑全局和中间层的特征从而避免预测图像空间不一致的问题,因此作者对传统的 UNet 进行了改进,并取了个新名字叫 TED,如下图所示
通过这个 TED 架构图,我们可以看到都三条并行的卷积通道,其中第一条是提取全局特征的,第二和第三条提取的是中间层特征,最后把原图和这三条卷积的结果 concat 到一起后再经过卷积获得与原图输入尺寸一致的特征(FHxFWxC)给到后续的 CURL
关于具体的实现细节可以看看源码
CURL: Neural Curve Layers for Global Image Adjustment
CURL 做的事情是接收 TED 的输出作为输入,然后按顺序执行三个卷积块,这三个卷积块会分别会输出 Lab, RGB, HSV 三个颜色空间上的映射曲线,分别在原图上应用这三个映射曲线来达到增强的目的
具体的这三个卷积块是如何运作的作者也画了个示意图
最核心的问题是网络是怎么输出映射曲线的,怎么作用到原图上,我看完源码后,感觉就是获得了三个线性变换的参数,但看原论文描述感觉好像又不是这么回事…
具体的实现代码在 util.py 里,函数为 apply_curve
@staticmethod
def apply_curve(img, C, channel_in, channel_out):
"""Applies a peicewise linear curve defined by a set of knot points to
an image channel
:param img: 需要被增强的图片
:param C: 映射曲线上分段点数,是一维tensor,shape=[n]
:param channel_in: 处理通道
:param channel_out: 输出通道
:returns: 增强后的图片
:rtype: Tensor
"""
slope = Variable(torch.zeros((C.shape[0]-1)))
curve_steps = C.shape[0]-1
'''
计算相邻分段点之间的距离
'''
for i in range(0, C.shape[0]-1):
slope[i] = C[i+1]-C[i]
'''
这里就是计算线性映射值 Scale 的地方,没太看懂,感觉就是把每个分段线性的斜率
进行了一个相加
'''
scale = float(C[0])
for i in range(0, slope.shape[0]-1):
scale += float(slope[i])*(img[:, :,channel_in]*curve_steps-i)
img_copy = img.clone()
# 最后,原图乘于这个 Scale 值就完成了增强
img_copy[:, :, channel_out] = img[:, :, channel_out]*scale
img_copy = torch.clamp(img_copy,0,1)
return img_copy
损失这块,会先把增强后的预测图转换成不同颜色空间然后再计算 L1 来衡量pixel-wise 的差异
但有一点不同在于用到了 cosine 度量,查了一些资料后,该度量作用是因为三维颜色空间中,如果只使用 L1 或者 L2 度量,以目标为中心的某一个半径的球面上,loss 值都是一样的,如下图所示,然而位于同一个球面上的结果在人类主观上看来的感受是不一样的。
所以,除了度量L1、L2距离,还应该度量输出与目标的夹角。最直接能想到的就是在rgb空间的使用cosine度量,下面是大致的代码实现
...
# rgb 下的 cosine 值损失
cosine_rgb_loss_value += (1-torch.mean(
torch.nn.functional.cosine_similarity(predicted_img, target_img, dim=0)))
...
# hsv 下的值损失
target_img_1 = target_img_val * \
target_img_sat*torch.cos(target_img_hue)
target_img_2 = target_img_val * \
target_img_sat*torch.sin(target_img_hue)
...
效果评估
老样子,评估指标还是 PSNR 和 SSIM,数据集也是 Adobe Five 5k,结果如下
对比上一篇的 Image-Adaptive 3DLUT,其 PSNR 指标都还没他高,不知道为何这里没有进行横向对比
参考资料
原文链接
https://arxiv.org/abs/1911.13175
手机端高分辨率人像照片增强在快手人像美化的应用
https://mp.weixin.qq.com/s/AHat5HZoCkfe04to2jBJeA