meshgrid
import numpy as np
X = np.arange(1, 4)
Y = np.arange(11, 13)
# MX.shape=MY.shape=(len(Y), len(X))=(H,W)
MX, MY = np.meshgrid(X, Y)
print(MX)
print(MY)
MP = np.stack([MX, MY], axis=-1)
[[1 2 3]
[1 2 3]]
[[11 11 11]
[12 12 12]]
MP:
(x0, y0) (x1, y0) (x2, y0)
(x0, y1) (x1, y1) (x2, y1)
=>
MX:
x0 x1 x2
x0 x1 x2
MY:
y0 y0 y0
y1 y1 y1
mmcv.ops.DeformConv2d
class DeformConv2d(nn.Module):
...
def forward(self, x: Tensor, offset: Tensor) -> Tensor:
"""Deformable Convolutional forward function.
Args:
x (Tensor): Input feature, shape (B, C_in, H_in, W_in)
offset (Tensor): Offset for deformable convolution, shape
(B, deform_groups*kernel_size[0]*kernel_size[1]*2,
H_out, W_out), H_out, W_out are equal to the output's.
An offset is like `[y0, x0, y1, x1, y2, x2, ..., y8, x8]`.
The spatial arrangement is like:
.. code:: text
(x0, y0) (x1, y1) (x2, y2)
(x3, y3) (x4, y4) (x5, y5)
(x6, y6) (x7, y7) (x8, y8)
Returns:
Tensor: Output of the layer.
"""
可知offset是先行優先排列展開的點集合,再y優先的展開為一維向量。
在RepPointsHead中對feat_map上每個特征點預測的pts,都是相對中心點的偏移,而DeformaConv2D中的offset是相對卷積kernel上對應點的。
dcn_kernel = 3
dcn_pad = dcn_kernel // 2 # dcn_stride=1, dcn_kernel is odd number
base_off = np.arange(-dcn_pad, dcn_pad+1)
base_off_x, base_off_y = np.meshgrid(base_off, base_off)
base_off = np.stack([base_off_y , base_off_x], axis=-1).reshape(-1)
print(base_off)
base_off = torch.tensor(base_off).view(1, -1, 1, 1)
dcn_off = pts_out_init - base_off
feat = dconv(feat, dcn_off.type_as(feat))
array([-1, -1, -1, 0, -1, 1, 0, -1, 0, 0, 0, 1, 1, -1, 1, 0, 1, 1])