r"""Convert the :attr:`MinkowskiEngine.SparseTensor` to a torch dense tensor. Args: :attr:`shape` (torch.Size, optional): The size of the output tensor. :attr:`min_coordinate` (torch.IntTensor, optional): The min coordinates of the output sparse
(self, shape=None, min_coordinate=None, contract_stride=True)
| 455 | return sparse_tensor, min_coords, tensor_stride |
| 456 | |
| 457 | def dense(self, shape=None, min_coordinate=None, contract_stride=True): |
| 458 | r"""Convert the :attr:`MinkowskiEngine.SparseTensor` to a torch dense |
| 459 | tensor. |
| 460 | |
| 461 | Args: |
| 462 | :attr:`shape` (torch.Size, optional): The size of the output tensor. |
| 463 | |
| 464 | :attr:`min_coordinate` (torch.IntTensor, optional): The min |
| 465 | coordinates of the output sparse tensor. Must be divisible by the |
| 466 | current :attr:`tensor_stride`. If 0 is given, it will use the origin for the min coordinate. |
| 467 | |
| 468 | :attr:`contract_stride` (bool, optional): The output coordinates |
| 469 | will be divided by the tensor stride to make features spatially |
| 470 | contiguous. True by default. |
| 471 | |
| 472 | Returns: |
| 473 | :attr:`tensor` (torch.Tensor): the torch tensor with size `[Batch |
| 474 | Dim, Feature Dim, Spatial Dim..., Spatial Dim]`. The coordinate of |
| 475 | each feature can be accessed via `min_coordinate + tensor_stride * |
| 476 | [the coordinate of the dense tensor]`. |
| 477 | |
| 478 | :attr:`min_coordinate` (torch.IntTensor): the D-dimensional vector |
| 479 | defining the minimum coordinate of the output tensor. |
| 480 | |
| 481 | :attr:`tensor_stride` (torch.IntTensor): the D-dimensional vector |
| 482 | defining the stride between tensor elements. |
| 483 | |
| 484 | """ |
| 485 | if min_coordinate is not None: |
| 486 | assert isinstance(min_coordinate, torch.IntTensor) |
| 487 | assert min_coordinate.numel() == self._D |
| 488 | if shape is not None: |
| 489 | assert isinstance(shape, torch.Size) |
| 490 | assert len(shape) == self._D + 2 # batch and channel |
| 491 | if shape[1] != self._F.size(1): |
| 492 | shape = torch.Size([shape[0], self._F.size(1), *[s for s in shape[2:]]]) |
| 493 | |
| 494 | # Use int tensor for all operations |
| 495 | tensor_stride = torch.IntTensor(self.tensor_stride).to(self.device) |
| 496 | |
| 497 | # New coordinates |
| 498 | batch_indices = self.C[:, 0] |
| 499 | |
| 500 | # TODO, batch first |
| 501 | if min_coordinate is None: |
| 502 | min_coordinate, _ = self.C.min(0, keepdim=True) |
| 503 | min_coordinate = min_coordinate[:, 1:] |
| 504 | if not torch.all(min_coordinate >= 0): |
| 505 | raise ValueError( |
| 506 | f"Coordinate has a negative value: {min_coordinate}. Please provide min_coordinate argument" |
| 507 | ) |
| 508 | coords = self.C[:, 1:] |
| 509 | elif isinstance(min_coordinate, int) and min_coordinate == 0: |
| 510 | coords = self.C[:, 1:] |
| 511 | else: |
| 512 | if min_coordinate.ndim == 1: |
| 513 | min_coordinate = min_coordinate.unsqueeze(0) |
| 514 | coords = self.C[:, 1:] - min_coordinate |