AdaBins:Depth Estimation using Adaptive Bins
文章目录
- 一、AdaBins处理的问题
- 二、AdaBins整体架构
- 1.MVIT
- 2.个人理解
一、AdaBins处理的问题?
并同时探讨了全局信息处理如何有助于提升整个深度估计的效果的问题。设计了一种基于变换机制的模块化架构,并通过将每个面元中心的位置作为权重系数进行加权求和得到最终深度值。该架构能够根据图像自身特性动态确定中心位置,并划分成多个子区域对各区域内的特征进行独立建模以实现精确预测。

这是论文中所展示的真实深度分布图和预测生成的深度分布图。若两个图像在深度分布特征上趋于一致,则系统损失已降至相对稳定水平。
二、AdaBins整体架构

文章主要运用了经典的编码解码组件Encoder:EfficientNet B5(此处无需赘述),其中在Decoder生成的特征图经由特定路径输入至本文提出的mVIT模块中这也构成了本文的关键内容之一
1.MVIT

在decoder模块中生成了feature-map channel=128后,经过两个分支处理后,在深入分析底部Transformer模块之前
class PatchTransformerEncoder(nn.Module):
def __init__(self, in_channels, patch_size=10, embedding_dim=128, num_heads=4):
super(PatchTransformerEncoder, self).__init__()
encoder_layers = nn.TransformerEncoderLayer(embedding_dim, num_heads, dim_feedforward=1024)
self.transformer_encoder = nn.TransformerEncoder(encoder_layers, num_layers=4) # takes shape S,N,E
self.embedding_convPxP = nn.Conv2d(in_channels, embedding_dim,
kernel_size=patch_size, stride=patch_size, padding=0)
self.positional_encodings = nn.Parameter(torch.rand(500, embedding_dim), requires_grad=True)
def forward(self, x):
embeddings = self.embedding_convPxP(x).flatten(2) # .shape = n,c,s = n, embedding_dim, s
# embeddings = nn.functional.pad(embeddings, (1,0)) # extra special token at start ?
embeddings = embeddings + self.positional_encodings[:embeddings.shape[2], :].T.unsqueeze(0)
# change to S,N,E format required by transformer
embeddings = embeddings.permute(2, 0, 1)
x = self.transformer_encoder(embeddings) # .shape = S, N, E
return x
该研究者开发出了一种简化的ViT架构,在该框架中,通过深度可分离卷积模块将feature_map x进行编码映射,从而生成与Transformer架构兼容的空间特征表示
类似于ViT的操作,在操作中加入了位置编码,并将输入数据依次传递到4个Transformer Encoder层中。具体实现细节可参考ViT代码库中的相关内容。输出结果为S \times B \times 128的特征图,在demo实验中设置S=15\times20=300
Bin widths = x[0,:] # 1x128
query = x[1:128+1,:,:] # 128xBx128
query经过permute -- >Bx128x128 #后面的128是维度
如果将此时的query再次经过permute(0,2,1) 此时中间的128是维度
接下来分析MVIT模型中的一部分支, 其中特征图通过3×3大小的卷积核进行处理, 结果与查询向量完成点积运算。
feature\_map^\top通过与 query 进行矩阵相乘生成 range_attention_maps 的大小为 B \times (H\times W) \times 128。
看一下此时的range_attention_map图左与最终图右区别


接着将上述的map图通过3个linear层,得到 bin_widths_normed = 1*256
range_attention_map通过卷积层计算得到与bin_widths_normed具有相同尺寸结构的输出,并且其空间分辨率保持一致
**out=**range_attention_map
bin_widths可以通过最大和最小值来计算得出,并*bin_widths_normed被划分为256份
采用取该bin中间位置为中心点的方式进行回归计算,并在左侧新增一个具有最小深度的depth bin,在此过程中该区域共有257份分片
通过torch.cumsum 可以得到深度bin的边界(从min_depth开始)
详情参考代码
bin_widths = (self.max_val - self.min_val) * bin_widths_normed
bin_widths = nn.functional.pad(bin_widths, (1, 0), mode='constant', value=self.min_val)
bin_edges = torch.cumsum(bin_widths, dim=1) #torch.cumsum 第一列不变,其他每一列累加至最后一列
centers = 0.5 * (bin_edges[:, :-1] + bin_edges[:, 1:])
# bin_edges[:,:-1]指的是从第一个元素到倒数第二个元素, bin_edges[:,1:]指的是从第二个元素到最后一个元素
n, dout = centers.size()
centers = centers.view(n, dout, 1, 1)
pred = torch.sum(out * centers, dim=1, keepdim=True)
2.个人理解
将一张图片分割为多个patch后,在每一步计算中会对当前生成的每个patch执行线性变换,并随后通过多层自注意力机制处理这些特征向量。最终每个处理后的patch能够与其他区域形成相似性关联。
例如 patch₁[:,₁]与白色相关联,在整张图片对应位置呈现较多的白色情况下(即当图像在其对应的像素位置上呈现较多的白色),patch₁[:,₁]与其进行点乘运算时的权重也随之增大;其他类似的响应也会随之增加,在 depth₀ 到 depth₁ 这一区域内的响应也会相应增强。
作者通过损失函数的约束,将TRansformer输出结果,聚集于关注深度值
在Vision Transformer(ViT)模型中,MLP生成分类标签,在我的论文提出的模型中,同样生成深度信息 bin
query得到的是全局信息中的不同深度值 如下图所示

特征图与查询项通过形成一个查询项与键的配对方式获得,在此配对中对应的map[i]即代表深度为query[i]的结果。
随后,在数据处理流程中对各深度 bin 的深度值进行计算与分布拟合(防止伪影生成),随后完成网格结构建立;接着,在 map 数据中对各个 bin 的中心点位置施加平滑修正以优化结果计算;其结果等效于线性回归模型的应用
这里损失函数就不再赘述
转载请标注出处
