Skip to content

Commit 650383b

Browse files
authored
Merge DeltaFlow into codebase (#21)
* cuda(histlib): cuda library from icp-flow project. * docs: update README with icp-flow in the official implementation. * conf(optimization-based): update all config files. * todo: update model file, double check with yancong and Qingwen confirm that: icp-flow results can be reproduced and tested. * docs: fix small typo, and starting updating model file. * feat(icp): core icp files, tested successfully. * feat(deflowpp): update deflowpp model. * hotfix(ssf): bug fixes in seflow+ssf as ssf concat two pc and forget to - index. * feat(autolabel): update more autolabel through himo paper. * add data with lidar_id and lidar_dt * add flow_instances for afterward easy deltaflow update. * feat(seflowpp): the full seflowpp process and train scripts. * tested with demo good, need double check the results on av2 and update the training time & weight link also. * fix(trainer): add seflowpp into trainer for folder name. * data(zod): update zod extraction scripts. * it could be a good reference for users to extract other data into h5 files etc. * !feat(lr): update optimizer to new structure. - update from DeltaFlow. - align some format with copilot comments. * update other submodule repo to align the lr changed. * dcos(slurm): update slurm script, for reader to easy check how is the trainining setup. * fix(env): fix some potiential env issue later * add some notes * fix(av2): instance label typo. * fix(process): update key name in new version for seflow-variant process. * hotfix(eval): updating num_frames into eval. * hotfix(eval/test): for history frames, we update keys' name and it need rm ground mask also. * small fix on ssl_label to None if under supervise training. * feat(aug): merge data aug strategy from DeltaFlow project. * docs(README): update readme. align with paper. * docs(README): update arxiv link * feat(deltaflow): update deltaflow model file. * checked with trained weight. * conf: update deltaflow conf files update README to show the progress. * hotfix(eval): not assert but return if no gt class pt etc. to avoid killed during eval. * loss(deltaflow): add deltaflow loss. * docs(README): update readme. * revert to OpenSceneFlow readme for the codebase. * docs: update README. * update av2_mode to data_mode. * revert back for zod process file * runner metric is good in last version as it's range_bucket have different meaning. * docs: update for diff opt methods. * hotfix(dataset): fix eval_mask in dataset. * we only evaluated points on non-ground point. * no need print ssf_metrics since our train range is out of evaluation. * docs(bib): add deltaflow bib back. * docs(readme): update new bib file. * feat(log): save the evaluation log and add inlineTee for output file. * for easy sharing score afterward etc. * update docs about upcoming works also. * style: clean up the developed code previously. * add readh5 and create_eval_pkl * docs(bib): update bib. * docs(data): update README demo data link.
1 parent 88f49bc commit 650383b

25 files changed

+1042
-261
lines changed

README.md

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111
OpenSceneFlow is a codebase for point cloud scene flow estimation.
1212
It is also an official implementation of the following papers (sorted by the time of publication):
1313

14+
<!-- - **TeFlow: An Efficient Multi-frame Scene Flow Estimation Method**
15+
*Qingwen Zhang, Chenhan Jiang, Xiaomeng Zhu, Yunqi Miao, Yushan Zhang, Olov Andersson, Patric Jensfelt*
16+
Under Review
17+
[ Strategy ] [ Self-Supervised ] - [ [OpenReview](https://openreview.net/forum?id=h70FLgnIAw) ] [ [Project](https://github.com/Kin-Zhang/TeFlow) ]&rarr; [here](#teflow) -->
18+
1419
- **DeltaFlow: An Efficient Multi-frame Scene Flow Estimation Method**
1520
*Qingwen Zhang, Xiaomeng Zhu, Yushan Zhang, Yixi Cai, Olov Andersson, Patric Jensfelt*
1621
Conference on Neural Information Processing Systems (**NeurIPS**) 2025 - Spotlight
17-
[ Backbone ] [ Supervised ] - [ [arXiv](https://arxiv.org/abs/2508.17054) ] [ [Project](https://github.com/Kin-Zhang/DeltaFlow) ]
22+
[ Backbone ] [ Supervised ] - [ [arXiv](https://arxiv.org/abs/2508.17054) ] [ [Project](https://github.com/Kin-Zhang/DeltaFlow) ]&rarr; [here](#deltaflow)
1823

1924
- **HiMo: High-Speed Objects Motion Compensation in Point Clouds** (SeFlow++)
2025
*Qingwen Zhang, Ajinkya Khoche, Yi Yang, Li Ling, Sina Sharif Mansouri, Olov Andersson, Patric Jensfelt*
@@ -103,11 +108,11 @@ If you prefer to build the Docker image by yourself, Check [build-docker-image](
103108

104109
## 1. Data Preparation
105110

106-
Refer to [dataprocess/README.md](dataprocess/README.md) for dataset download instructions. Currently, we support **Argoverse 2**, **Waymo**, **nuScenes**, [**MAN-TruckScene**](https://github.com/TUMFTM/truckscenes-devkit), [**ZOD**](https://github.com/zenseact/zod) and **custom datasets** (more datasets will be added in the future).
111+
Refer to [dataprocess/README.md](dataprocess/README.md) for dataset download instructions. Currently, we support [**Argoverse 2**](https://www.argoverse.org/av2.html), [**Waymo**](https://waymo.com/open/), [**nuScenes**](https://www.nuscenes.org/), [**MAN-TruckScene**](https://github.com/TUMFTM/truckscenes-devkit), [**ZOD**](https://github.com/zenseact/zod) and **custom datasets** (more datasets will be added in the future).
107112

108113
After downloading, convert the raw data to `.h5` format for easy training, evaluation, and visualization. Follow the steps in [dataprocess/README.md#process](dataprocess/README.md#process).
109114

110-
For a quick start, use our **mini processed dataset**, which includes one scene in `train` and `val`. It is pre-converted to `.h5` format with label data ([HuggingFace](https://huggingface.co/kin-zhang/OpenSceneFlow/blob/main/demo_data.zip)/[Zenodo](https://zenodo.org/records/13744999/files/demo_data.zip)).
115+
For a quick start, use our **mini processed dataset**, which includes one scene in `train` and `val`. It is pre-converted to `.h5` format with label data ([HuggingFace](https://huggingface.co/kin-zhang/OpenSceneFlow/resolve/main/demo-data-v2.zip)).
111116

112117

113118
```bash
@@ -125,14 +130,26 @@ Some tips before running the code:
125130
* If you want to use [wandb](wandb.ai), replace all `entity="kth-rpl",` to your own entity otherwise tensorboard will be used locally.
126131
* Set correct data path by passing the config, e.g. `train_data=/home/kin/data/av2/h5py/demo/train val_data=/home/kin/data/av2/h5py/demo/val`.
127132

128-
And free yourself from trainning, you can download the pretrained weight from [HuggingFace](https://huggingface.co/kin-zhang/OpenSceneFlow) and we provided the detail `wget` command in each model section. For optimization-based method, it's train-free so you can directly run with [3. Evaluation](#3-evaluation) (check more in the evaluation section).
133+
And free yourself from trainning, you can download the pretrained weight from [**HuggingFace - OpenSceneFlow**](https://huggingface.co/kin-zhang/OpenSceneFlow) and we provided the detail `wget` command in each model section. For optimization-based method, it's train-free so you can directly run with [3. Evaluation](#3-evaluation) (check more in the evaluation section).
129134

130135
```bash
131136
conda activate opensf
132137
```
133138

134139
### Supervised Training
135140

141+
#### DeltaFlow
142+
143+
Train DeltaFlow with the leaderboard submit config. [Runtime: Around 18 hours in 10x RTX 3080 GPUs.]
144+
145+
```bash
146+
# total bz then it's 10x2 under above training setup.
147+
python train.py model=deltaFlow optimizer.lr=2e-3 epochs=20 batch_size=2 num_frames=5 loss_fn=deflowLoss train_aug=True "voxel_size=[0.15, 0.15, 0.15]" "point_cloud_range=[-38.4, -38.4, -3.2, 38.4, 38.4, 3.2]" +optimizer.scheduler.name=WarmupCosLR +optimizer.scheduler.max_lr=2e-3 +optimizer.scheduler.total_steps=20000
148+
149+
# Pretrained weight can be downloaded through (av2), check all other datasets in the same folder.
150+
wget https://huggingface.co/kin-zhang/OpenSceneFlow/resolve/main/deltaflow/deltaflow-av2.ckpt
151+
```
152+
136153
#### Flow4D
137154

138155
Train Flow4D with the leaderboard submit config. [Runtime: Around 18 hours in 4x RTX 3090 GPUs.]
@@ -181,7 +198,7 @@ wget https://huggingface.co/kin-zhang/OpenSceneFlow/resolve/main/deflow_best.ckp
181198
### Feed-Forward Self-Supervised Model Training
182199

183200
Train Feed-forward SSL methods (e.g. SeFlow/SeFlow++/VoteFlow etc), we needed to:
184-
1) process auto-label process.
201+
1) process auto-label process for training. Check [dataprocess/README.md#self-supervised-process](dataprocess/README.md#self-supervised-process) for more details. We provide these inside the demo dataset already.
185202
2) specify the loss function, we set the config here for our best model in the leaderboard.
186203

187204
#### SeFlow
@@ -240,7 +257,8 @@ python save.py model=fastnsf
240257

241258
## 3. Evaluation
242259

243-
You can view Wandb dashboard for the training and evaluation results or upload result to online leaderboard.
260+
You can view Wandb dashboard for the training and evaluation results or upload result to online leaderboard.
261+
<!-- Three-way EPE and Dynamic Bucket-normalized are evaluated within a 70x70m range (followed Argoverse 2 online leaderboard). No ground points are considered in the evaluation. -->
244262

245263
Since in training, we save all hyper-parameters and model checkpoints, the only thing you need to do is to specify the checkpoint path. Remember to set the data path correctly also.
246264

@@ -249,7 +267,7 @@ Since in training, we save all hyper-parameters and model checkpoints, the only
249267
python eval.py checkpoint=/home/kin/seflow_best.ckpt data_mode=val
250268

251269
# (optimization-based): it might need take really long time, maybe tmux for run it.
252-
python eval.py model=nsfp
270+
python eval.py model=nsfp +master_port=12344 # change diff port if you want to have multiple runners.
253271

254272
# it will output the av2_submit.zip or av2_submit_v2.zip for you to submit to leaderboard
255273
python eval.py checkpoint=/home/kin/seflow_best.ckpt data_mode=test leaderboard_version=1
@@ -326,6 +344,7 @@ https://github.com/user-attachments/assets/07e8d430-a867-42b7-900a-11755949de21
326344
## Cite Us
327345

328346
[*OpenSceneFlow*](https://github.com/KTH-RPL/OpenSceneFlow) is originally designed by [Qingwen Zhang](https://kin-zhang.github.io/) from DeFlow and SeFlow.
347+
It is actively maintained and developed by the community (ref. below works).
329348
If you find it useful, please cite our works:
330349

331350
```bibtex
@@ -347,16 +366,26 @@ If you find it useful, please cite our works:
347366
doi={10.1109/ICRA57147.2024.10610278}
348367
}
349368
@article{zhang2025himo,
350-
title={HiMo: High-Speed Objects Motion Compensation in Point Clouds},
351-
author={Zhang, Qingwen and Khoche, Ajinkya and Yang, Yi and Ling, Li and Sina, Sharif Mansouri and Andersson, Olov and Jensfelt, Patric},
352-
year={2025},
353-
journal={arXiv preprint arXiv:2503.00803},
369+
title={{HiMo}: High-Speed Objects Motion Compensation in Point Cloud},
370+
author={Zhang, Qingwen and Khoche, Ajinkya and Yang, Yi and Ling, Li and Mansouri, Sina Sharif and Andersson, Olov and Jensfelt, Patric},
371+
journal={IEEE Transactions on Robotics},
372+
year={2025},
373+
volume={41},
374+
pages={5896-5911},
375+
doi={10.1109/TRO.2025.3619042}
376+
}
377+
@inproceedings{zhang2025deltaflow,
378+
title={{DeltaFlow}: An Efficient Multi-frame Scene Flow Estimation Method},
379+
author={Zhang, Qingwen and Zhu, Xiaomeng and Zhang, Yushan and Cai, Yixi and Andersson, Olov and Jensfelt, Patric},
380+
booktitle={The Thirty-ninth Annual Conference on Neural Information Processing Systems},
381+
year={2025},
382+
url={https://openreview.net/forum?id=T9qNDtvAJX}
354383
}
355-
@article{zhang2025deltaflow,
356-
title={{DeltaFlow}: An Efficient Multi-frame Scene Flow Estimation Method},
357-
author={Zhang, Qingwen and Zhu, Xiaomeng and Zhang, Yushan and Cai, Yixi and Andersson, Olov and Jensfelt, Patric},
358-
year={2025},
359-
journal={arXiv preprint arXiv:2508.17054},
384+
@misc{zhang2025teflow,
385+
title={{TeFlow}: Enabling Multi-frame Supervision for Feed-forward Scene Flow Estimation},
386+
author={Zhang, Qingwen and Jiang, Chenhan and Zhu, Xiaomeng and Miao, Yunqi and Zhang, Yushan and Andersson, Olov and Jensfelt, Patric},
387+
year={2025},
388+
url={https://openreview.net/forum?id=h70FLgnIAw}
360389
}
361390
```
362391

@@ -373,13 +402,14 @@ And our excellent collaborators works contributed to this codebase also:
373402
pages={3462-3469},
374403
doi={10.1109/LRA.2025.3542327}
375404
}
376-
@article{khoche2025ssf,
377-
title={SSF: Sparse Long-Range Scene Flow for Autonomous Driving},
405+
@inproceedings{khoche2025ssf,
406+
title={{SSF}: Sparse Long-Range Scene Flow for Autonomous Driving},
378407
author={Khoche, Ajinkya and Zhang, Qingwen and Sanchez, Laura Pereira and Asefaw, Aron and Mansouri, Sina Sharif and Jensfelt, Patric},
379-
journal={arXiv preprint arXiv:2501.17821},
380-
year={2025}
408+
booktitle={2025 IEEE International Conference on Robotics and Automation (ICRA)},
409+
year={2025},
410+
pages={6394-6400},
411+
doi={10.1109/ICRA55743.2025.11128770}
381412
}
382-
383413
@inproceedings{lin2025voteflow,
384414
title={VoteFlow: Enforcing Local Rigidity in Self-Supervised Scene Flow},
385415
author={Lin, Yancong and Wang, Shiming and Nan, Liangliang and Kooij, Julian and Caesar, Holger},

assets/slurm/dufolabel_sbatch.py

Lines changed: 0 additions & 58 deletions
This file was deleted.

assets/slurm/ssl-process.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ cd /proj/berzelius-2023-154/users/x_qinzh/OpenSceneFlow
1818

1919

2020
# data directory containing the extracted h5py files
21-
DATA_DIR="/proj/berzelius-2023-364/data/truckscenes/h5py/val"
21+
DATA_DIR="/proj/berzelius-2023-364/data/av2/h5py/sensor/train"
2222

2323
TOTAL_SCENES=$(ls ${DATA_DIR}/*.h5 | wc -l)
2424
# Process every n-th frame into DUFOMap, no need to change at least for now.

conf/config.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ wandb_mode: disabled # [offline, disabled, online]
99
wandb_project_name: seflow
1010

1111
train_data: /home/kin/data/av2/h5py/demo/train
12+
train_aug: False # involved by deltaflow
1213
val_data: /home/kin/data/av2/h5py/demo/val
1314

1415
output: ${model.name}-${slurm_id}
@@ -28,8 +29,8 @@ gradient_clip_val: 5.0
2829
# optimizer ==> Adam
2930
optimizer:
3031
name: Adam # [Adam, AdamW]
31-
lr: 1e-4
32-
loss_fn: seflowLoss # choices: [ff3dLoss, zeroflowLoss, deflowLoss, seflowLoss]
32+
lr: 2e-4
33+
loss_fn: deflowLoss # choices: [ff3dLoss, zeroflowLoss, deflowLoss, seflowLoss]
3334
# add_seloss: {chamfer_dis: 1.0, static_flow_loss: 1.0, dynamic_chamfer_dis: 1.0, cluster_based_pc0pc1: 1.0}
3435
# ssl_label:
3536

conf/eval.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
dataset_path: /home/kin/data/av2/h5py/sensor
3-
checkpoint: /home/kin/model_zoo/deflow.ckpt
3+
checkpoint: /home/kin/data/model_zoo/deltaflow_public/deltaflow-av2.ckpt
44
data_mode: val # [val, test]
55
save_res: False # [True, False]
66

@@ -15,7 +15,7 @@ output: ${model.name}-${slurm_id}
1515
gpus: 1
1616
seed: 42069
1717
eval_only: True
18-
wandb_mode: offline # [offline, disabled, online]
18+
wandb_mode: disabled # [offline, disabled, online]
1919
defaults:
2020
- hydra: default
2121
- model: deflow

conf/model/deltaflow.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: deltaflow
2+
3+
target:
4+
_target_: src.models.DeltaFlow
5+
voxel_size: ${voxel_size}
6+
point_cloud_range: ${point_cloud_range}
7+
num_frames: ${num_frames}
8+
planes: [16, 32, 64, 128, 256, 256, 128, 64, 32, 16] # 1st is #input channel, last is #output channel
9+
# num_layer: [1, 1, 1, 1, 1, 1, 1, 1, 1] # the smallest model
10+
num_layer: [2, 2, 2, 2, 2, 2, 2, 2, 2] # MinkUnet 18
11+
# num_layer: [2, 3, 4, 6, 2, 2, 2, 2, 2] # MinkUnet 34
12+
decay_factor: 0.4
13+
decoder_option: default # choices: [default, deflow]
14+
15+
val_monitor: val/Dynamic/Mean

dataprocess/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,6 @@ Process train data for self-supervised learning. Only training data needs this s
247247
```bash
248248
python process.py --data_dir /home/kin/data/av2/h5py/sensor/train --scene_range 0,701
249249
```
250+
251+
As some users must have multi-nodes for running, here I provide an example SLURM script to run the data process in parallel.
252+
Check [assets/slurm/ssl-process.sh](../assets/slurm/ssl-process.sh) for more details.

eval.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@
1313
import torch
1414
from torch.utils.data import DataLoader
1515
import lightning.pytorch as pl
16-
from lightning.pytorch.loggers import WandbLogger
16+
from lightning.pytorch.loggers import TensorBoardLogger, WandbLogger
1717
from omegaconf import DictConfig
1818
import hydra, wandb, os, sys
1919
from hydra.core.hydra_config import HydraConfig
2020
from src.dataset import HDF5Dataset
2121
from src.trainer import ModelWrapper
22+
from src.utils import InlineTee
2223

2324
def precheck_cfg_valid(cfg):
2425
if os.path.exists(cfg.dataset_path + f"/{cfg.data_mode}") is False:
@@ -36,8 +37,8 @@ def main(cfg):
3637

3738
if 'iter_only' in cfg.model and cfg.model.iter_only:
3839
from src.runner import launch_runner
39-
print(f"---LOG[eval]: Run optmization-based method: {cfg.model.name}")
40-
launch_runner(cfg, cfg.data_mode)
40+
launch_runner(cfg, cfg.data_mode, output_dir)
41+
print(f"---LOG[eval]: Finished optimization-based evaluation. Logging saved to {output_dir}/output.log")
4142
return
4243

4344
if not os.path.exists(cfg.checkpoint):
@@ -47,27 +48,39 @@ def main(cfg):
4748
torch_load_ckpt = torch.load(cfg.checkpoint)
4849
checkpoint_params = DictConfig(torch_load_ckpt["hyper_parameters"])
4950
cfg.output = checkpoint_params.cfg.output + f"-e{torch_load_ckpt['epoch']}-{cfg.data_mode}-v{cfg.leaderboard_version}"
51+
# replace output_dir ${old_output_dir} with ${output_dir}
52+
output_dir = output_dir.replace(HydraConfig.get().runtime.output_dir.split('/')[-2], checkpoint_params.cfg.output.split('/')[-1])
5053
cfg.model.update(checkpoint_params.cfg.model)
5154
cfg.num_frames = cfg.model.target.get('num_frames', checkpoint_params.cfg.get('num_frames', cfg.get('num_frames', 2)))
5255

5356
mymodel = ModelWrapper.load_from_checkpoint(cfg.checkpoint, cfg=cfg, eval=True)
54-
print(f"\n---LOG[eval]: Loaded model from {cfg.checkpoint}. The backbone network is {checkpoint_params.cfg.model.name}.\n")
57+
os.makedirs(output_dir, exist_ok=True)
58+
sys.stdout = InlineTee(f"{output_dir}/output.log")
59+
print(f"---LOG[eval]: Loaded model from {cfg.checkpoint}. The backbone network is {checkpoint_params.cfg.model.name}.")
60+
print(f"---LOG[eval]: Evaluation data: {cfg.dataset_path}/{cfg.data_mode} set.\n")
5561

56-
wandb_logger = WandbLogger(save_dir=output_dir,
57-
entity="kth-rpl",
58-
project=f"deflow-eval",
59-
name=f"{cfg.output}",
60-
offline=(cfg.wandb_mode == "offline"))
62+
if cfg.wandb_mode != "disabled":
63+
logger = WandbLogger(save_dir=output_dir,
64+
entity="kth-rpl",
65+
project=f"opensf-eval",
66+
name=f"{cfg.output}",
67+
offline=(cfg.wandb_mode == "offline"))
68+
logger.watch(mymodel, log_graph=False)
69+
else:
70+
# check local tensorboard logging: tensorboard --logdir logs/jobs/{log folder}
71+
logger = TensorBoardLogger(save_dir=output_dir, name="logs")
6172

62-
trainer = pl.Trainer(logger=wandb_logger, devices=1)
73+
trainer = pl.Trainer(logger=logger, devices=1)
6374
# NOTE(Qingwen): search & check: def eval_only_step_(self, batch, res_dict)
6475
trainer.validate(model = mymodel, \
6576
dataloaders = DataLoader( \
6677
HDF5Dataset(cfg.dataset_path + f"/{cfg.data_mode}", \
6778
n_frames=cfg.num_frames, \
6879
eval=True, leaderboard_version=cfg.leaderboard_version), \
6980
batch_size=1, shuffle=False))
70-
wandb.finish()
81+
if cfg.wandb_mode != "disabled":
82+
wandb.finish()
83+
print(f"---LOG[eval]: Finished feed-forward evaluation. Logging saved to {output_dir}/output.log")
7184

7285
if __name__ == "__main__":
7386
main()

process.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,6 @@ def main(
186186
if not os.path.exists(gm_config_path) and run_gm:
187187
raise FileNotFoundError(f"Ground segmentation config file not found: {gm_config_path}. Please check folder")
188188

189-
190189
data_path = Path(data_dir)
191190
dataset = HDF5Data(data_path) # single frame reading.
192191
all_scene_ids = list(dataset.scene_id_bounds.keys())

0 commit comments

Comments
 (0)