Deformable ConvNet DCN 可变形卷积的理解

5 篇文章 2 订阅
4 篇文章 0 订阅

先声明这篇只是快速的复习用, 用词比较自我加随性,多见谅
代码解说的地方很多参考了这个连结

首先DCN有两个版本, 大家都知道的v1就是单纯的加了offset偏移, 另一个v2就是从v1的基础上再加上了modulation, 也就是对学习对所有位置的权重

DCN v1 作用
  • v1: 多用了一个卷积学习出偏移offset的值, 相较于原先标准的卷积在感受野上有多更多分布的采样点, 原来标准的卷积不就是一个矩形的样子? 这样能学的特征非常的受到限制, 所以可变卷积就tm的问世了

在这里插入图片描述

公式

标准卷积(方便对照)
在这里插入图片描述

DCNv1
在这里插入图片描述

  • p表示为特征图上每一个点
  • y(p0)就表示 output feature map
  • w 表示权重, 就是conv kernel 上的每一个值
  • Δ P n \Delta P_n ΔPn表示经由Conv学习到的偏值
  • x 包含了输入特征图上的原采样点加上了学习到的偏值, 然后经过线性插值的过程

看最上边那张图, 经过conv_offset(就是最上图那个绿色的卷积)这个卷积学习出来的通道数为2N, 为什么是2, 因为学习出来的偏移有两个direction的, 一个为x, 一个为y, 一个通道负责一个方向, 那么N是表示采样点的个数, 比如用conv3x3去学习出offset, 那么就有2x3x3个点

这边记得从conv_offset学习出来的偏值通常会是float, 因为坐标需要整形
所以需要用一个bilinear interpolation来对学习出来的offset进行预处理

在这里插入图片描述
以下公式为线性插值方法
在这里插入图片描述

  • G ( q , p ) G(q, p) G(q,p) 就是bilinear interpolation function
  • 这里的p就是 ( p 0 + p n + Δ p n ) (p_0 + p_n + \Delta p_n) (p0+pn+Δpn)

接下来讲一下代码的实现思路
参考 代码

init的部分把相关信息配置好
p_conv就是用来学习offset的,这里仔细看outchannel的参数定义为2kernelsizekernelsize, 就是前面说到的2x3x3

m_conv就是DCNv2用来学习所以采样点的权重的
在这里插入图片描述
在这里插入图片描述
然后看到执行过程
看到经过了p_conv 得到offset, 如果有经过m_conv则会用一个sigmoid压缩成[0, 1]之间

在这里插入图片描述
这边看到用了一个 forward中用了_get_p 函数, 里面又用到了_get_p_0, 所以tm的两个都要看才行

先tm的看_get_p_n 函数, 主要是计算出所有卷积核的中心坐标, 为啥可以刚好计算出卷积核的中心坐标??
看下图, 假设一个input fmap(5x7), conv为3x3, 则输出的outmap为2x3, 则输出map上的每一个元素值就刚好等于卷积核中心的”位置(坐标)“了,
在这里插入图片描述
继续接着看代码, 用torch.meshgrid函数计算出卷积核上的九个坐标, 也就是(-1, 1)~…(1, 1)等9个, 最后噼里啪啦得到p_n 形状是(1, 2N, 1, 1), 这里的2N就是前面说到2N

再来看到_get_p_0 这个函数, 用来获取卷积核中心的坐标就是他妈的公式上的p0
传入的是output map的h跟w

最后看到_get_p, 这个函数求出来的就是 p 0 + p n + Δ p n p0 + pn + \Delta p_n p0+pn+Δpn
再来复习一下p0就是卷积核中心点
pn就是周围的点, 如果是(-1, 1), 那最终就是
0 + (-1, 1)+ offset了

最后因为取出来的offset是float, 需要用bilinear interpolation进行插值转换成整数, 坐标毕竟是整数
线性插值法请参考博客 博客
以下是截取参考链接的

根据线性插值理论我们需要获取4个整数坐标,所以在获取所有可变卷积核的坐标p后,通过floor()获取不超过本身的最大整数,也就是左上角坐标q_lt,同时为了防止偏移量过大移出feature map的范围通过torch.clamp对卷积核坐标做了限制。接下来只要通过左上角坐标就可以推出左下角(q_lb),右上角(q_rt),右下角(q_rb)坐标。
获取4个点的坐标后根据上图公式可以计算出像素值前面的系数(即 [公式] 这部分),代码中这4个系数分别为g_lt,g_rb,g_lb,g_rt。现在只获取了坐标值,我们最终木的是获取相应坐标上的值,这里我们通过self._get_x_q()获取相应值。如下

_get_x_q 可以从求出的四个坐标求出相应的值
在这里插入图片描述

接下来就自己看个明白或者看一开始的参考链接了
不然我也只是照抄而已, 老实说实际算法也没必要完全理解, 知道怎么用就行
这篇纯属记录一下这个算法思路

写些打加~~~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值