test_rendering.py 4.19 KB
Newer Older
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
1
import pytest
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
2
3
import torch

4
5
6
7
8
9
10
from nerfacc import (
    accumulate_along_rays,
    render_visibility,
    render_weight_from_alpha,
    render_weight_from_density,
    rendering,
)
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
11
12

device = "cuda:0"
13
14
batch_size = 32
eps = 1e-6
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
15
16


Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
17
@pytest.mark.skipif(not torch.cuda.is_available, reason="No CUDA device")
18
19
20
21
22
23
24
25
26
def test_render_visibility():
    packed_info = torch.tensor(
        [[0, 1], [1, 0], [1, 4]], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    alphas = torch.tensor(
        [0.4, 0.3, 0.8, 0.8, 0.5], dtype=torch.float32, device=device
    ).unsqueeze(
        -1
    )  # (n_samples, 1)
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
27

28
29
30
    # transmittance: [1.0, 1.0, 0.7, 0.14, 0.028]
    vis, packed_info_vis = render_visibility(
        packed_info, alphas, early_stop_eps=0.03, alpha_thre=0.0
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
31
    )
32
33
    vis_tgt = torch.tensor(
        [True, True, True, True, False], dtype=torch.bool, device=device
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
34
    )
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
    packed_info_vis_tgt = torch.tensor(
        [[0, 1], [1, 0], [1, 3]], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    assert torch.allclose(vis, vis_tgt)
    assert torch.allclose(packed_info_vis, packed_info_vis_tgt)

    # transmittance: [1.0, 1.0, 1.0, 0.2, 0.04]
    vis, packed_info_vis = render_visibility(
        packed_info, alphas, early_stop_eps=0.05, alpha_thre=0.35
    )
    vis_tgt = torch.tensor(
        [True, False, True, True, False], dtype=torch.bool, device=device
    )
    packed_info_vis_tgt = torch.tensor(
        [[0, 1], [1, 0], [1, 2]], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    assert torch.allclose(vis, vis_tgt)
    assert torch.allclose(packed_info_vis, packed_info_vis_tgt)


@pytest.mark.skipif(not torch.cuda.is_available, reason="No CUDA device")
def test_render_weight_from_alpha():
    packed_info = torch.tensor(
        [[0, 1], [1, 0], [1, 4]], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    alphas = torch.tensor(
        [0.4, 0.3, 0.8, 0.8, 0.5], dtype=torch.float32, device=device
    ).unsqueeze(
        -1
    )  # (n_samples, 1)

    # transmittance: [1.0, 1.0, 0.7, 0.14, 0.028]
    weights = render_weight_from_alpha(
        packed_info, alphas, early_stop_eps=0.03, alpha_thre=0.0
    )
    weights_tgt = torch.tensor(
        [1.0 * 0.4, 1.0 * 0.3, 0.7 * 0.8, 0.14 * 0.8, 0.0 * 0.0],
        dtype=torch.float32,
        device=device,
    )
    assert torch.allclose(weights, weights_tgt)


def test_render_weight_from_density():
    packed_info = torch.tensor(
        [[0, 1], [1, 0], [1, 4]], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    sigmas = torch.rand((batch_size, 1), device=device)  # (n_samples, 1)
    t_starts = torch.rand_like(sigmas)
    t_ends = torch.rand_like(sigmas) + 1.0
    alphas = 1.0 - torch.exp(-sigmas * (t_ends - t_starts))

    weights = render_weight_from_density(packed_info, t_starts, t_ends, sigmas)
    weights_tgt = render_weight_from_alpha(packed_info, alphas)
    assert torch.allclose(weights, weights_tgt)


def test_accumulate_along_rays():
    ray_indices = torch.tensor(
        [0, 2, 2, 2, 2], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    weights = torch.tensor(
        [0.4, 0.3, 0.8, 0.8, 0.5], dtype=torch.float32, device=device
    )
    values = torch.rand((5, 2), device=device)  # (n_samples, 1)

    ray_values = accumulate_along_rays(
        weights, ray_indices, values=values, n_rays=3
    )
    assert ray_values.shape == (3, 2)
    assert torch.allclose(ray_values[0, :], weights[0, None] * values[0, :])
    assert (ray_values[1, :] == 0).all()
    assert torch.allclose(
        ray_values[2, :], (weights[1:, None] * values[1:]).sum(dim=0)
    )


def test_rendering():
    def rgb_sigma_fn(t_starts, t_ends, ray_indices):
        return torch.hstack([t_starts] * 3), t_starts

    packed_info = torch.tensor(
        [[0, 1], [1, 0], [1, 4]], dtype=torch.int32, device=device
    )  # (n_rays, 2)
    sigmas = torch.rand((5, 1), device=device)  # (n_samples, 1)
    t_starts = torch.rand_like(sigmas)
    t_ends = torch.rand_like(sigmas) + 1.0

123
124
125
    _, _, _ = rendering(
        packed_info, t_starts, t_ends, rgb_sigma_fn=rgb_sigma_fn
    )
Ruilong Li(李瑞龙)'s avatar
Ruilong Li(李瑞龙) committed
126
127
128


if __name__ == "__main__":
129
130
131
132
133
    test_render_visibility()
    test_render_weight_from_alpha()
    test_render_weight_from_density()
    test_accumulate_along_rays()
    test_rendering()