Laplacian Loss

Laplacian loss

先介绍一下背景。

Matting 任务当中在几篇论文里发现一个Laplacian loss,这个loss在论文《Context-aware synthesis for video frame interpolation》中最先出现,这一篇论文主要是研究视频插帧的,需要恢复视频中某一帧的信息,这个任务与抠图在一个方面类似,即非常需要细节特征,原文中对 loss 的描述为:

Whereas the ℓ 1 color loss and the Laplacian loss aim to minimize the color difference, the feature loss focuses on perceptual difference …… the Laplacian loss yield better results since they directly optimize the evaluation metric.

大意为:L1损失和拉普拉斯损失主要目的为最小化颜色信息的差异,特征损失更关注与感官上的不同……拉普拉斯损失由于能够直接优化评估矩阵所以得到了更好的结果。

解读:这段话中包括3个损失,一个L1损失,一个Laplacian损失,一个feature loss,也就是特征损失。我们的关注点是第二个,即Laplacian 损失,这个损失能衡量预测结果与 ground truth 之间对应像素上的颜色差异,并且使用这个损失能够得到更好的结果。

另外,在抠图论文《Context-Aware Image Matting for Simultaneous Foreground and Alpha Estimation》当中对该 loss 的描述为:
This loss function measures the differences of two Laplacian pyramid representations and captures the local and global difference.

也就是说这个 loss 还能捕捉全局以及局部的差异,听起来很强。在该损失后抠图的效果在一些论文实验中表明是得到了一定的提升,在这需要深究一下这个损失究竟起到了什么作用。其形式上定义如下:
l a p _ l o s s = ∑ 2 i − 1 ∣ ∣ L i ( α ^ ) − L i ( α ) ∣ ∣ 1 lap\_loss = \sum 2^{i-1}||L^i(\hat\alpha)-L^i(\alpha )||_1 lap_loss=2i1∣∣Li(α^)Li(α)1其中 L alpha_hat 表示预测出的alpha在 Laplacian loss 金字塔第 i 层的结果(关于这个第 i 层的是什么暂时可以先不管),alpha则表示ground truth 在第 i 层的结果,前面还有个2的幂次项,从形式上看,这个 Laplacian loss 主要工作是在 L1 的基础上乘了一个2的幂次项,并且将多层的结果相加。

再看代码:

def lap_loss(logit, target, gauss_filter, loss_type='l1', weight=None):
        '''
        Based on FBA Matting implementation:
        https://gist.github.com/MarcoForte/a07c40a2b721739bb5c5987671aa5270
        '''
        def conv_gauss(x, kernel):
            x = F.pad(x, (2,2,2,2), mode='reflect')
            x = F.conv2d(x, kernel, groups=x.shape[1])
            return x
        
        def downsample(x):
            return x[:, :, ::2, ::2]
        
        def upsample(x, kernel):
            N, C, H, W = x.shape
            cc = torch.cat([x, torch.zeros(N,C,H,W).cuda()], dim = 3)
            cc = cc.view(N, C, H*2, W)
            cc = cc.permute(0,1,3,2)
            cc = torch.cat([cc, torch.zeros(N, C, W, H*2).cuda()], dim = 3)
            cc = cc.view(N, C, W*2, H*2)
            x_up = cc.permute(0,1,3,2)
            return conv_gauss(x_up, kernel=4*gauss_filter)
        def lap_pyramid(x, kernel, max_levels=3):
            current = x
            pyr = []
            for level in range(max_levels):
                filtered = conv_gauss(current, kernel)
                down = downsample(filtered)
                up = upsample(down, kernel)
                diff = current - up
                pyr.append(diff)
                current = down
            return pyr
        
        def weight_pyramid(x, max_levels=3):
            current = x
            pyr = []
            for level in range(max_levels):
                down = downsample(current)
                pyr.append(current)
                current = down
            return pyr
        
        pyr_logit = lap_pyramid(x = logit, kernel = gauss_filter, max_levels = 5)
        pyr_target = lap_pyramid(x = target, kernel = gauss_filter, max_levels = 5)
        if weight is not None:
            pyr_weight = weight_pyramid(x = weight, max_levels = 5)
            return sum(regression_loss(A[0], A[1], loss_type=loss_type, weight=A[2]) * (2**i) for i, A in enumerate(zip(pyr_logit, pyr_target, pyr_weight)))
        else:
            return sum(regression_loss(A[0], A[1], loss_type=loss_type, weight=None) * (2**i) for i, A in enumerate(zip(pyr_logit, pyr_target)))

