"driver/vscode:/vscode.git/clone" did not exist on "19a93dac051f3b5200fe00151b8fa5994aa890dd"
fps.py 2.32 KB
Newer Older
rusty1s's avatar
update  
rusty1s committed
1
from typing import Optional
rusty1s's avatar
rusty1s committed
2

rusty1s's avatar
update  
rusty1s committed
3
import torch
rusty1s's avatar
rusty1s committed
4
from torch import Tensor
rusty1s's avatar
rusty1s committed
5
6


rusty1s's avatar
rusty1s committed
7
@torch.jit._overload  # noqa
rusty1s's avatar
rusty1s committed
8
def fps(src, batch=None, ratio=None, random_start=True):  # noqa
rusty1s's avatar
rusty1s committed
9
    # type: (Tensor, Optional[Tensor], Optional[float], bool) -> Tensor
rusty1s's avatar
rusty1s committed
10
    pass  # pragma: no cover
Duc's avatar
Duc committed
11
12


rusty1s's avatar
rusty1s committed
13
@torch.jit._overload  # noqa
rusty1s's avatar
rusty1s committed
14
def fps(src, batch=None, ratio=None, random_start=True):  # noqa
Duc's avatar
Duc committed
15
    # type: (Tensor, Optional[Tensor], Optional[Tensor], bool) -> Tensor
rusty1s's avatar
rusty1s committed
16
    pass  # pragma: no cover
Duc's avatar
Duc committed
17
18


rusty1s's avatar
rusty1s committed
19
def fps(src: torch.Tensor, batch=None, ratio=None, random_start=True):  # noqa
rusty1s's avatar
rusty1s committed
20
21
22
23
    r""""A sampling algorithm from the `"PointNet++: Deep Hierarchical Feature
    Learning on Point Sets in a Metric Space"
    <https://arxiv.org/abs/1706.02413>`_ paper, which iteratively samples the
    most distant point with regard to the rest points.
rusty1s's avatar
rusty1s committed
24
25

    Args:
rusty1s's avatar
update  
rusty1s committed
26
        src (Tensor): Point feature matrix
rusty1s's avatar
rusty1s committed
27
28
29
30
            :math:`\mathbf{X} \in \mathbb{R}^{N \times F}`.
        batch (LongTensor, optional): Batch vector
            :math:`\mathbf{b} \in {\{ 0, \ldots, B-1\}}^N`, which assigns each
            node to a specific example. (default: :obj:`None`)
rusty1s's avatar
rusty1s committed
31
32
        ratio (float or Tensor, optional): Sampling ratio.
            (default: :obj:`0.5`)
rusty1s's avatar
rusty1s committed
33
34
        random_start (bool, optional): If set to :obj:`False`, use the first
            node in :math:`\mathbf{X}` as starting node. (default: obj:`True`)
rusty1s's avatar
rusty1s committed
35

rusty1s's avatar
docs  
rusty1s committed
36
37
    :rtype: :class:`LongTensor`

rusty1s's avatar
rusty1s committed
38

rusty1s's avatar
update  
rusty1s committed
39
    .. code-block:: python
rusty1s's avatar
rusty1s committed
40
41
42
43

        import torch
        from torch_cluster import fps

rusty1s's avatar
update  
rusty1s committed
44
45
46
        src = torch.Tensor([[-1, -1], [-1, 1], [1, -1], [1, 1]])
        batch = torch.tensor([0, 0, 0, 0])
        index = fps(src, batch, ratio=0.5)
rusty1s's avatar
rusty1s committed
47
48
    """

rusty1s's avatar
rusty1s committed
49
50
51
52
53
54
55
56
    r: Optional[Tensor] = None
    if ratio is None:
        r = torch.tensor(0.5, dtype=src.dtype, device=src.device)
    elif isinstance(ratio, float):
        r = torch.tensor(ratio, dtype=src.dtype, device=src.device)
    else:
        r = ratio
    assert r is not None
57

rusty1s's avatar
update  
rusty1s committed
58
    if batch is not None:
rusty1s's avatar
rusty1s committed
59
        assert src.size(0) == batch.numel()
rusty1s's avatar
update  
rusty1s committed
60
        batch_size = int(batch.max()) + 1
rusty1s's avatar
rusty1s committed
61

rusty1s's avatar
update  
rusty1s committed
62
63
        deg = src.new_zeros(batch_size, dtype=torch.long)
        deg.scatter_add_(0, batch, torch.ones_like(batch))
rusty1s's avatar
typos  
rusty1s committed
64

rusty1s's avatar
rusty1s committed
65
        ptr = deg.new_zeros(batch_size + 1)
rusty1s's avatar
fix  
rusty1s committed
66
        torch.cumsum(deg, 0, out=ptr[1:])
rusty1s's avatar
rusty1s committed
67
68
    else:
        ptr = torch.tensor([0, src.size(0)], device=src.device)
rusty1s's avatar
rusty1s committed
69

rusty1s's avatar
rusty1s committed
70
    return torch.ops.torch_cluster.fps(src, ptr, r, random_start)