Skip to content

Commit c8010f6

Browse files
committed
feat(v2_metric): and fix vis script with model name directly.
1 parent 4c13b46 commit c8010f6

File tree

10 files changed

+512
-168
lines changed

10 files changed

+512
-168
lines changed

3_vis.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,31 @@
1919
from hydra.core.hydra_config import HydraConfig
2020
from scripts.network.dataloader import HDF5Dataset
2121
from scripts.pl_model import ModelWrapper
22+
from scripts.utils import bc
2223

23-
@hydra.main(version_base=None, config_path="conf", config_name="eval")
24+
@hydra.main(version_base=None, config_path="conf", config_name="vis")
2425
def main(cfg):
2526
pl.seed_everything(cfg.seed, workers=True)
2627
output_dir = HydraConfig.get().runtime.output_dir
2728

2829
if not os.path.exists(cfg.checkpoint):
2930
print(f"Checkpoint {cfg.checkpoint} does not exist. Need checkpoints for evaluation.")
3031
sys.exit(1)
31-
32+
33+
if cfg.res_name is None:
34+
cfg.res_name = cfg.checkpoint.split("/")[-1].split(".")[0]
35+
print(f"{bc.BOLD}NOTE{bc.ENDC}: res_name is not specified, use {bc.OKBLUE}{cfg.res_name}{bc.ENDC} as default.")
36+
3237
checkpoint_params = DictConfig(torch.load(cfg.checkpoint)["hyper_parameters"])
33-
cfg.output = checkpoint_params.cfg.output + f"-{cfg.av2_mode}"
38+
cfg.output = checkpoint_params.cfg.output
3439
cfg.model.update(checkpoint_params.cfg.model)
3540
mymodel = ModelWrapper.load_from_checkpoint(cfg.checkpoint, cfg=cfg, eval=True)
3641

3742
wandb_logger = WandbLogger(save_dir=output_dir,
3843
entity="kth-rpl",
3944
project=f"deflow-eval",
4045
name=f"{cfg.output}",
41-
offline=(cfg.wandb_mode == "offline"))
46+
offline=True)
4247

4348
trainer = pl.Trainer(logger=wandb_logger, devices=1)
4449
# NOTE(Qingwen): search & check in pl_model.py : def test_step(self, batch, res_dict)

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Task: Scene Flow Estimation in Autonomous Driving. Pre-trained weights for model
2121

