def _test_forward_with_batchsize(self, device, contiguous, batch_sz): x, _, offset, _, stride, padding, dilation = self.get_fn_args( device, contiguous, batch_sz) in_channels = 6 out_channels = 2 kernel_size = (3, 2) groups = 2 layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups).to(device=x.device, dtype=x.dtype) res = layer(x, offset) weight = layer.weight.data bias = layer.bias.data expected = self.expected_fn(x, weight, offset, bias, stride=stride, padding=padding, dilation=dilation) self.assertTrue(torch.allclose(res, expected), '\nres:\n{}\nexpected:\n{}'.format(res, expected)) # test for wrong sizes with self.assertRaises(RuntimeError): wrong_offset = torch.rand_like(offset[:, :2]) res = layer(x, wrong_offset)
def __init__(self, in_nc, out_nc, kernel_size=3, stride=1, padding=1, dilation=1, groups=1, bias=True): super(DeformConv2d, self).__init__() self.conv_offset = nn.Conv2d(in_nc, 2 * (kernel_size**2), kernel_size=kernel_size, stride=stride, padding=padding, bias=bias) self.conv_offset.weight.data.zero_() self.conv_offset.bias.data.zero_() self.dcn_conv = O.DeformConv2d(in_nc, out_nc, kernel_size=kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias)
def test_forward(self, device, contiguous, batch_sz, dtype=None): dtype = dtype or self.dtype x, _, offset, mask, _, stride, padding, dilation = self.get_fn_args(device, contiguous, batch_sz, dtype) in_channels = 6 out_channels = 2 kernel_size = (3, 2) groups = 2 tol = 2e-3 if dtype is torch.half else 1e-5 layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups).to(device=x.device, dtype=dtype) res = layer(x, offset, mask) weight = layer.weight.data bias = layer.bias.data expected = self.expected_fn(x, weight, offset, mask, bias, stride=stride, padding=padding, dilation=dilation) torch.testing.assert_close( res.to(expected), expected, rtol=tol, atol=tol, msg='\nres:\n{}\nexpected:\n{}'.format(res, expected) ) # no modulation test res = layer(x, offset) expected = self.expected_fn(x, weight, offset, None, bias, stride=stride, padding=padding, dilation=dilation) torch.testing.assert_close( res.to(expected), expected, rtol=tol, atol=tol, msg='\nres:\n{}\nexpected:\n{}'.format(res, expected) )
def _test_forward_with_batchsize(self, device, contiguous, batch_sz, dtype): x, _, offset, mask, _, stride, padding, dilation = self.get_fn_args(device, contiguous, batch_sz, dtype) in_channels = 6 out_channels = 2 kernel_size = (3, 2) groups = 2 tol = 2e-3 if dtype is torch.half else 1e-5 layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups).to(device=x.device, dtype=dtype) res = layer(x, offset, mask) weight = layer.weight.data bias = layer.bias.data expected = self.expected_fn(x, weight, offset, mask, bias, stride=stride, padding=padding, dilation=dilation) self.assertTrue(torch.allclose(res.to(expected.dtype), expected, rtol=tol, atol=tol), '\nres:\n{}\nexpected:\n{}'.format(res, expected)) # no modulation test res = layer(x, offset) expected = self.expected_fn(x, weight, offset, None, bias, stride=stride, padding=padding, dilation=dilation) self.assertTrue(torch.allclose(res.to(expected.dtype), expected, rtol=tol, atol=tol), '\nres:\n{}\nexpected:\n{}'.format(res, expected)) # test for wrong sizes with self.assertRaises(RuntimeError): wrong_offset = torch.rand_like(offset[:, :2]) res = layer(x, wrong_offset) with self.assertRaises(RuntimeError): wrong_mask = torch.rand_like(mask[:, :2]) res = layer(x, offset, wrong_mask)
def __init__(self, in_channels, out_channels, kernel_size=3, stride=1, dilation=1, groups=1, offset_groups=1): super().__init__() offset_channels = 2 * kernel_size * kernel_size self.conv2d_offset = nn.Conv2d( in_channels, offset_channels * offset_groups, kernel_size=kernel_size, stride=stride, padding=dilation, dilation=dilation, ) self.conv2d = ops.DeformConv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=dilation, dilation=dilation, groups=groups, bias=False)
def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True): super().__init__() self.layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, bias=bias) kernel_height, kernel_width = self.layer.kernel_size offset_groups = groups offset_channels = 2 * offset_groups * kernel_height * kernel_width self.offsets = nn.Conv2d(in_channels, offset_channels, kernel_size=kernel_size, padding=padding) self.out_channels = out_channels
def __init__(self, chi, cho, k, s=1, p=None, dilation=1, groups=1, bias=True): super().__init__() k = k if isinstance(k, tuple) else (k, k) p = autopad(k, p) self.conv = ops.DeformConv2d(chi, cho, k, s, p, dilation=dilation, groups=groups, bias=bias) # for each group we need output channels of 2 to get for each kernel weight # offset position in x, y (2 channels) and we have to know that for every # pixel in the convolution output, thus we use same kernel size and padding!! self.offset = nn.Conv2d(chi, groups * 2 * k[0] * k[1], k, s, p, dilation=dilation, groups=groups, bias=True) self._init_offset()
def deformable_conv(in_planes, out_planes, kernel_size=3, strides=1, padding=1, use_bias=True): return ops.DeformConv2d(in_planes, out_planes, kernel_size, strides, padding, bias=use_bias)
def test_wrong_sizes(self): in_channels = 6 out_channels = 2 kernel_size = (3, 2) groups = 2 x, _, offset, mask, _, stride, padding, dilation = self.get_fn_args('cpu', contiguous=True, batch_sz=10, dtype=self.dtype) layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups) with pytest.raises(RuntimeError, match="the shape of the offset"): wrong_offset = torch.rand_like(offset[:, :2]) layer(x, wrong_offset) with pytest.raises(RuntimeError, match=r'mask.shape\[1\] is not valid'): wrong_mask = torch.rand_like(mask[:, :2]) layer(x, offset, wrong_mask)
def _test_forward(self, device, contiguous): x, _, offset, _, stride, padding, dilation = self.get_fn_args(device, contiguous) in_channels = 6 out_channels = 2 kernel_size = (3, 2) groups = 2 offset_groups = 3 layer = ops.DeformConv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, dilation=dilation, groups=groups, offset_groups=offset_groups).to(device=x.device, dtype=x.dtype) res = layer(x, offset) weight = layer.weight.data bias = layer.bias.data expected = self.expected_fn(x, weight, offset, bias, stride=stride, padding=padding, dilation=dilation) self.assertTrue(torch.allclose(res, expected), '\nres:\n{}\nexpected:\n{}'.format(res, expected))
def __init__(self, inplanes, outplanes, stride=1, downsample=None, dilation=1, deformable_groups=1): super(AdaptBlock, self).__init__() regular_matrix = torch.tensor([[-1, -1, -1, 0, 0, 0, 1, 1, 1],\ [-1, 0, 1, -1 ,0 ,1 ,-1, 0, 1]]) self.register_buffer('regular_matrix', regular_matrix.float()) self.downsample = downsample self.transform_matrix_conv = nn.Conv2d(inplanes, 4, 3, 1, 1, bias=True) self.translation_conv = nn.Conv2d(inplanes, 2, 3, 1, 1, bias=True) self.adapt_conv = ops.DeformConv2d(inplanes, outplanes, kernel_size=3, stride=stride, \ padding=dilation, dilation=dilation, bias=False, groups=deformable_groups) self.bn = nn.BatchNorm2d(outplanes, momentum=BN_MOMENTUM) self.relu = nn.ReLU(inplace=True)
def test_forward_scriptability(self): # Non-regression test for https://github.com/pytorch/vision/issues/4078 torch.jit.script(ops.DeformConv2d(in_channels=8, out_channels=8, kernel_size=3))