其中的 logits 表示预测结果,是一个 [Batch_size, 1, H, W] 形状的tensor,target 表示 ground truth,形状和 logits 相同,gauss_filter 表示一个高斯核,loss_type表示 loss 类型,默认为L1,weight 是抠图任务里专用的一个trimap,我们主要关注前3个参数。

代码阅读下来,以 logits 为例,发现它所做的就是对传入的 logits 使用高斯核进行卷积、下采样、上采样、高斯核卷积,同时还设计了一个金字塔结构对不同尺度的 logits 进行操作。具体过程为:
设 logits 为 X, X 经过高斯核卷积、下采样、高斯卷积,得到X1,接下来以 X1 为输入,同样经过高斯卷积、下采样、高斯卷积,得到 X2,往后依次重复该过程,得到X3,X4,等到图像尺度缩小至X4,再进行上采样等操作,得到 X4’,此时做 X4 与 X4’ 的差,得到一个带有较强边缘信息的特征图。
同样的,ground truth 也要进行这些操作,logits 和 ground truth 计算得到的差异进行比较,再乘以2的幂次项,全部相加,得到 lap_loss。这样多层下来的每一层就是上面提到的第 i 层。

Laplacian loss的原理

开始并没有想到这是关于数字图像处理的问题,只是想到深度学习里有个ASPP模块跟这个很像,于是去找了有关于ASPP的资料,但是得到的结果都是在说ASPP有什么作用,好多资料只是在说ASPP能够获得不同尺度下的特征,能获得全局和局部的特征信息,前面提到的论文里也讲了 Laplacian loss 有这个效果,但是内心并不满足于深度学习那种粗糙的解释,于是找了找不同图像多尺度技术相关的资料,终于是找到了,以下是参考博客: [图像多尺度技术](https://blog.csdn.net/qq_26570133/article/details/78846982) 总得来说涉及到一些通信信号、数字图像处理内容。

首先需要了解一个概念,高斯模糊/平滑,Laplacian loss 里面提到对 logits 首先做了高斯卷积操作。从数学角度看,图像的高斯模糊过程就是图像与正态分布做卷积,在二维卷积里面,一个正方形高斯核的值中间高、四周边缘低,大致呈一个“圆形”:
[ 1 2 1 2 4 2 1 2 1 ] \left[ \begin{array}{c} 1 & 2 & 1 \\\\ 2 & 4 & 2 \\\\ 1 & 2 & 1 \\ \end{array} \right] 121242121 它秉承的一个原则就是弱化离当前像素过远的像素的影响,并对像素内容进行加权求和,由于高斯核呈一种“圆形”的特性,经过它处理的图像能够比其他均衡模糊滤波器更好地保留各个方向的边缘信息(这个可以参考下卷积操作的边缘提取功能 Sobel 算子只能提取竖直或横向的两种边缘特征),但是又能做好平滑处理。它通常使用的场合我目前已知的有对图像模糊/平滑处理,在此之上它还经常使用在缩小图像尺寸的场合,在对图像进行下采样的时候,采样前需要对图像进行低通滤波处理,这样就能保证采样后的图像中不会出现虚假的高频信息。
对此我粗浅的理解是,对图像进行缩放为原来大小的二分之一操作,如果简单地去除每行每列上二分之一的像素,那么就有可能造成图像断裂的情况,即相邻两个像素点明明不应该是边界,但差异巨大,这种就应当是虚假的高频信息,因此在此需要先进行平滑处理,弱化边界上的信号。

这样就应当解释了 loss 函数中的第一步高斯卷积的操作。

高斯金字塔

这个概念表示图像经过循环的高斯平滑和亚采样得到一系列图像,图片的尺度逐渐变小(亚采样表示去除图像行列上的所有偶数行):

图片1 [512 x 512] ——> 图片2 [256 x 256] ——> 图片3 [128 x 128] ——> 图片4 [64 x 64]
这种底部大,顶部小的结构就是金字塔结构。

拉普拉斯金字塔

与高斯金字塔相反,拉普拉斯金字塔是个倒着的金字塔,也就是图片尺度逐级变大,但是这个并不是单纯把图像放大,它要计算 [原图像] 和 [下采样、上采样后图像] 两者差值,得到的结果尺度逐渐变大,形成一个金字塔,后文会有解释。这个上采样的过程为在小尺度图像的偶数行列进行填 0 操作,然后使用 4 倍数值的高斯核进行卷积平滑,得到 2 倍原来尺度的图像。这个 4 倍的高斯核即

[ 4 8 4 8 16 8 4 8 4 ] \left[ \begin{array}{c} 4 & 8 & 4 \\\\ 8 & 16 & 8 \\\\ 4 & 8 & 4 \\ \end{array} \right] 4848168484 这里乘以 4 的理由是,如果图像填 0 后只是使用原高斯核进行卷积,那么相邻像素的差异并不大,图像的边界信息会十分模糊,而这种上采样并不是我们想要的,乘以 4 后能放大像素之间的差异,边界相比与不乘 4 更加清晰。例如填 0 后的图像: [ 0 0 0 0 0 0 5 0 6 0 0 0 0 0 0 ] \left[ \begin{array}{c} 0 & 0 & 0 & 0 & 0 \\\\ 0 & 5 & 0 & 6 & 0\\\\ 0 & 0 & 0 & 0 & 0 \\ \end{array} \right] 000050000060000 使用原高斯核卷积,得到中间一行结果为:
[ 20 22 24 ] \left[ \begin{array}{c} 20 & 22 & 24 \\ \end{array} \right] [202224]使用 4 倍的高斯核中间一行结果为:
[ 80 88 96 ] \left[ \begin{array}{c} 80 & 88 & 96 \\ \end{array} \right] [808896]结果的差异是显而易见的。
解释完 4 倍的高斯卷积核,再回到拉普拉斯金字塔本身,我们提到这是个和高斯金字塔相反的过程,但是高斯金字塔下采样过程中丢失的信息在上采样后并不能完全恢复,丢失信息的情况依然存在,如果直观把原图和下采样、上采样后的图片进行对比,会发现后者仍然模糊,此时用前者减去后者得到的新图像,形成的就是拉普拉斯金字塔。

这个相减的过程,能够更突出显示图像的像素信息,因为高斯核属于低通滤波,图像经过这个操作后得到的结果更加平滑,边界信息相比原图没那么明显(因为图像中高频的边缘部分都被过滤),而原图这些边界信息较为明显,至于非边界部分信号变化不大,因此相减后得到的图像更关注边界的信息,或者说对高频信号更为敏感。

题外话,高斯核用于模糊,拉普拉斯核用于锐化,拉普拉斯金字塔得到的是图像不同尺度的边界信息,因此这里叫 Laplacian loss 也合情合理。

到此为止,我们解释了 Laplacian loss 里下采样和上采样的内容,以及第二个高斯卷积乘以 4 的操作

截止频率因子

在 loss 里我们还看到有个二的幂次项,参考资料里说高斯金字塔相邻两层的截止频率因子为 2 ,但是实在不太懂这是啥意思,后来查了相关概念,以下是我的猜测,但是我估计八九不离十,如果有错请指正:

高斯核进行平滑后图像边缘部分的高频信号频率会被变换为原来的一半左右,也就是说灰度变化梯度变成了原来的一半,那这个时候必须乘 2 来重新放大这些信号的差异,并且层数越高,这个放大因子越大,以 2 的幂次增加。

关于多尺度

loss 里面有多层的机制,按照一些文章的解释,多尺度的图像能够关注到图片的不同细节,比如低分辨率的图像更关注轮廓,高分辨率图像更关注细节。

再回到 Laplacian loss

前面已经分析拉普拉斯金字塔对一些高频信号点异常敏感,那么对于一个预测出的 alpha,如果存在预测错误的点,Laplacian loss 相比于 L1 能更好地检测出来,同时它又具有多尺度的特点,能关注不同层次的信息,因此在抠图任务中理论上应该具备更好的性能,或者说对于细粒度任务,相比 L1 它的作用更大。
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值