Hierarchical Dynamic Filtering Network for RGB-D Salient Object Detection 论文解读
该论文发表在ECCV2020。
论文地址:https://arxiv.org/pdf/2007.06227.pdf
项目地址:https://github.com/lartpang/HDFNet
文章目录
-
简介
-
动机
-
方法
-
- Two Stream Structure
- Dynamic Dilated Pyramid Module
- Hybrid Enhanced Loss
-
实验
-
海报展示
简介
这是一篇关于RGB-D显著性目标检测的工作,该研究课题的关键点在于如何充分融合和利用跨模态的信息(深度图的结构信息)来有助于目标检测的任务。
本文的贡献主要在于两点:第一点是利用动态滤波 的方法并设计出一个新颖的动态空洞金字塔模块 ,该模块能够更好地融合不同尺度的跨模态信息;第二点设计出一个混合增强损失函数 ,使得预测结果能够产生更加清晰的边缘和具有一致性的显著区域。
动机
- 现有的基于FCN的显著性目标检测(不涉及深度图)的工作,在处理复杂或者低对比度的场景时没有优势。为了克服这个问题,引入深度图可以进一步提升目标检测的表现。
- 在RGB-D目标检测的任务中,其一大挑战是如何利用这样的深度信息。
- 在RGB-D的任务中,RGB图像包含风度的细节信息而深度图则包含更多的空间结构信息,因此两者可以相互补充。
- 现有的显著性目标检测的算法在测试时,针对不同的样本使用的是固定的参数,这就使得模型的泛化能力大大地降低。此外,对于该任务每一个位置的预测结果的损失是不用的,所以,在不同位置上的梯度优化的方向应该是不同的。为了解决这一问题,本文提出动态空洞金字塔模块,使用RGB-D的混合特征来自适应的调整卷积核,处理不同的输入样本和位置。
- 早期的基于学习的SOD方法是简单使用全连接层,但是却破坏了数据的空间结构信息。后来,使用FCN缓解了这一问题。但是其本质上的gridding operation和down-sampling 操作使得很多细节信息都丢失。在本文中,作者提出混合增强损失函数,分别来对显著物体的主体区域和边缘部分进行约束,最终得到更好的预测结果。
方法

Two Stream Structure
如图2所示,它是一个two-stream网络结构,其输入是深度图和RGB图像。
首先,两者分别经过一个具有相同网络结构的编码网络(这里可以使用VGG-16,VGG-19,ResNet-50)得到不同尺寸的中间特征。考虑到计算代价和噪声,作者这里处理后三个尺度的特征:f_d^3,f_d^4,f_d^5;f_{rgb}^3,f_{rgb}^4,f_{rgb}^5
然后,使用密集块(denseBlock)对f_d^i,f_{rgb}^i;其中i=3,4,5进行融合得到更强的特征表达{f_T}_m
最后,将该特征送入DDPM模块中产生多尺度的卷积核,以此来和RGB分支中的解码器的特征做滤波操作得到特征f_M并且使用该特征与编码器中特征以element-wise addition的方式进行合并。
Dynamic Dilated Pyramid Module


由图2所示,DDPM的目的是为decoder部分的特征提供自适应的kernel。
首先,作者使用kernel generation units (KGUs)来产生相互之间独立的tensor,KGU由四个密集连接层组成。然后,使用kernel transformation units (KTUs)对kernel进行转换并设置不同的空洞率。下面代码是dilation=1的情况。最后按照算法1得到最终的features并进行融合。
多尺度的处理情况描述如下:

class DepthDC3x3_1(nn.Module):
def __init__(self, in_xC, in_yC, out_C, down_factor=4):
"""DepthDC3x3_1,利用nn.Unfold实现的动态卷积模块
Args:
in_xC (int): 第一个输入的通道数
in_yC (int): 第二个输入的通道数
out_C (int): 最终输出的通道数
down_factor (int): 用来降低卷积核生成过程中的参数量的一个降低通道数的参数
"""
super(DepthDC3x3_1, self).__init__()
self.kernel_size = 3
self.fuse = nn.Conv2d(in_xC, out_C, 3, 1, 1)
self.gernerate_kernel = nn.Sequential(
nn.Conv2d(in_yC, in_yC, 3, 1, 1),
DenseLayer(in_yC, in_yC, k=down_factor),
nn.Conv2d(in_yC, in_xC * self.kernel_size ** 2, 1),
)
self.unfold = nn.Unfold(kernel_size=3, dilation=1, padding=1, stride=1)
def forward(self, x, y):
N, xC, xH, xW = x.size()
kernel = self.gernerate_kernel(y).reshape([N, xC, self.kernel_size ** 2, xH, xW])
unfold_x = self.unfold(x).reshape([N, xC, -1, xH, xW])
result = (unfold_x * kernel).sum(2)
return self.fuse(result)
Hybrid Enhanced Loss
总损失如下:

其中,



实验

海报展示


















