-
2019-09-19 23:24:01
代码:https://github.com/4uiiurz1/pytorch-deform-conv-v2
卷积神经网络(CNNs)由于其固定的几何结构而固有地局限于模型几何变换。
在这项工作中,我们引入两个新的模块来增强CNN的变换建模能力,即可变形卷积和可变形RoI池。两者都是基于模块中的增加空间采样位置的想法,其中带有额外的偏移量并学习目标任务的偏移量,不需要额外的监督。新的模块可以很容易地取代现有CNN中的普通对等体,并且可以很容易地通过标准的反向传播来进行端到端的训练,从而产生可变形卷积网络。
大量的实验验证了我们的方法的性能。我们首次展示了在深度CNN中学习密集的空间变换,对于复杂的视觉任务,如目标检测和语义分割是很有效的。
代码发布在https://github.com/msracver/Deformable-ConvNets。
图1:3×3标准可变形卷积的采样位置的说明。
(a)标准卷积的规则采样网格(绿点)。
(b)变形的采样位置(深蓝点),在可变形卷积中具有增强偏移(浅蓝色箭头)。
更多相关内容 -
Python-PyTorch中的可变形卷积网络
2019-08-11 08:10:54PyTorch中的可变形卷积网络 -
pytorch版可变形卷积代码DCNv2.zip
2020-04-09 17:36:32pytorch版可变形卷积代码DCNv2,下载编译可直接使用,内附编译过程及详细使用方法。在Ubuntu环境下使用的。 -
Python-可变形卷积网络的官方实现
2019-08-11 03:53:31可变形卷积网络的官方实现,Deformable Convolutional Networks -
Python-利用Pytorch实现的可变形卷积网络v2
2019-08-09 21:15:27利用Pytorch实现的可变形卷积网络v2 -
C-3D可变形卷积神经网络模型的肺结节检测
2021-01-26 09:53:12在C-3D卷积神经网络模型基础上,提出了一种三维可变形卷积神经网络以实现肺结节的检测。在模型的主体结构上,采用了三维可变形卷积和三维可变形池化的操作,解决了传统的方块卷积与池化在应对不规则的肺结节时,无法高... -
defHTR:具有可变形卷积的HTR CNN的Pytorch代码
2021-03-30 19:16:17defHTR:具有可变形卷积的HTR CNN的Pytorch代码 -
DCNv2可变形卷积开发包
2020-11-13 10:33:12可变性卷积的思想很简单,就是讲原来固定形状的卷积核变成可变的。同时可以去我的github地址去下载:https://github.com/z1z9b89/DCNv2 -
超分辨率matlab代码-LF-DFnet:[TIP2021]使用可变形卷积的光场图像超分辨率
2021-05-26 14:52:09PyTorch实施“使用可变形卷积的光场图像超分辨率”, 下载结果 我们在4xSR的所有5个数据集上共享由LF-DFnet生成的超分辨LF图像。 然后,研究人员可以将他们的算法与我们的LF-DFnet进行比较,而无需进行推断。 可在... -
高分辨率遥感影像深度迁移可变形卷积的场景分类法.docx
2021-09-20 10:08:47高分辨率遥感影像深度迁移可变形卷积的场景分类法.docx -
可变形卷积:Deformable ConvNets
2020-11-30 17:11:16可变形卷积:Deformable ConvNets DCNv1论文网址:Deformable Convolutional Networks DCNv2论文网址:Deformable ConvNets v2: More Deformable, Better Results DCNv2代码:...可变形卷积:Deformable ConvNets
DCNv1论文网址:Deformable Convolutional Networks
DCNv2论文网址:Deformable ConvNets v2: More Deformable, Better Results
DCNv2代码:https://github.com/CharlesShang/DCNv2/tree/pytorch_0.4DCNv1
1. 空洞卷积(dilated conv)
- 在图像分割领域,图像输入到CNN(典型的网络比如FCN)中,FCN先像传统的CNN那样对图像做卷积再pooling,降低图像尺寸的同时增大感受野,但是由于图像分割预测是pixel-wise的输出,所以要将pooling后较小的图像尺寸upsampling到原始的图像尺寸进行预测,之前的pooling操作使得每个pixel预测都能看到较大感受野信息。因此图像分割FCN中有两个关键,一个是pooling减小图像尺寸增大感受野,另一个是upsampling扩大图像尺寸。
- 在先减小再增大尺寸的过程中,肯定有一些信息损失掉了,那么能不能设计一种新的操作,不通过pooling也能有较大的感受野看到更多的信息呢?答案就是dilated conv。
-
(a)普通卷积,1-dilated convolution,卷积核的感受野为3×3
图中对应3x3的1-dilated conv,和普通的卷积操作一样. -
(b)空洞卷积,2-dilated convolution,卷积核的感受野为7×7
图中对应3x3的2-dilated conv,实际的卷积kernel size还是3x3(红点)。 可以看到虽然kernel size只有3x3,但是这个卷积的感受野已经增大到了7x7。 -
( c) 空洞卷积,4-dilated convolution,卷积核的感受野为15×15
图中是4-dilated conv操作,同理跟在两个1-dilated和2-dilated conv的后面,能达到15x15的感受野。 -
空洞卷积与普通卷积的相同点在于,卷积核的大小是一样的,在神经网络中即参数数量不变,区别在于扩张卷积具有更大的感受野。
-
空洞卷积在保持参数个数不变的情况下增大了卷积核的感受野,同时它可以保证输出的特征映射(feature map)的大小保持不变。
-
dilated的好处是不做pooling损失信息的情况下,加大了感受野,让每个卷积输出都包含较大范围的信息。在图像需要全局信息或者语音文本需要较长的sequence信息依赖的问题中,都能很好的应用dilated conv。
-
将普通的卷积stride步长设为大于1,也会达到增加感受野的效果,但是stride大于1就会导致downsampling,图像尺寸变小。
2. 反卷积(Deconv)
- deconv的其中一个用途是做upsampling,即增大图像尺寸。而dilated conv并不是做upsampling,而是增大感受野。
- 卷积操作可以形象的做个解释:对于标准的k*k卷积操作,stride为s,分三种情况:
(a)s>1,即卷积的同时做了downsampling,卷积后图像尺寸减小;
(b)s=1,普通的步长为1的卷积,比如在tensorflow中设置padding=SAME的话,卷积的图像输入和输出有相同的尺寸大小;
(c)0<s<1,deconv,相当于对图像做upsampling。比如s=0.5时,意味着在图像每个像素之间padding一个空白的像素后,stride改为1做卷积,得到的feature map尺寸增大一倍。
3. 可变形卷积(Deformable convolution)
- 文章提出了可变卷积和可变ROI采样。原理是一样的,就是在这些卷积或者ROI采样层上,添加了位移变量,这个变量根据数据的情况学习,偏移后,相当于卷积核每个方块可伸缩的变化,从而改变了感受野的范围,感受野成了一个多边形。
- (a)是普通的卷积,卷积核大小为3*3,采样点排列非常规则,是一个正方形。
(b)是可变形的卷积,给每个采样点加一个offset(这个offset通过额外的卷积层学习得到),排列变得不规则。
(c)和(d)是可变形卷积的两种特例。对于(c)加上offset,达到尺度变换的效果;对于(d)加上offset,达到旋转变换的效果。
- 如上图所示,有一个额外的conv层来学习offset,共享input feature maps。然后input feature maps和offset共同作为deformable conv层的输入,deformable conv层操作采样点发生偏移,再进行卷积。
- 事实上,可变形卷积单元中增加的偏移量是网络结构的一部分,通过另外一个平行的标准卷积单元计算得到,进而也可以通过梯度反向传播进行端到端的学习。加上该偏移量的学习之后,可变形卷积核的大小和位置可以根据当前需要识别的图像内容进行动态调整,其直观效果就是不同位置的卷积核采样点位置会根据图像内容发生自适应的变化,从而适应不同物体的形状、大小等几何形变。
- 上图展示了两层的3*3卷积层的映射。对于标准的卷积,后面层的feature map上的一个点,映射到前面层所对应的感受野是规则的,无法考虑到不同目标的外形、大小不同;而可变形的卷积则考虑到了目标的形变,映射到前面层的采样点大多会覆盖在目标上面,采样到更多我们感兴趣的信息。
4. 可变形ROI pooling(Deformable RoI pooling)
- RoI pooling是把不同大小的RoI(w*h)对应的feature map 统一到固定的大小(k x k);可形变RoI pooling则是先对RoI对应的每个bin按照RoI的长宽比例的倍数进行整体偏移(同样偏移后的位置是小数,使用双线性差值来求),然后再pooling。
- 由于按照RoI长宽比例进行水平和竖直方向偏移,因此每一个bin的偏移量只需要一个参数来表示,具体可以用全连接来实现。
- 如上图所示,RoI被分为3*3个bin,被输入到一个额外的fc层来学习offset,然后通过一个deformable RoI pooling层来操作使每个bin发生偏移。
- 对于普通的ROI pooling,将ROI分解成k×k个bin,输出为k×k的特征图y,对于第 (i, j)个 bin (0 ≤ i, j < k),有:
- 对于 deformable RoI pooling,offsets {∆pij |0 ≤ i, j < k} 加入到空间bin的位置,有:
DCNv2
1. 简介
- 目标检测一个主要挑战:尺度,姿势,视角和部件变形引起的几何变化。
- 在DCN v1中引入了两种新的模块来提高卷积神经网络对变换的建模能力,即可变形卷积 (deformable convolution) 和可变形兴趣区域池化 (deformable ROI pooling)。
- DCNv1引入了可变形卷积,能更好的适应目标的几何变换。但是v1可视化结果显示其感受野对应位置超出了目标范围,导致特征不受图像内容影响(理想情况是所有的对应位置分布在目标范围以内)。
- 提出DCNv2,主要改进有:(1)扩展可变形卷积,增强建模能力;(2)提出了特征模拟方案指导网络培训:feature mimicking scheme.
2. 可变形卷积可视化
- 可视化三个内容:
有效感受野 : 可视化感受野
有效采样位置: 对采样点求梯度,然后可视化
误差界限显著性区域 : 参考显著性分析理论,进行可视化
- 从中观察到:
(1)常规卷积可以一定程度上模拟几何变化,通过网络权重做到的;
(2)可变形卷积DCNv1模拟几何变化能力显著提升,但是不够精确。
3. DCNv2改进
- 3点改进:
(1)使用更多的可变形卷积;
(2)在DCNv1基础(添加offset)上添加幅值参数;
(3)R-CNN Feature Mimicking.
3.1 使用更多的可变形卷积
- DCNv1:ResNet-50 Conv5里边的3×3的卷积层都使用可变形卷积替换。Aligned RoI pooling 由 Deformable RoI Pooling取代。
- DCNv2:在Conv3, Conv4, Conv5中所有的3×3的卷积层全部被替换掉。
3.2 在DCNv1基础(添加offset)上添加幅值参数
在DCNV1里,Deformable Conv只学习offset:
而在DCNV2中,加入了对每个采样点的权重:
其中Δpk是学到的offset,Δmk是学到的权重。这样的好处是增加了更大的自由度,对于某些不想要的采样点权重可以学成0。- Δpk和Δmk都是通过在相同的输入feature map 上应用的单独卷积层获得的。 该卷积层具有与当前卷积层相同的空间分辨率。 输出为3K通道,其中前2K通道对应于学习的偏移,剩余的K通道进一步馈送到sigmoid层以获得调制量。
- 对于deformable RoIPooling,DCNV2的修改类似:
Δpk和Δmk的值由输入特征图上的分支产生。 在这个分支中,RoIpooling在RoI上生成特征,然后是两个1024-D的fc层。 额外的fc层产生3K通道的输出(权重被初始化为零)。 前2K通道是可学习偏移Δpk, 剩余的K个通道由sigmoid层标准化以产生Δmk。
3.3 R-CNN Feature Mimicking
- Revisiting RCNN中作者发现把R-CNN和Faster RCNN的classification score结合起来可以提升performance,说明R-CNN学到的focus在物体上的feature可以解决redundant context的问题。但是增加额外的R-CNN会使inference速度变慢很多。
- DCNV2里的解决方法是把R-CNN当做teacher network,让DCNV2的ROIPooling之后的feature去模拟R-CNN的feature。
- 得到ROI之后,在原图中抠出这个ROI,resize到224x224,再送到一个RCNN中进行分类,这个RCNN只分类,不回归。然后,主网络fc2的特征去模仿RCNN fc2的特征,实际上就是两者算一个余弦相似度,1减去相似度作为loss即可.
4. 实验结果
-
基于可变形卷积的手绘图像检索
2021-05-06 12:12:18针对此问题, 本文提出一种基于可变形卷积的手绘检索方法. 首先通过Berkerly边缘检测算法将自然图转化为边缘图, 消除域差异. 然后将卷积神经网络中的部分标准卷积替换为可变形卷积, 使网络能够充分关注手绘图轮廓... -
Deformable ConvNets可变形卷积
2020-07-08 11:44:04论文:Deformable Convolutional Networks(CVPR 2017) 文章目录 针对问题 可变形卷积 Deformable RoI Pooling 实验结果对比 可变形卷积Pytorch实现 补充 参考文献 针对问题 如何应对几何形变问题(尺度,姿态,...论文:Deformable Convolutional Networks(CVPR 2017)
针对问题
如何应对几何形变问题(尺度,姿态,视点和部件变形等),常用方法:
- 假设目标分布已知的情况下,通过增加具有期望变化的样本,
- 或者设计invariant features和算法
但上述方法都难以应对复杂的或新的变化,文中通过在卷积层和RoI pooling层中引入offset以提高网络的灵活性,能够更好地覆盖不同尺度和形状的目标,使网络更专注于目标区域,提取到的特征更加丰富
可变形卷积
3 × 3 3\times3 3×3 卷积核 , R \mathscr{R} R for Regular Grid
( − 1 , − 1 ) ( 0 , − 1 ) ( 1 , − 1 ) ( − 1 , 0 ) ( 0 , 0 ) ( 1 , 0 ) ( − 1 , 1 ) ( 0 , 1 ) ( 1 , 1 ) \begin{matrix} (-1,-1)&(0,-1)&(1,-1)\\ (-1,0)&(0,0)&(1,0)\\ (-1,1)&(0,1)&(1,1) \end{matrix} (−1,−1)(−1,0)(−1,1)(0,−1)(0,0)(0,1)(1,−1)(1,0)(1,1)
普通卷积
y ( p 0 ) = ∑ p n ∈ R w ( p n ) ⋅ x ( p 0 + p n ) y(p_0)=\sum\limits_{p_n\in \mathscr{R}}\ w(p_n)\cdot x(p_0+p_n) y(p0)=pn∈R∑ w(pn)⋅x(p0+pn)可变形卷积增加了可以学习的坐标偏移量 Δ p n \Delta p_n Δpn
y ( p 0 ) = ∑ p n ∈ R w ( p n ) ⋅ x ( p 0 + p n + Δ p n ) ⏟ 插值得到偏移坐标处像素值 \begin{aligned} y(p_0)=\sum\limits_{p_n\in \mathscr{R}}\ w(p_n)\cdot \underbrace{x(p_0+p_n+\Delta p_n)}_{\text{插值得到偏移坐标处像素值}} \end{aligned} y(p0)=pn∈R∑ w(pn)⋅插值得到偏移坐标处像素值 x(p0+pn+Δpn)上式可以看出:变形的其实不是卷积核,而是特征图,普通卷积作用在变形的特征图上达到了变形卷积的效果
计算梯度:
∂ y ( p 0 ) ∂ Δ p n = ∑ p n ∈ R w ( p n ) ⋅ ∂ x ( p 0 + p n + Δ p n ) ∂ Δ p n = ∑ p n ∈ R [ w ( p n ) ⋅ ∑ q ∂ G ( q , p 0 + p n + Δ p n ) ∂ Δ p n ⋅ x ( q ) ] \begin{aligned} \frac{\partial\ \boldsymbol{y}(p_0)}{\partial\ \Delta\ \boldsymbol{p}_n} &=\sum\limits_{\boldsymbol{p}_n\in \mathscr{R}}\ \boldsymbol{w}(\boldsymbol{p}_n)\cdot \frac{\partial\ \boldsymbol{x}(\boldsymbol{p}_0+\boldsymbol{p}_n+\Delta \boldsymbol{p}_n)}{\partial\ \Delta\boldsymbol{p}_n} \\ &=\sum\limits_{\boldsymbol{p}_n\in \mathscr{R}}\ \left[\boldsymbol{w}(\boldsymbol{p}_n)\cdot \sum\limits_q\ \frac{\partial\ G(\boldsymbol{q},\boldsymbol{p}_0+\boldsymbol{p}_n+\Delta \boldsymbol{p}_n)}{\partial\ \Delta \boldsymbol{p}_n}\cdot \boldsymbol{x}(\boldsymbol{q})\right] \end{aligned} ∂ Δ pn∂ y(p0)=pn∈R∑ w(pn)⋅∂ Δpn∂ x(p0+pn+Δpn)=pn∈R∑ [w(pn)⋅q∑ ∂ Δpn∂ G(q,p0+pn+Δpn)⋅x(q)]Δ p n \Delta p_n Δpn通常都是小数,而图像是一个一个离散像素点,可以用双线性差值进行差值计算出该处像素值,可变形卷积示意图如下:
可变形卷积步骤- 输入 【 B ∗ H ∗ W ∗ C 】 【B*H*W*C】 【B∗H∗W∗C】经过普通卷积(same)得到输出 【 B ∗ H ∗ W ∗ ( 2 ⋅ n ⋅ n ) 】 【B*H*W*(2\cdot n\cdot n)】 【B∗H∗W∗(2⋅n⋅n)】, n n n 表示卷积核尺寸,乘以2表示每个像素都有 x 、 y x、y x、y两个方向的偏移量,其实就是相对偏移坐标
- 将1中得到的相对偏移坐标与原坐标相加,即得到各个像素偏移后的位置(要将位置限定在原图坐标范围内,不能超出图片范围)
- 因为图像都是由离散的一个一个像素组成,而求得的偏移位置是浮点数,需要用到双线性插值的方法该位置对应像素值(根据该点周围的四个点计算: 【 c e i l ( x ) , c e i l ( y ) 】 【ceil(x),ceil(y)】 【ceil(x),ceil(y)】、 【 f l o o r ( x ) , c e i l ( y ) 】 【floor(x),ceil(y)】 【floor(x),ceil(y)】、 【 c e i l ( x ) , f l o o r ( y ) 】 【ceil(x),floor(y)】 【ceil(x),floor(y)】、 【 f l o o r ( x ) , f l o o r ( y ) 】 【floor(x),floor(y)】 【floor(x),floor(y)】,梯度回传也是根据这四个点)
- 计算得到变换后的特征图作输出
Deformable Group
注意:如果按照上面的方法计算的话,特征图中同一个像素点的不同Channel有不一样的偏移量。源码中num_deformable_group变量,其作用是将输入沿Channel Axis分割成几个部分(Group),同一个Group的Channel共享offset。设置Goup=1则所有Channel都是相同的offset
不同的通道提取到的特征其实是不一样的,为提高网络的灵活性,可以适当调整group的个数,用dg表示Group数,则:输入: B × dg ⋅ C dg × H × W B\times\text{dg}\cdot \frac{C}{\text{dg}}\times H\times W B×dg⋅dgC×H×W
卷积核: n × n × dg ⋅ C dg × 2 ⋅ n ⋅ n ⋅ dg n\times n\times\text{dg}\cdot \frac{C}{\text{dg}}\times 2\cdot n\cdot n\cdot \text{dg} n×n×dg⋅dgC×2⋅n⋅n⋅dg
输出: B × ( 2 ⋅ n ⋅ n ) ⋅ dg × H × W B\times (2\cdot n\cdot n)\cdot \text{dg}\times H\times W B×(2⋅n⋅n)⋅dg×H×WDeformable RoI Pooling
思想和可变形卷积基本一样,ROI pooling之后的尺寸特征尺寸就固定下来了,所以用了一个FC连接
包括deformable position-sensitive(PS)RoI pooling,其思想与前面的基本一致,就是给一个可以学习的偏移量,然后再结合普通的position-sensitive(PS)RoI pooling
实验结果对比
文中主网络将ResNet101 res5部分的 3 ∗ 3 3*3 3∗3卷积替换为可变形卷积(设置在靠后的卷积层,应该是为了从相对较为稳定的特征上学习偏移量),stride(原本为32)改为16,而dilated参数则设置为2以弥补减小stride带的感受野损失下表中可看出:替换res5中3个卷积的时候效果最好。事实上v2中在 coco 数据集上的表现更好
下表中可看出:deformable conv和 atrous conv 相比表现更好
可变形卷积Pytorch实现
双线性插值 【 8 】 ^{【8】} 【8】
f ( x , y ) ≈ f ( x 1 , y 1 ) ( x 2 − x ) ( y 2 − y ) ⏟ S 4 + f ( x 2 , y 1 ) ( x − x 1 ) ( y 2 − y ) ⏟ S 3 + f ( x 1 , y 2 ) ( x 2 − x ) ( y − y 1 ) ⏟ S 2 + f ( x 2 , y 2 ) ( x − x 1 ) ( y − y 1 ) ⏟ S 1 \begin{aligned} {\color{red}f(x, y)} \approx{f\left(x_1,y_1\right)}\underbrace{\left(x_{2}-x\right)\left(y_{2}-y\right)}_{S_4} +{f\left(x_2,y_1\right)}\underbrace{\left(x-x_{1}\right)\left(y_{2}-y\right)}_{S_3} \\ +{f\left(x_1,y_2\right)}\underbrace{\left(x_{2}-x\right)\left(y-y_{1}\right)}_{S_2}+{f\left(x_2,y_2\right)}\underbrace{\left(x-x_{1}\right)\left(y-y_{1}\right)}_{S_1} \end{aligned} f(x,y)≈f(x1,y1)S4 (x2−x)(y2−y)+f(x2,y1)S3 (x−x1)(y2−y)+f(x1,y2)S2 (x2−x)(y−y1)+f(x2,y2)S1 (x−x1)(y−y1)import torch from torch import nn class DeformConv2d(nn.Module): def __init__(self, inc, outc, kernel_size=3, padding=1, stride=1, bias=None, modulation=False): """ Args: modulation (bool, optional): If True, Modulated Defomable Convolution (Deformable ConvNets v2). """ super(DeformConv2d, self).__init__() self.kernel_size = kernel_size self.padding = padding self.stride = stride self.zero_padding = nn.ZeroPad2d(padding) self.conv = nn.Conv2d(inc, outc, kernel_size=kernel_size, stride=kernel_size, bias=bias) self.p_conv = nn.Conv2d(inc, 2*kernel_size*kernel_size, kernel_size=3, padding=1, stride=stride) nn.init.constant_(self.p_conv.weight, 0) self.p_conv.register_backward_hook(self._set_lr) self.modulation = modulation if modulation: self.m_conv = nn.Conv2d(inc, kernel_size*kernel_size, kernel_size=3, padding=1, stride=stride) nn.init.constant_(self.m_conv.weight, 0) self.m_conv.register_backward_hook(self._set_lr) @staticmethod def _set_lr(module, grad_input, grad_output): grad_input = (grad_input[i] * 0.1 for i in range(len(grad_input))) grad_output = (grad_output[i] * 0.1 for i in range(len(grad_output))) def forward(self, x): offset = self.p_conv(x) if self.modulation: m = torch.sigmoid(self.m_conv(x)) dtype = offset.data.type() ks = self.kernel_size N = offset.size(1) // 2 if self.padding: x = self.zero_padding(x) # (b, 2N, h, w) p = self._get_p(offset, dtype) # (b, h, w, 2N) p = p.contiguous().permute(0, 2, 3, 1) q_lt = p.detach().floor() q_rb = q_lt + 1 # 下标分别对应 lt:左上、rb:右下、lb:左下、rt:右上 q_lt = torch.cat([torch.clamp(q_lt[..., :N], 0, x.size(2)-1), torch.clamp(q_lt[..., N:], 0, x.size(3)-1)], dim=-1).long() q_rb = torch.cat([torch.clamp(q_rb[..., :N], 0, x.size(2)-1), torch.clamp(q_rb[..., N:], 0, x.size(3)-1)], dim=-1).long() q_lb = torch.cat([q_lt[..., :N], q_rb[..., N:]], dim=-1) q_rt = torch.cat([q_rb[..., :N], q_lt[..., N:]], dim=-1) # clip p p = torch.cat([torch.clamp(p[..., :N], 0, x.size(2)-1), torch.clamp(p[..., N:], 0, x.size(3)-1)], dim=-1) # bilinear kernel (b, h, w, N) # 四个顶点对应的权重:lt:S4、rb:S1、lb:S2、rt:S3 g_lt = (1 + (q_lt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_lt[..., N:].type_as(p) - p[..., N:])) g_rb = (1 - (q_rb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_rb[..., N:].type_as(p) - p[..., N:])) g_lb = (1 + (q_lb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_lb[..., N:].type_as(p) - p[..., N:])) g_rt = (1 - (q_rt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_rt[..., N:].type_as(p) - p[..., N:])) # 获取周围四个点的值 # (b, c, h, w, N) x_q_lt = self._get_x_q(x, q_lt, N) x_q_rb = self._get_x_q(x, q_rb, N) x_q_lb = self._get_x_q(x, q_lb, N) x_q_rt = self._get_x_q(x, q_rt, N) # 双线性插值 # (b, c, h, w, N) x_offset = g_lt.unsqueeze(dim=1) * x_q_lt + \ g_rb.unsqueeze(dim=1) * x_q_rb + \ g_lb.unsqueeze(dim=1) * x_q_lb + \ g_rt.unsqueeze(dim=1) * x_q_rt # modulation if self.modulation: m = m.contiguous().permute(0, 2, 3, 1) m = m.unsqueeze(dim=1) m = torch.cat([m for _ in range(x_offset.size(1))], dim=1) x_offset *= m x_offset = self._reshape_x_offset(x_offset, ks) out = self.conv(x_offset) return out def _get_p_n(self, N, dtype): p_n_x, p_n_y = torch.meshgrid( torch.arange(-(self.kernel_size-1)//2, (self.kernel_size-1)//2+1), torch.arange(-(self.kernel_size-1)//2, (self.kernel_size-1)//2+1)) # (2N, 1) p_n = torch.cat([torch.flatten(p_n_x), torch.flatten(p_n_y)], 0) p_n = p_n.view(1, 2*N, 1, 1).type(dtype) return p_n def _get_p_0(self, h, w, N, dtype): p_0_x, p_0_y = torch.meshgrid( torch.arange(1, h*self.stride+1, self.stride), torch.arange(1, w*self.stride+1, self.stride)) p_0_x = torch.flatten(p_0_x).view(1, 1, h, w).repeat(1, N, 1, 1) p_0_y = torch.flatten(p_0_y).view(1, 1, h, w).repeat(1, N, 1, 1) p_0 = torch.cat([p_0_x, p_0_y], 1).type(dtype) return p_0 def _get_p(self, offset, dtype): N, h, w = offset.size(1)//2, offset.size(2), offset.size(3) # (1, 2N, 1, 1) p_n = self._get_p_n(N, dtype) # (1, 2N, h, w) p_0 = self._get_p_0(h, w, N, dtype) p = p_0 + p_n + offset return p def _get_x_q(self, x, q, N): b, h, w, _ = q.size() padded_w = x.size(3) c = x.size(1) # (b, c, h*w) x = x.contiguous().view(b, c, -1) # (b, h, w, N) # offset_x*w + offset_y # 例如:a.shape=(30, 30),a[1][1]就是第 1*30+1 个元素 index = q[..., :N]*padded_w + q[..., N:] # (b, c, h*w*N) index = index.contiguous().unsqueeze(dim=1).expand(-1, c, -1, -1, -1).contiguous().view(b, c, -1) x_offset = x.gather(dim=-1, index=index).contiguous().view(b, c, h, w, N) return x_offset @staticmethod def _reshape_x_offset(x_offset, ks): b, c, h, w, N = x_offset.size() x_offset = torch.cat([x_offset[..., s:s+ks].contiguous().view(b, c, h, w*ks) for s in range(0, N, ks)], dim=-1) x_offset = x_offset.contiguous().view(b, c, h*ks, w*ks) return x_offset
补充
对conv,pooling操作深入探讨 【 6 】 ^{【6】} 【6】
附:im2col可细分为四个阶段: 1. Indexing (im2col):本文关注的部分。 2. Computation (gemm):在im2col之后,conv就被转化为了一个dense matrix multiplication的问题。 本质上,conv还是一个线性模型就是因为在这一步还是一个线性变化。 有若干工作试图增强计算步骤的表示能力。从最开始的Network In Network到后来的Neural Decision Forest, 再到最近我们的Factorized Bilinear Layer,都是在这一步试图做出一些变化。 3. Reduce (sum):最简单的reduce操作就是求和,但是这个步骤还是有大量变化的余地。 例如,是否可以通过类似于attention一样的机制做加权求和?(这里defomble conv2已经做了) 是否可以通过random projection引入随机性? 5. Reindex (col2im):这步骤是第一步的逆操作。
参考文献
【1】可变形卷积网络(Deformable Convolutional Networks)
【2】Deformable Convolutional Networks
【3】STN-Spatial Transformer Networks-论文笔记
【4】详细解读Spatial Transformer Networks(STN)
【4】可变形卷积Deformable Convolution Net(DCN)理解
【5】Deformable ConvNets–Part5: TensorFlow实现Deformable ConvNets
【6】【VALSE 前沿技术选介17-02期】可形变的神经网络
【7】论文讨论&&思考《Deformable Convolutional Networks》
【8】双线性插值
【9】双线性插值的两种实现方法
【10】Deformable Convlolutional Networks算法笔记
【11】Review: DCN — Deformable Convolutional Networks, 2nd Runner Up in 2017 COCO Detection (Object Detection) -
Deformable-convolution--可变形卷积
2021-11-25 17:57:55在目前的视频超分研究中,可变形卷积应用效果得到了非常大的认可,在与传统光流或者深度学习光流网络计算光流的直接pk中,因为其直接在特征域计算对齐的特性,在EDVR等网络实践中效果更佳。 1. 原文解读 Deformable ...在目前的视频超分研究中,可变形卷积应用效果得到了非常大的认可,在与传统光流或者深度学习光流网络计算光流的直接pk中,因为其直接在特征域计算对齐的特性,在EDVR等网络实践中效果更佳。
1. 原文解读
Deformable Convolutional Networks-PDF
Deformable Convolutional Networks-slides1.1 背景
在计算机视觉领域,同一物体在不同场景,角度中未知的几何变换是检测/识别的一大挑战,通常来说我们有两种做法:
(1)通过充足的数据增强,扩充足够多的样本去增强模型适应尺度变换的能力。
(2)设置一些针对几何变换不变的特征或者算法,比如SIFT和sliding windows。
两种方法都有缺陷,第一种方法因为样本的局限性显然模型的泛化能力比较低,无法泛化到一般场景中,第二种方法则因为手工设计的不变特征和算法对于过于复杂的变换是很难的而无法设计。所以作者提出了Deformable Conv(可变形卷积)和 Deformable Pooling(可变形池化)来解决这个问题。
文章提出的比较早,针对可变形池化还专门做了优化与讲解,现在池化操作已经越来越多的被结合convolution的stride取代。
1.2 思路
offset层数是由kernel size决定的,他一定是输出2*kernel size*kernel size数目的channel,这一点可以类比光流图的输出结果进行比对,因为kernel内部每一个点都需要有X和Y两个方向的位移。比如kernel size数值为3,则offset层的输出结果一定是含有18层,kernel size的数值为5则输出结果一定为50层。
这一点也可以通过原论文来进行解释,可以看到R就是kernel的行列式定义,kernal size=3的时候,则|R|=9。而上图中涉及到的N值则是与R相同,offset field数值为2N,则与推理的数据保持一致。
实际上在实现上,可变形卷积一共有两种思路:可以参考blogDeformable ConvNets–Part5: TensorFlow实现Deformable ConvNets下面的讨论。
Function 1:
按照论文所说,offset层输出结果是2N的卷积核偏移量;卷积得出的是(Batch,H,W,2N),2N分成代表卷积核横向x的(3,3)各个偏移值,代表卷积核纵向y的(3,3)各个偏移值,对特征图卷积的时候,根据2N个偏移值计算卷积核对应的9个新位置,对这九个新位置作(3,3)形变卷积。b*h*w*c 的input map相对应的offset层形状为 b*h*w*c*2N,可以理解是对卷积核进行了旋转平移缩放的操作,然后与卷积层进行rule based convolution。
Function 2:
直接将卷积核的偏移量等量替代为feature map上的位移量,可以理解特征图进行了旋转平移缩放的操作,详细操作可以参考1.2的可变形卷积流程。2. 可变形卷积流程:
1、原始图片batch(大小为b*h*w*c),记为U,经过一个普通卷积,卷积填充为same,即输出输入的h,w数值不变,对应的输出结果为offset层(b*h*w*2c),记为V,输出的结果是指原图片batch中每个像素的偏移量(x偏移与y偏移,因此为2c)。也就是说offset层是通过卷积网络计算得到的。
2、将U中图片的像素索引值与V相加减变换,得到偏移后的position(即在原始图片U中的坐标值),注意变换操作需要将最终的position值限定为图片大小以内。注意到position只是一个float类型的坐标值,我们需要这些float类型的坐标值获取像素。
3、比如取一个float类型的坐标值(a,b),将其转换为四个整数,floor(a), ceil(a), floor(b), ceil(b),将这四个整数进行整合,得到四对坐标(floor(a),floor(b)), ((floor(a),ceil(b)), ((ceil(a),floor(b)), ((ceil(a),ceil(b))。这四对坐标每个坐标都对应U中的一个像素值,而我们需要得到(a,b)的像素值,这里采用双线性差值的方式计算,一方面得到的像素准确,另一方面可以进行反向传播。
4、在得到position的所有像素后,即得到了一个新图片M,将这个新图片M作为输入数据输入到下一个卷积层中。
除此之外还有两篇讲解比较详细的文章
再思考可变形卷积
DCN V1代码阅读笔记 -
可变形卷积学习(RepPoints)
2021-03-06 22:04:37近来在学习anchor-free网络,看到了可变形卷积(Deformable Convolutional Networks(DCN))的内容,大致总结一下,便于后面回顾。 可变形卷积可从以下三篇论文去学习,它们也被称为DCNv1、DCNv2、RepPoints(DCNv3)... -
可变形卷积网络:Deformable Convolutional Networks
2020-04-29 18:10:14包括理解! Deformable Convolutional Networks 摘要 卷积神经网络(CNNs)由于其构建模块中固定的几何结构,其固有的局限性在于模型的几何变换。在这项工作中,我们引入了两个新的模块来增强... -
更灵活、有个性的卷积——可变形卷积(Deformable Conv)
2020-12-15 14:25:20作者简介 CW,广东深圳人,毕业于中山大学(SYSU)数据科学与计算机学院,毕业后就业于腾讯计算机系统有限公司...相信大家在看paper的时候或多或少都能见到Deformable操作的身影,这种可变形操作可嵌入到算法中的许... -
卷积神经网络-Deformable Convolutional可变形卷积详解[下]
2020-06-20 15:38:39卷积神经网络-Deformable Convolutional可变形卷积详解[下] -
可变形卷积系列(三) Deformable Kernels,创意满满的可变形卷积核 | ICLR 2020
2020-04-16 11:43:57论文提出可变形卷积核(DK)来自适应有效感受域,每次进行卷积操作时都从原卷积中采样出新卷积,是一种新颖的可变形卷积的形式,从实验来看,是之前方法的一种有力的补充。 来源:晓飞的算法工程笔记 公众号 论文:... -
MASA DCN(可变形卷积) 算法笔记
2020-05-18 22:36:23因此论文以此为切入点,通过在卷积层中插入offset(可变形卷积)和在ROI Pooling层中插入offset(可变形ROI Pooling)来增强网络的特征提取能力。这个offset的作用是使网络在提取特征时更多的把注意力聚焦到和训练... -
可变形卷积网络
2020-06-19 11:49:431、什么是可变形卷积? 可变形卷积是指卷积核在每一个元素上额外增加了一个参数方向参数,这样卷积核就能在训练过程中扩展到很大的范围。 注意:这里有一个非常非常非常容易混淆的点,所谓的deformable,到底... -
可变形卷积网络:计算机新“视”界
2021-06-26 12:27:08展示了可变形卷积可以作为尺度变换,比例变换和旋转变换的特殊情况 事实上,可变形卷积单元中增加的偏移量是网络结构的一部分,通过另外一个平行的标准卷积单元计算得到,进而也可以通过梯度反向传播进行端到端的... -
论文阅读笔记 | 目标检测算法——DCN(可变形卷积网络)
2021-08-20 10:43:24如有错误,恳请指出。 文章目录1. Introduction2. Deformable Convolutional Networks2.1 Deformable Convolution2.2 Deformable RoI Poolingb2.3 Postion﹣Sensitive RoI Pooling3....卷积神经网络由于其构建. -
可变形卷积在视频学习中的应用:如何利用带有稀疏标记数据的视频帧
2020-11-05 09:10:17卷积层是卷积神经网络的基本层。虽然它在计算机视觉和深度学习中得到了广泛的应用,但也存在一些不足。例如,对于某些输入特征图,核权值是固定的,不能 适应局部特征的变化,因此需要更多的核来建模复杂的特征图幅... -
可变形卷积从概念到实现过程
2020-02-09 23:19:16可变形卷积是如何实现的?什么是可变形卷积?为什么要可变形卷积?如何实现可变形卷积? 什么是可变形卷积? 可变形卷积是指卷积核在每一个元素上额外增加了一个参数方向参数,这样卷积核就能在训练过程中扩展到很大... -
可变形卷积pytorch版本解读
2020-01-10 21:55:07(可用时受益于 GPU 加速,不可用时会倒退回 CPU)时,选择并保存适当的 torch.device, 不失为一种好方法,它可用于确定存储张量的位置。 device = torch.device('cuda' if args.cuda else 'cpu') ''' torch.manual_... -
八、可变形卷积网络 (超级详细哦)
2019-08-09 01:31:47可变形卷积网络(很详细哦)1、可变形卷积网络简单介绍2、可变形卷积网络的进一步分析3、可变形卷积网络的实验结果 1、可变形卷积网络简单介绍 由于构造卷积神经网络 (CNN) 所用的模块(卷积核)中几何结构是固定... -
可变形卷积:DCNv1and DCNv2
2022-05-09 19:39:50目录1.DCNv11.1 可变形卷积核 1.1 可变形卷积核 DCN v1的核心思想在于它认为卷积核不应该是一个简简单单的矩形 在不同的阶段,不同的特征图,甚至不同的像素点上都可能有其最优的卷积核结构。 因此DCN v1提出在方形... -
论文阅读-可变形卷积v2: More Deformable, Better Results
2019-05-13 18:17:10论文提出可变形卷积神经网络v2(DCNv2),规避了采样区域增加从而引入无关区域的问题,通过更多的可变形卷积层的堆叠,可调节的可变形卷积核RoI池化模块与R-CNN特征融合训练进一步提升了训练精度。