eval_demo.py 6.09 KB
Newer Older
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
1
2
3
4
5
6
7
8
9
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.


import dataclasses
import os
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
10
from typing import Any, cast, Dict, List, Optional, Tuple
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
11
12
13

import lpips
import torch
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
14
from pytorch3d.implicitron.dataset.data_source import ImplicitronDataSource, Task
15
from pytorch3d.implicitron.dataset.json_index_dataset import JsonIndexDataset
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
16
17
18
from pytorch3d.implicitron.dataset.json_index_dataset_map_provider import (
    CO3D_CATEGORIES,
)
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from pytorch3d.implicitron.evaluation.evaluate_new_view_synthesis import (
    aggregate_nvs_results,
    eval_batch,
    pretty_print_nvs_metrics,
    summarize_nvs_eval_results,
)
from pytorch3d.implicitron.models.model_dbir import ModelDBIR
from pytorch3d.implicitron.tools.utils import dataclass_to_cuda_
from tqdm import tqdm


def main() -> None:
    """
    Evaluates new view synthesis metrics of a simple depth-based image rendering
    (DBIR) model for multisequence/singlesequence tasks for several categories.

    The evaluation is conducted on the same data as in [1] and, hence, the results
    are directly comparable to the numbers reported in [1].

    References:
        [1] J. Reizenstein, R. Shapovalov, P. Henzler, L. Sbordone,
                P. Labatut, D. Novotny:
            Common Objects in 3D: Large-Scale Learning
                and Evaluation of Real-life 3D Category Reconstruction
    """

    task_results = {}
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
46
    for task in (Task.SINGLE_SEQUENCE, Task.MULTI_SEQUENCE):
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
47
        task_results[task] = []
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
48
49
50
51
        for category in CO3D_CATEGORIES[: (20 if task == Task.SINGLE_SEQUENCE else 10)]:
            for single_sequence_id in (
                (0, 1) if task == Task.SINGLE_SEQUENCE else (None,)
            ):
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
                category_result = evaluate_dbir_for_category(
                    category, task=task, single_sequence_id=single_sequence_id
                )
                print("")
                print(
                    f"Results for task={task}; category={category};"
                    + (
                        f" sequence={single_sequence_id}:"
                        if single_sequence_id is not None
                        else ":"
                    )
                )
                pretty_print_nvs_metrics(category_result)
                print("")

                task_results[task].append(category_result)
            _print_aggregate_results(task, task_results)

    for task in task_results:
        _print_aggregate_results(task, task_results)


def evaluate_dbir_for_category(
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
75
76
    category: str,
    task: Task,
77
    bg_color: Tuple[float, float, float] = (0.0, 0.0, 0.0),
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
78
79
80
81
82
83
84
85
86
87
88
89
90
    single_sequence_id: Optional[int] = None,
    num_workers: int = 16,
):
    """
    Evaluates new view synthesis metrics of a simple depth-based image rendering
    (DBIR) model for a given task, category, and sequence (in case task=='singlesequence').

    Args:
        category: Object category.
        bg_color: Background color of the renders.
        task: Evaluation task. Either singlesequence or multisequence.
        single_sequence_id: The ID of the evaluiation sequence for the singlesequence task.
        num_workers: The number of workers for the employed dataloaders.
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
91
        path_manager: (optional) Used for interpreting paths.
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
92
93
94
95
96
97
98
99
100

    Returns:
        category_result: A dictionary of quantitative metrics.
    """

    single_sequence_id = single_sequence_id if single_sequence_id is not None else -1

    torch.manual_seed(42)

Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
101
102
103
104
105
106
107
    dataset_map_provider_args = {
        "category": category,
        "dataset_root": os.environ["CO3D_DATASET_ROOT"],
        "assert_single_seq": task == Task.SINGLE_SEQUENCE,
        "task_str": task.value,
        "test_on_train": False,
        "test_restrict_sequence_id": single_sequence_id,
108
        "dataset_JsonIndexDataset_args": {"load_point_clouds": True},
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
109
110
111
    }
    data_source = ImplicitronDataSource(
        dataset_map_provider_JsonIndexDatasetMapProvider_args=dataset_map_provider_args
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
112
113
    )

Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
114
    datasets, dataloaders = data_source.get_datasets_and_dataloaders()
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
115

116
117
118
119
    test_dataset = datasets.test
    test_dataloader = dataloaders.test
    if test_dataset is None or test_dataloader is None:
        raise ValueError("must have a test dataset.")
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
120

Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
121
    all_train_cameras = data_source.get_all_train_cameras()
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
122

123
    image_size = cast(JsonIndexDataset, test_dataset).image_width
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
124
125
126
127
128

    if image_size is None:
        raise ValueError("Image size should be set in the dataset")

    # init the simple DBIR model
129
130
131
    model = ModelDBIR(  # pyre-ignore[28]: c’tor implicitly overridden
        render_image_width=image_size,
        render_image_height=image_size,
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
        bg_color=bg_color,
        max_points=int(1e5),
    )
    model.cuda()

    # init the lpips model for eval
    lpips_model = lpips.LPIPS(net="vgg")
    lpips_model = lpips_model.cuda()

    per_batch_eval_results = []
    print("Evaluating DBIR model ...")
    for frame_data in tqdm(test_dataloader):
        frame_data = dataclass_to_cuda_(frame_data)
        preds = model(**dataclasses.asdict(frame_data))
        per_batch_eval_results.append(
            eval_batch(
                frame_data,
149
                preds["implicitron_render"],
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
150
151
                bg_color=bg_color,
                lpips_model=lpips_model,
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
152
                source_cameras=all_train_cameras,
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
153
154
155
            )
        )

156
157
158
159
160
    if task == Task.SINGLE_SEQUENCE:
        camera_difficulty_bin_breaks = 0.97, 0.98
    else:
        camera_difficulty_bin_breaks = 2.0 / 3, 5.0 / 6

Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
161
    category_result_flat, category_result = summarize_nvs_eval_results(
162
        per_batch_eval_results, task, camera_difficulty_bin_breaks
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
163
164
165
166
167
    )

    return category_result["results"]


Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
168
169
170
def _print_aggregate_results(
    task: Task, task_results: Dict[Task, List[List[Dict[str, Any]]]]
) -> None:
Jeremy Reizenstein's avatar
Jeremy Reizenstein committed
171
172
173
174
175
176
177
178
179
180
181
182
    """
    Prints the aggregate metrics for a given task.
    """
    aggregate_task_result = aggregate_nvs_results(task_results[task])
    print("")
    print(f"Aggregate results for task={task}:")
    pretty_print_nvs_metrics(aggregate_task_result)
    print("")


if __name__ == "__main__":
    main()