Point Cloud Serialization Point cloud is sparse, here we use "sparsify" to specifically refer to preparing "spconv.SparseConvTensor" for SpConv. relay on ["grid_coord" or "coord" + "grid_size", "batch", "feat"] pad: padding sparse for sparse shape.
(self, pad=96)
| 136 | self["serialized_inverse"] = inverse |
| 137 | |
| 138 | def sparsify(self, pad=96): |
| 139 | """ |
| 140 | Point Cloud Serialization |
| 141 | |
| 142 | Point cloud is sparse, here we use "sparsify" to specifically refer to |
| 143 | preparing "spconv.SparseConvTensor" for SpConv. |
| 144 | |
| 145 | relay on ["grid_coord" or "coord" + "grid_size", "batch", "feat"] |
| 146 | |
| 147 | pad: padding sparse for sparse shape. |
| 148 | """ |
| 149 | assert {"feat", "batch"}.issubset(self.keys()) |
| 150 | if "grid_coord" not in self.keys(): |
| 151 | # if you don't want to operate GridSampling in data augmentation, |
| 152 | # please add the following augmentation into your pipline: |
| 153 | # dict(type="Copy", keys_dict={"grid_size": 0.01}), |
| 154 | # (adjust `grid_size` to what your want) |
| 155 | assert {"grid_size", "coord"}.issubset(self.keys()) |
| 156 | self["grid_coord"] = torch.div( |
| 157 | self.coord - self.coord.min(0)[0], self.grid_size, rounding_mode="trunc" |
| 158 | ).int() |
| 159 | if "sparse_shape" in self.keys(): |
| 160 | sparse_shape = self.sparse_shape |
| 161 | else: |
| 162 | sparse_shape = torch.add( |
| 163 | torch.max(self.grid_coord, dim=0).values, pad |
| 164 | ).tolist() |
| 165 | sparse_conv_feat = spconv.SparseConvTensor( |
| 166 | features=self.feat, |
| 167 | indices=torch.cat( |
| 168 | [self.batch.unsqueeze(-1).int(), self.grid_coord.int()], dim=1 |
| 169 | ).contiguous(), |
| 170 | spatial_shape=sparse_shape, |
| 171 | batch_size=self.batch[-1].tolist() + 1, |
| 172 | ) |
| 173 | self["sparse_shape"] = sparse_shape |
| 174 | self["sparse_conv_feat"] = sparse_conv_feat |
| 175 | |
| 176 | |
| 177 | class PointModule(nn.Module): |