| 106 | expansion = 4 |
| 107 | |
| 108 | def __init__(self, inplanes, planes, stride=1, downsample=None, dcn=None): |
| 109 | super(Bottleneck, self).__init__() |
| 110 | self.with_dcn = dcn is not None |
| 111 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False) |
| 112 | self.bn1 = BatchNorm2d(planes) |
| 113 | fallback_on_stride = False |
| 114 | self.with_modulated_dcn = False |
| 115 | if self.with_dcn: |
| 116 | fallback_on_stride = dcn.get('fallback_on_stride', False) |
| 117 | self.with_modulated_dcn = dcn.get('modulated', False) |
| 118 | if not self.with_dcn or fallback_on_stride: |
| 119 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, |
| 120 | stride=stride, padding=1, bias=False) |
| 121 | else: |
| 122 | deformable_groups = dcn.get('deformable_groups', 1) |
| 123 | if not self.with_modulated_dcn: |
| 124 | #from assets.ops.dcn import DeformConv |
| 125 | from ..assets.ops.dcn import DeformConv |
| 126 | conv_op = DeformConv |
| 127 | offset_channels = 18 |
| 128 | else: |
| 129 | #from assets.ops.dcn import ModulatedDeformConv |
| 130 | from ..assets.ops.dcn import ModulatedDeformConv |
| 131 | conv_op = ModulatedDeformConv |
| 132 | offset_channels = 27 |
| 133 | self.conv2_offset = nn.Conv2d( |
| 134 | planes, deformable_groups * offset_channels, |
| 135 | kernel_size=3, |
| 136 | padding=1) |
| 137 | self.conv2 = conv_op( |
| 138 | planes, planes, kernel_size=3, padding=1, stride=stride, |
| 139 | deformable_groups=deformable_groups, bias=False) |
| 140 | self.bn2 = BatchNorm2d(planes) |
| 141 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) |
| 142 | self.bn3 = BatchNorm2d(planes * 4) |
| 143 | self.relu = nn.ReLU(inplace=True) |
| 144 | self.downsample = downsample |
| 145 | self.stride = stride |
| 146 | self.dcn = dcn |
| 147 | self.with_dcn = dcn is not None |
| 148 | |
| 149 | def forward(self, x): |
| 150 | residual = x |