def __init__(self, in_channels=4, feat_channels=[], with_distance=False, with_cluster_center=False, with_voxel_center=False, voxel_size=(0.2, 0.2, 4), point_cloud_range=(0, -40, -3, 70.4, 40, 1), norm_cfg=dict(type='BN1d', eps=1e-3, momentum=0.01), mode='max', fusion_layer=None, return_point_feats=False): super(DynamicVFE, self).__init__() assert mode in ['avg', 'max'] assert len(feat_channels) > 0 if with_cluster_center: in_channels += 3 if with_voxel_center: in_channels += 3 if with_distance: in_channels += 3 self.in_channels = in_channels self._with_distance = with_distance self._with_cluster_center = with_cluster_center self._with_voxel_center = with_voxel_center self.return_point_feats = return_point_feats self.fp16_enabled = False # Need pillar (voxel) size and x/y offset in order to calculate offset self.vx = voxel_size[0] self.vy = voxel_size[1] self.vz = voxel_size[2] self.x_offset = self.vx / 2 + point_cloud_range[0] self.y_offset = self.vy / 2 + point_cloud_range[1] self.z_offset = self.vz / 2 + point_cloud_range[2] self.point_cloud_range = point_cloud_range self.scatter = DynamicScatter(voxel_size, point_cloud_range, True) feat_channels = [self.in_channels] + list(feat_channels) vfe_layers = [] for i in range(len(feat_channels) - 1): in_filters = feat_channels[i] out_filters = feat_channels[i + 1] if i > 0: in_filters *= 2 norm_name, norm_layer = build_norm_layer(norm_cfg, out_filters) vfe_layers.append( nn.Sequential(nn.Linear(in_filters, out_filters, bias=False), norm_layer, nn.ReLU(inplace=True))) self.vfe_layers = nn.ModuleList(vfe_layers) self.num_vfe = len(vfe_layers) self.vfe_scatter = DynamicScatter(voxel_size, point_cloud_range, (mode != 'max')) self.cluster_scatter = DynamicScatter(voxel_size, point_cloud_range, average_points=True) self.fusion_layer = None if fusion_layer is not None: self.fusion_layer = builder.build_fusion_layer(fusion_layer)
def __init__(self, model_cfg, num_point_features, voxel_size, point_cloud_range, mode='max', norm_cfg=dict(type='BN1d', eps=1e-3, momentum=0.01)): super().__init__(model_cfg=model_cfg) self.point_cloud_range = point_cloud_range self.vx = voxel_size[0] self.vy = voxel_size[1] self.vz = voxel_size[2] self.x_offset = self.vx / 2 + point_cloud_range[0] self.y_offset = self.vy / 2 + point_cloud_range[1] self.z_offset = self.vz / 2 + point_cloud_range[2] # self.use_norm = self.model_cfg.USE_NORM self.with_distance = self.model_cfg.WITH_DISTANCE self.use_absolute_xyz = self.model_cfg.USE_ABSLOTE_XYZ num_point_features += 5 if self.use_absolute_xyz else 3 if self.with_distance: num_point_features += 1 self.num_filters = self.model_cfg.NUM_FILTERS assert len(self.num_filters) > 0 self.num_filters = [num_point_features] + list(self.num_filters) pfn_layers = [] # TODO: currently only support one PFNLayer for i in range(len(self.num_filters) - 1): in_filters = self.num_filters[i] out_filters = self.num_filters[i + 1] if i > 0: in_filters *= 2 _, norm_layer = build_norm_layer(norm_cfg, out_filters) pfn_layers.append( nn.Sequential(nn.Linear(in_filters, out_filters, bias=False), norm_layer, nn.ReLU(inplace=True))) self.num_pfn = len(pfn_layers) self.pfn_layers = nn.ModuleList(pfn_layers) self.pfn_scatter = DynamicScatter(voxel_size, point_cloud_range, (mode != 'max')) self.cluster_scatter = DynamicScatter(voxel_size, point_cloud_range, average_points=True) voxel_layer = dict(max_num_points=-1, point_cloud_range=point_cloud_range, voxel_size=voxel_size, max_voxels=(-1, -1)) self.voxel_layer = Voxelization(**voxel_layer)
def __init__(self, in_channels=4, feat_channels=(64, ), with_distance=False, with_cluster_center=True, with_voxel_center=True, voxel_size=(0.2, 0.2, 4), point_cloud_range=(0, -40, -3, 70.4, 40, 1), norm_cfg=dict(type='BN1d', eps=1e-3, momentum=0.01), mode='max'): super(DynamicPillarFeatureNet, self).__init__(in_channels, feat_channels, with_distance, with_cluster_center=with_cluster_center, with_voxel_center=with_voxel_center, voxel_size=voxel_size, point_cloud_range=point_cloud_range, norm_cfg=norm_cfg, mode=mode) self.fp16_enabled = False feat_channels = [self.in_channels] + list(feat_channels) pfn_layers = [] # TODO: currently only support one PFNLayer for i in range(len(feat_channels) - 1): in_filters = feat_channels[i] out_filters = feat_channels[i + 1] if i > 0: in_filters *= 2 norm_name, norm_layer = build_norm_layer(norm_cfg, out_filters) pfn_layers.append( nn.Sequential(nn.Linear(in_filters, out_filters, bias=False), norm_layer, nn.ReLU(inplace=True))) self.num_pfn = len(pfn_layers) self.pfn_layers = nn.ModuleList(pfn_layers) self.pfn_scatter = DynamicScatter(voxel_size, point_cloud_range, (mode != 'max')) self.cluster_scatter = DynamicScatter(voxel_size, point_cloud_range, average_points=True)
def test_dynamic_scatter(): if not torch.cuda.is_available(): pytest.skip('test requires GPU and torch+cuda') feats = torch.rand(size=(200000, 3), dtype=torch.float32, device='cuda') * 100 - 50 coors = torch.randint(low=-1, high=20, size=(200000, 3), dtype=torch.int32, device='cuda') dsmean = DynamicScatter([0.32, 0.32, 6], [-74.88, -74.88, -2, 74.88, 74.88, 4], True) dsmax = DynamicScatter([0.32, 0.32, 6], [-74.88, -74.88, -2, 74.88, 74.88, 4], False) # test empty input empty_feats = torch.empty(size=(0, 3), dtype=torch.float32, device='cuda') empty_coors = torch.empty(size=(0, 3), dtype=torch.int32, device='cuda') empty_feats.requires_grad_() empty_feats_out_mean, empty_coors_out_mean = dsmean( empty_feats, empty_coors) empty_feats_out_mean.sum().backward() empty_feats_out_max, empty_coors_out_max = dsmax(empty_feats, empty_coors) empty_feats_out_max.sum().backward() assert empty_feats_out_mean.shape == empty_feats.shape assert empty_feats_out_max.shape == empty_feats.shape assert empty_coors_out_mean.shape == empty_coors.shape assert empty_coors_out_max.shape == empty_coors.shape # test empty reduced output empty_o_feats = torch.rand( size=(200000, 3), dtype=torch.float32, device='cuda') * 100 - 50 empty_o_coors = torch.randint(low=-1, high=0, size=(200000, 3), dtype=torch.int32, device='cuda') empty_o_feats.requires_grad_() empty_o_feats_out_mean, empty_o_coors_out_mean = dsmean( empty_o_feats, empty_o_coors) empty_o_feats_out_mean.sum().backward() assert (empty_o_feats.grad == 0).all() empty_o_feats_out_max, empty_o_coors_out_max = dsmax( empty_o_feats, empty_o_coors) empty_o_feats_out_max.sum().backward() assert (empty_o_feats.grad == 0).all() # test non-empty input ref_voxel_coors = coors.unique(dim=0, sorted=True) ref_voxel_coors = ref_voxel_coors[ref_voxel_coors.min(dim=-1).values >= 0] ref_voxel_feats_mean = [] ref_voxel_feats_max = [] for ref_voxel_coor in ref_voxel_coors: voxel_mask = (coors == ref_voxel_coor).all(dim=-1) ref_voxel_feats_mean.append(feats[voxel_mask].mean(dim=0)) ref_voxel_feats_max.append(feats[voxel_mask].max(dim=0).values) ref_voxel_feats_mean = torch.stack(ref_voxel_feats_mean) ref_voxel_feats_max = torch.stack(ref_voxel_feats_max) feats_out_mean, coors_out_mean = dsmean(feats, coors) seq_mean = (coors_out_mean[:, 0] * 400 + coors_out_mean[:, 1] * 20 + coors_out_mean[:, 2]).argsort() feats_out_mean = feats_out_mean[seq_mean] coors_out_mean = coors_out_mean[seq_mean] feats_out_max, coors_out_max = dsmax(feats, coors) seq_max = (coors_out_max[:, 0] * 400 + coors_out_max[:, 1] * 20 + coors_out_max[:, 2]).argsort() feats_out_max = feats_out_max[seq_max] coors_cout_max = coors_out_max[seq_max] assert (coors_out_mean == ref_voxel_coors).all() assert torch.allclose(feats_out_mean, ref_voxel_feats_mean, atol=1e-2, rtol=1e-5) assert (coors_cout_max == ref_voxel_coors).all() assert torch.allclose(feats_out_max, ref_voxel_feats_max, atol=1e-2, rtol=1e-5) # test grad # feats = torch.rand(size=(100, 4), dtype=torch.float32, device='cuda') * 100 - 50 coors = torch.randint(low=-1, high=3, size=(100, 3), dtype=torch.int32, device='cuda') feats.requires_grad_() gradcheck(dsmean, (feats, coors), eps=1e-2, atol=1e-2, rtol=1e-5) gradcheck(dsmax, (feats, coors), eps=1e-2, atol=1e-2, rtol=1e-5)
def __init__(self, voxel_size=(0.2, 0.2, 4), point_cloud_range=(0, -40, -3, 70.4, 40, 1)): super(DynamicSimpleVFE, self).__init__() self.scatter = DynamicScatter(voxel_size, point_cloud_range, True) self.fp16_enabled = False
def __init__(self, in_channels=4, feat_channels=[], with_distance=False, with_cluster_center=False, with_voxel_center=False, voxel_size=(0.2, 0.2, 4), point_cloud_range=(0, -40, -3, 70.4, 40, 1), norm_cfg=dict(type='BN1d', eps=1e-3, momentum=0.01), mode='max', fusion_layer=None, return_point_feats=False): super(HardVFE, self).__init__() assert len(feat_channels) > 0 if with_cluster_center: in_channels += 3 if with_voxel_center: in_channels += 3 if with_distance: in_channels += 3 self.in_channels = in_channels self._with_distance = with_distance self._with_cluster_center = with_cluster_center self._with_voxel_center = with_voxel_center self.return_point_feats = return_point_feats self.fp16_enabled = False # Need pillar (voxel) size and x/y offset to calculate pillar offset self.vx = voxel_size[0] self.vy = voxel_size[1] self.vz = voxel_size[2] self.x_offset = self.vx / 2 + point_cloud_range[0] self.y_offset = self.vy / 2 + point_cloud_range[1] self.z_offset = self.vz / 2 + point_cloud_range[2] self.point_cloud_range = point_cloud_range self.scatter = DynamicScatter(voxel_size, point_cloud_range, True) feat_channels = [self.in_channels] + list(feat_channels) vfe_layers = [] for i in range(len(feat_channels) - 1): in_filters = feat_channels[i] out_filters = feat_channels[i + 1] if i > 0: in_filters *= 2 # TODO: pass norm_cfg to VFE # norm_name, norm_layer = build_norm_layer(norm_cfg, out_filters) if i == (len(feat_channels) - 2): cat_max = False max_out = True if fusion_layer: max_out = False else: max_out = True cat_max = True vfe_layers.append( VFELayer(in_filters, out_filters, norm_cfg=norm_cfg, max_out=max_out, cat_max=cat_max)) self.vfe_layers = nn.ModuleList(vfe_layers) self.num_vfe = len(vfe_layers) self.fusion_layer = None if fusion_layer is not None: self.fusion_layer = builder.build_fusion_layer(fusion_layer)