2222
**Environment**: Clone the repo and build the environment, check [detail installation](assets/README.md) for more information. [Conda](https://docs.conda.io/projects/miniconda/en/latest/)/[Mamba](https://github.com/mamba-org/mamba) is recommended.
2323
```
24-
git clone https://github.com/KTH-RPL/DeFlow
24+
git clone --recursive https://github.com/KTH-RPL/DeFlow.git
2525
cd DeFlow
2626
mamba env create -f environment.yaml
2727
```
@@ -100,14 +100,14 @@ We provide a script to visualize the results of the model. You can specify the c
100100
python 3_vis.py checkpoint=/home/kin/model.ckpt dataset_path=/home/kin/data/av2/preprocess/sensor/vis
101101

102102
# Then terminal will tell you the command you need run. For example here is the output of the above:
103-
Model: DeFlow, Checkpoint from: /logs/wandb/deflow-10078447/checkpoints/epoch_35_seflow.ckpt
104-
We already write the flow_est into the dataset, please run following commend to visualize the flow. Copy and paste it to your terminal:
105-
python tests/scene_flow.py --flow_mode='flow_est' --data_dir=/home/kin/data/av2/preprocess/sensor/vis
103+
Model: DeFlow, Checkpoint from: /home/kin/model_zoo/deflow.ckpt
104+
We already write the estimate flow: deflow into the dataset, please run following commend to visualize the flow. Copy and paste it to your terminal:
105+
python tests/scene_flow.py --flow_mode 'deflow' --data_dir /home/kin/data/av2/preprocess/sensor/mini
106106
Enjoy! ^v^ ------
107107

108108

109109
# Then run the test with changed flow_mode between estimate and gt [flow_est, flow]
110-
python tests/scene_flow.py --flow_mode='flow_est' --data_dir=/home/kin/data/av2/preprocess/sensor/vis
110+
python tests/scene_flow.py --flow_mode 'deflow' --data_dir /home/kin/data/av2/preprocess/sensor/mini
111111
```
112112

113113
Note: ego_motion already compensated, so the visualization is more clear.

conf/eval.yaml

+10-12
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11

2-
defaults:
3-
- hydra: default
4-
- model: deflow
5-
6-
slurm_id: 00000
7-
8-
wandb_mode: offline # [offline, disabled, online]
92
dataset_path: /home/kin/data/av2/preprocess/sensor
10-
11-
output: ${model.name}-${slurm_id}
12-
13-
checkpoint: /home/kin/model.ckpt
3+
checkpoint: /home/kin/model_zoo/deflow.ckpt
144
av2_mode: val # [val, test]
155
save_res: False # [True, False]
166

177
# no need to change
8+
slurm_id: 00000
9+
output: ${model.name}-${slurm_id}
1810
gpus: 1
19-
seed: 42069
11+
seed: 42069
12+
eval_only: True
13+
wandb_mode: offline # [offline, disabled, online]
14+
15+
defaults:
16+
- hydra: default
17+
- model: deflow

conf/vis.yaml

+9-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
dataset_path: /home/kin/data/av2/preprocess/sensor/mini
2+
checkpoint: /home/kin/model_zoo/deflow.ckpt
3+
res_name: # if None will directly be the `model_name.ckpt` in checkpoint path
4+
15

6+
# no need to change
27
defaults:
38
- hydra: default
49
- model: deflow
5-
6-
dataset_path: /home/kin/data/av2/preprocess/sensor/mini
7-
checkpoint: /home/kin/model.ckpt
8-
9-
# no need to change
10-
seed: 42069
10+
seed: 42069
11+
gpus: 1
12+
slurm_id: 00000
13+
output: ${model.name}-${slurm_id}

scripts/network/loss_func.py

+2-70
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
# Copyright (C) 2023-now, RPL, KTH Royal Institute of Technology
44
# Author: Qingwen Zhang (https://kin-zhang.github.io/)
55
#
6-
# This work is licensed under the terms of the MIT license.
7-
# For a copy, see <https://opensource.org/licenses/MIT>.
8-
6+
# Description: Define the loss function for training.
97
"""
108
import torch
119

@@ -64,70 +62,4 @@ def ff3dLoss(res_dict):
6462
is_foreground_class = (classes > 0) # 0 is background, ref: FOREGROUND_BACKGROUND_BREAKDOWN
6563
background_scalar = is_foreground_class.float() * 0.9 + 0.1
6664
error = error * background_scalar
67-
return error.mean()
68-
69-
# ==========================> From AV2.0 Eval Official Scripts.
70-
from typing import Dict, Final
71-
import os, sys
72-
BASE_DIR = os.path.abspath(os.path.join( os.path.dirname( __file__ ), '../..' ))
73-
sys.path.append(BASE_DIR)
74-
from scripts.utils.av2_eval import compute_metrics, FOREGROUND_BACKGROUND_BREAKDOWN
75-
import numpy as np
76-
77-
CLOSE_DISTANCE_THRESHOLD: Final = 35.0
78-
EPS: Final = 1e-6
79-
def compute_epe(res_dict, indices, eps=1e-8):
80-
epe_sum = 0
81-
count_sum = 0
82-
for index in indices:
83-
count = res_dict['Count'][index]
84-
if count != 0:
85-
epe_sum += res_dict['EPE'][index] * count
86-
count_sum += count
87-
return epe_sum / (count_sum + eps) if count_sum != 0 else 0.0
88-
89-
# after ground mask already, not origin N, 3 but without ground points
90-
def evaluate_leaderboard(est_flow, rigid_flow, pc0, gt_flow, is_valid, pts_ids):
91-
92-
# gt_is_dynamic = (gt_flow - rigid_flow).norm(dim=1, p=2) > 0.05
93-
gt_is_dynamic = torch.linalg.vector_norm(gt_flow - rigid_flow, dim=-1) >= 0.05
94-
mask_ = ~est_flow.isnan().any(dim=1) & ~rigid_flow.isnan().any(dim=1) & ~pc0[:, :3].isnan().any(dim=1) & ~gt_flow.isnan().any(dim=1)
95-
mask_no_nan = mask_ & ~gt_is_dynamic.isnan() & ~is_valid.isnan() & ~pts_ids.isnan()
96-
est_flow = est_flow[mask_no_nan, :]
97-
rigid_flow = rigid_flow[mask_no_nan, :]
98-
pc0 = pc0[mask_no_nan, :]
99-
gt_flow = gt_flow[mask_no_nan, :]
100-
gt_is_dynamic = gt_is_dynamic[mask_no_nan]
101-
is_valid = is_valid[mask_no_nan]
102-
pts_ids = pts_ids[mask_no_nan]
103-
104-
est_is_dynamic = torch.linalg.vector_norm(est_flow - rigid_flow, dim=-1) >= 0.05
105-
is_close = torch.all(torch.abs(pc0[:, :2]) <= CLOSE_DISTANCE_THRESHOLD, dim=1)
106-
res_dict = compute_metrics(
107-
est_flow.detach().cpu().numpy().astype(float),
108-
est_is_dynamic.detach().cpu().numpy().astype(bool),
109-
gt_flow.detach().cpu().numpy().astype(float),
110-
pts_ids.detach().cpu().numpy().astype(np.uint8),
111-
gt_is_dynamic.detach().cpu().numpy().astype(bool),
112-
is_close.detach().cpu().numpy().astype(bool),
113-
is_valid.detach().cpu().numpy().astype(bool),
114-
FOREGROUND_BACKGROUND_BREAKDOWN,
115-
)
116-
117-
# reference: eval.py L503
118-
# we need Dynamic IoU and EPE 3-Way Average to calculate loss!
119-
# weighted: (x[metric_type.value] * x.Count).sum() / total
120-
# 'Class': ['Background', 'Background', 'Background', 'Background', 'Foreground', 'Foreground', 'Foreground', 'Foreground']
121-
# 'Motion': ['Dynamic', 'Dynamic', 'Static', 'Static', 'Dynamic', 'Dynamic', 'Static', 'Static']
122-
# 'Distance': ['Close', 'Far', 'Close', 'Far', 'Close', 'Far', 'Close', 'Far']
123-
124-
EPE_Background_Static = compute_epe(res_dict, [2, 3])
125-
EPE_Dynamic = compute_epe(res_dict, [4, 5])
126-
EPE_Foreground_Static = compute_epe(res_dict, [6, 7])
127-
128-
Dynamic_IoU = sum(res_dict['TP']) / (sum(res_dict['TP']) + sum(res_dict['FP']) + sum(res_dict['FN'])+EPS)
129-
# EPE_Dynamic is nan?
130-
if np.isnan(EPE_Dynamic) or np.isnan(Dynamic_IoU) or np.isnan(EPE_Background_Static) or np.isnan(EPE_Foreground_Static):
131-
print(res_dict)
132-
133-
return EPE_Background_Static, EPE_Dynamic, EPE_Foreground_Static, Dynamic_IoU
65+
return error.mean()

0 commit comments

Comments
 (0)