Video-depth PointDiT-B, update 32500, EMA2
Browse files
video-depth-pointdit/README.md
CHANGED
|
@@ -23,8 +23,8 @@ are not expected to close that gap.
|
|
| 23 |
| `rows/*.jsonl` | the recorded evaluation rows (raw and EMA2 weights; video and single-frame calls) |
|
| 24 |
| `manifest.json`, `manifest.sha256` | file names, sizes, sha256 (`manifest.sha256` is `sha256sum -c` input), code commit, update count |
|
| 25 |
| `infer_video_depth.py` | depth for your own video or frames: npy, colour-mapped PNGs, MP4 (see "Run inference on your own video") |
|
| 26 |
-
| `reproduce_evaluation.sh` | the
|
| 27 |
-
| `load_point.py` | builds the model through the repository's builder and loads the EMA weights |
|
| 28 |
|
| 29 |
There is no optimizer state and no raw (non-EMA) weight file here. The evaluator needs only the EMA2 artifact.
|
| 30 |
The frozen DINOv3 encoder is not included (see Licence).
|
|
@@ -53,41 +53,91 @@ The frozen DINOv3 encoder is not included (see Licence).
|
|
| 53 |
prediction), `--base-steps 1`, on the logit-normal quantile grid the model was trained with (its native sampler is
|
| 54 |
four steps, noise scale 2.0).
|
| 55 |
|
| 56 |
-
##
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
```bash
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
FOLDER=<this folder> # the downloaded video-depth-pointdit/
|
| 71 |
-
python $FOLDER/load_point.py $FOLDER # builds the model, loads EMA2 (CPU, about 15 s)
|
| 72 |
-
bash $FOLDER/reproduce_evaluation.sh $FOLDER $PWD/out # one GPU; checks manifest.sha256 first
|
| 73 |
```
|
| 74 |
|
| 75 |
-
`
|
| 76 |
-
the
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
## Run inference on your own video
|
| 79 |
|
| 80 |
`infer_video_depth.py` takes a video file or a folder of frames and writes per-frame depth. It builds the model through
|
| 81 |
the repository's builder (`build_point_model`), loads the EMA2 weights, computes the frozen DINOv3 ViT-B/16 features of the
|
| 82 |
frames and samples with the repository's sampler exactly as the evaluation does: one Euler step from Gaussian noise,
|
| 83 |
-
the contracted depth state capped at 1.984375, bf16 autocast. Run it from a clone of the repository
|
| 84 |
-
|
| 85 |
|
| 86 |
```bash
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
python $FOLDER/infer_video_depth.py $FOLDER --input
|
| 90 |
-
python $FOLDER/infer_video_depth.py $FOLDER --input frames_dir/ --out out/ --max-frames 25 --stride 2
|
| 91 |
```
|
| 92 |
|
| 93 |
- **Frames:** the first `--max-frames` (default 21, at most 25) frames at `--stride`, in one call. Each is resized, whole
|
|
@@ -106,17 +156,23 @@ python $FOLDER/infer_video_depth.py $FOLDER --input frames_dir/ --out out/ --max
|
|
| 106 |
known scale, or fit one scale and shift per clip against a reference, as the benchmark does.
|
| 107 |
- **Seed.** The sampler starts from Gaussian noise: `--seed` fixes it. `--seed-key 0:<dataset>:<sequence>` uses the
|
| 108 |
benchmark's noise key, which reproduces a benchmark row's call exactly.
|
| 109 |
-
- **Weights it needs:** the DINOv3 ViT-B/16 file
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
the
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
## Recorded results
|
| 122 |
|
|
@@ -168,6 +224,4 @@ is high (0.84 and 0.97 on those two). KITTI's near third (closer than about 10 m
|
|
| 168 |
- DINOv3 (Meta) is under the DINOv3 licence and is NOT redistributed here. Request it at
|
| 169 |
`https://ai.meta.com/resources/models-and-libraries/dinov3-downloads/`. The model needs the ViT-B/16 LVD-1689M
|
| 170 |
weights (`dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth`, sha256
|
| 171 |
-
`73cec8be7427c8655ceced13ce62f6e20a1fa90d1b4d4a550df17a1144081a7c`).
|
| 172 |
-
`/vgg/yushi/Repo/baselines/dinov3/weights/dinov3_vitb16.pth` (the config names a symlink to it under
|
| 173 |
-
`/scratch/shared/engs2907/pointdit_official/pretrained/dinov3/`).
|
|
|
|
| 23 |
| `rows/*.jsonl` | the recorded evaluation rows (raw and EMA2 weights; video and single-frame calls) |
|
| 24 |
| `manifest.json`, `manifest.sha256` | file names, sizes, sha256 (`manifest.sha256` is `sha256sum -c` input), code commit, update count |
|
| 25 |
| `infer_video_depth.py` | depth for your own video or frames: npy, colour-mapped PNGs, MP4 (see "Run inference on your own video") |
|
| 26 |
+
| `reproduce_evaluation.sh` | the evaluation commands, taking every external path by flag (see Quick start) |
|
| 27 |
+
| `load_point.py` | builds the model through the repository's builder and loads the EMA weights (reads only this folder) |
|
| 28 |
|
| 29 |
There is no optimizer state and no raw (non-EMA) weight file here. The evaluator needs only the EMA2 artifact.
|
| 30 |
The frozen DINOv3 encoder is not included (see Licence).
|
|
|
|
| 53 |
prediction), `--base-steps 1`, on the logit-normal quantile grid the model was trained with (its native sampler is
|
| 54 |
four steps, noise scale 2.0).
|
| 55 |
|
| 56 |
+
## Quick start without Civo
|
| 57 |
|
| 58 |
+
Everything below uses only this folder, the project repository on GitHub, two public checkouts and files you request or
|
| 59 |
+
download yourself. No path of the Civo cluster is on any command line.
|
| 60 |
+
|
| 61 |
+
**1. Code.** `git clone git@github.com:NIRVANALAN/vgg_forecast_4d.git` (you need access to the repository) and check out
|
| 62 |
+
`main`. Loading and inference need commit `2310eec5` or later. The evaluation flag `--data-root` (used below) is on the
|
| 63 |
+
branch `docs/video-depth-pointdit-off-civo` until its pull request is merged; check that branch out for the evaluation.
|
| 64 |
+
Run every command from the clone root with `export PYTHONPATH=$PWD/src`.
|
| 65 |
+
|
| 66 |
+
**2. Environment.** The scripts were run in Python 3.12.13 with torch 2.9.0+cu130 (CUDA 13.0), numpy 2.4.6, omegaconf
|
| 67 |
+
2.3.1, hydra-core 1.3.4, einops 0.8.2, safetensors 0.8.0, opencv-python 4.11.0.86, imageio 2.37.4 with imageio-ffmpeg
|
| 68 |
+
0.6.0, scipy 1.18.0, pillow 12.3.0, matplotlib 3.11.1, accelerate 1.14.0, timm 1.0.28, transformers 5.14.1. The recorded
|
| 69 |
+
rows used FlashAttention 2.8.3 (`fa2`); the scripts default to PyTorch's `sdpa` attention, which needs no extra
|
| 70 |
+
package (pass `--attention-backend fa2` where it is offered if you installed flash-attn). A GPU is needed for evaluation
|
| 71 |
+
and recommended for inference; loading runs on a CPU.
|
| 72 |
+
|
| 73 |
+
**3. This folder.** `hf download yslan/dev-pointdit-video-depth --include "video-depth-pointdit/*" --local-dir <dir>`; the
|
| 74 |
+
folder is `<dir>/video-depth-pointdit`, called `$FOLDER` below. `cd $FOLDER && sha256sum -c manifest.sha256` checks it.
|
| 75 |
+
|
| 76 |
+
**4. DINOv3 ViT-B/16 (not included).** Request it at `https://ai.meta.com/resources/models-and-libraries/dinov3-downloads/`
|
| 77 |
+
(Meta's licence). The file is `dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth`, sha256
|
| 78 |
+
`73cec8be7427c8655ceced13ce62f6e20a1fa90d1b4d4a550df17a1144081a7c` (the scripts refuse another file). The code is
|
| 79 |
+
`git clone https://github.com/facebookresearch/dinov3` (tested at `6876159a11b4df116f30f667f8c9888617df0751`). Both go
|
| 80 |
+
to the scripts by flag: `--dino-weights <file> --dinov3-repo <checkout>`.
|
| 81 |
+
|
| 82 |
+
**5. Load (CPU, about 15 s).**
|
| 83 |
+
|
| 84 |
+
```bash
|
| 85 |
+
python $FOLDER/load_point.py $FOLDER
|
| 86 |
+
# temporal_pointdit window_valid_mean_depth 32500 0.9996 140204928
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
**6. Inference on your video (section below).**
|
| 90 |
+
|
| 91 |
+
```bash
|
| 92 |
+
python $FOLDER/infer_video_depth.py $FOLDER --input clip.mp4 --out out/ \
|
| 93 |
+
--dino-weights <dinov3 file> --dinov3-repo <dinov3 checkout>
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
**7. Evaluation (one GPU).** Needs the benchmark data in the layout of the repository's evaluator
|
| 97 |
+
(`monocular_depth.cohort_pairs`; the layout and the 21 frames per sequence are written out in the repository's
|
| 98 |
+
`doc/handoff/video_depth_and_camera_pose_evaluation_for_external_models.md`, section 3.1) and a checkout of
|
| 99 |
+
`https://github.com/NIRVANALAN/STream3R` at `7bdca8cf7ec206ff8b08c0941ad8286d72087d4f`, whose depth readers the evaluator
|
| 100 |
+
uses (`STREAM3R_ROOT`):
|
| 101 |
|
| 102 |
```bash
|
| 103 |
+
export STREAM3R_ROOT=<STream3R checkout>
|
| 104 |
+
bash $FOLDER/reproduce_evaluation.sh $FOLDER out/ --dino-weights <dinov3 file> --dinov3-repo <dinov3 checkout> \
|
| 105 |
+
--data-root <dir holding sintel/ bonn/ kitti/> [--datasets "sintel bonn kitti"]
|
|
|
|
|
|
|
|
|
|
| 106 |
```
|
| 107 |
|
| 108 |
+
It checks `manifest.sha256`, writes a temporary run directory (this folder's config with the three external paths
|
| 109 |
+
replaced; the shipped config is not edited) and runs `eval/temporal_point/checkpoint_evaluation.py --task video_depth`
|
| 110 |
+
per dataset with the aspect-preserving depth-fit protocol, EMA2, seed 0, `--base-steps 1`, `--depth-state-cap 1.984375`.
|
| 111 |
+
|
| 112 |
+
**What reads what.** The released PointDiT-B 512 checkpoint is never read: the scripts set `model.point.weights: random`,
|
| 113 |
+
which builds the same architecture, and all 216 tensors then come from the EMA2 file. The model after loading EMA2 is
|
| 114 |
+
bit-identical to one built over the released checkpoint (checked: 216 of 216 tensors equal). The recorded training
|
| 115 |
+
config keeps its Civo paths as history. Which keys still name one:
|
| 116 |
+
|
| 117 |
+
| Config key (`train/resolved_resume_29500.yaml`) | Read by load / inference / evaluation? | How to override |
|
| 118 |
+
|---|---|---|
|
| 119 |
+
| `model.point.checkpoint` (the released PointDiT-B 512 file) | no: skipped (see above) | nothing to do |
|
| 120 |
+
| `model.dino.weights` (DINOv3 file), `model.dino.repo` (DINOv3 checkout) | yes, by inference and evaluation | `--dino-weights`, `--dinov3-repo` |
|
| 121 |
+
| the evaluation data root (not in the config: `monocular_depth.DATA_ROOT`) | yes, by evaluation | `--data-root` |
|
| 122 |
+
| STream3R checkout (not in the config: default server path) | yes, by evaluation | environment variable `STREAM3R_ROOT` |
|
| 123 |
+
| `data.track4d.sources[*].kwargs.ROOT`, `metric_scales_csv`, `index_cache_dir`, `camera_exclusion_manifest` roots | no: training data, not read by these scripts | none needed |
|
| 124 |
+
| `train.output_dir`, `train.resume_from` | no | none needed |
|
| 125 |
+
|
| 126 |
+
The last two rows are from reading the code (the evaluator reads only `data.track4d.frames`, the model, DINO and schedule
|
| 127 |
+
sections); the off-Civo check below ran on a machine where those directories still exist, so it does not prove it.
|
| 128 |
|
| 129 |
## Run inference on your own video
|
| 130 |
|
| 131 |
`infer_video_depth.py` takes a video file or a folder of frames and writes per-frame depth. It builds the model through
|
| 132 |
the repository's builder (`build_point_model`), loads the EMA2 weights, computes the frozen DINOv3 ViT-B/16 features of the
|
| 133 |
frames and samples with the repository's sampler exactly as the evaluation does: one Euler step from Gaussian noise,
|
| 134 |
+
the contracted depth state capped at 1.984375, bf16 autocast. Run it from a clone of the repository (steps 1 to 4
|
| 135 |
+
of the Quick start), on one GPU (a CPU works but takes minutes per frame set):
|
| 136 |
|
| 137 |
```bash
|
| 138 |
+
D="--dino-weights <dinov3 file> --dinov3-repo <dinov3 checkout>"
|
| 139 |
+
python $FOLDER/infer_video_depth.py $FOLDER --input clip.mp4 --out out/ $D # first 21 frames
|
| 140 |
+
python $FOLDER/infer_video_depth.py $FOLDER --input frames_dir/ --out out/ --max-frames 25 --stride 2 $D
|
|
|
|
| 141 |
```
|
| 142 |
|
| 143 |
- **Frames:** the first `--max-frames` (default 21, at most 25) frames at `--stride`, in one call. Each is resized, whole
|
|
|
|
| 156 |
known scale, or fit one scale and shift per clip against a reference, as the benchmark does.
|
| 157 |
- **Seed.** The sampler starts from Gaussian noise: `--seed` fixes it. `--seed-key 0:<dataset>:<sequence>` uses the
|
| 158 |
benchmark's noise key, which reproduces a benchmark row's call exactly.
|
| 159 |
+
- **Weights it needs:** only this folder and the DINOv3 ViT-B/16 file and checkout (`--dino-weights`, `--dinov3-repo`,
|
| 160 |
+
both required). `--attention-backend` is `sdpa` by default; `fa2` is the recorded run's.
|
| 161 |
+
|
| 162 |
+
**Checked.** (1) Before the off-Civo flags were added, on one H100 (2026-10-07, repository commit `2310eec5`), the script
|
| 163 |
+
run on the first 21 frames of Bonn `balloon2` and Sintel `alley_2` with the benchmark noise key
|
| 164 |
+
(`--seed-key 0:<dataset>:<sequence>`) scores, after one scale and shift per sequence in depth against the ground truth
|
| 165 |
+
(the registered protocol), AbsRel 0.0970 on `balloon2` (recorded row: 0.0970) and 0.2377 on `alley_2` (recorded: 0.2368);
|
| 166 |
+
delta<1.25 0.9480 and 0.6414 (recorded 0.9480 and 0.6420). The recorded rows came from an A100; the small differences are
|
| 167 |
+
GPU and kernel numerics. (2) With the flags of this README, on one H100 (repository branch `docs/video-depth-pointdit-off-civo`),
|
| 168 |
+
every external input copied to node-local `/tmp` and passed by flag (this folder, the DINOv3 file and checkout, a STream3R
|
| 169 |
+
checkout, the Bonn frames), with `TRACK4D_ROOT` and `VGGT_OMEGA_ROOT` pointing at nonexistent paths: `load_point.py` printed
|
| 170 |
+
`temporal_pointdit window_valid_mean_depth 32500 0.9996 140204928`; `infer_video_depth.py` ran on a folder of 21 Bonn frames
|
| 171 |
+
and on an mp4 made from them (448 x 592 raster, `sdpa` attention); and `reproduce_evaluation.sh --datasets bonn` re-scored
|
| 172 |
+
Bonn at AbsRel 0.060529 against the recorded 0.060454 (difference +7.4e-5; `sdpa` here, `fa2` in the recorded row).
|
| 173 |
+
(3) A model built without the released checkpoint holds exactly the same 216 tensors as one built over it, after loading
|
| 174 |
+
EMA2 (all equal, bit for bit). A full three-set re-score from a downloaded copy of this folder with the earlier scripts
|
| 175 |
+
(`fa2`, Civo paths) gave Sintel 0.381766, Bonn 0.060523, KITTI 0.090556 against the recorded 0.381446, 0.060454, 0.090497.
|
| 176 |
|
| 177 |
## Recorded results
|
| 178 |
|
|
|
|
| 224 |
- DINOv3 (Meta) is under the DINOv3 licence and is NOT redistributed here. Request it at
|
| 225 |
`https://ai.meta.com/resources/models-and-libraries/dinov3-downloads/`. The model needs the ViT-B/16 LVD-1689M
|
| 226 |
weights (`dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth`, sha256
|
| 227 |
+
`73cec8be7427c8655ceced13ce62f6e20a1fa90d1b4d4a550df17a1144081a7c`).
|
|
|
|
|
|
video-depth-pointdit/infer_video_depth.py
CHANGED
|
@@ -4,8 +4,11 @@
|
|
| 4 |
python infer_video_depth.py <this folder> --input clip.mp4 --out out_dir
|
| 5 |
python infer_video_depth.py <this folder> --input frames_dir/ --out out_dir --max-frames 21 --stride 2
|
| 6 |
|
| 7 |
-
Run it from
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
| 9 |
(`build_point_model`), loads the EMA2 weights (`_load_weights`), computes the frozen DINOv3 ViT-B/16 features of the
|
| 10 |
frames, and samples with the repository's sampler (`sample_window_self_maps`: the shared Euler driver, one step from
|
| 11 |
Gaussian noise, the contracted depth state capped at 1.984375, bf16 autocast) exactly as the evaluator does.
|
|
@@ -80,11 +83,11 @@ def main() -> int:
|
|
| 80 |
parser.add_argument("--seed", type=int, default=0, help="seed of the Gaussian noise the sampler starts from")
|
| 81 |
parser.add_argument("--seed-key", help="the evaluator's noise key '<seed>:<dataset>:<sequence>' (reproduction)")
|
| 82 |
parser.add_argument("--hfov-degrees", type=float, help="horizontal field of view; writes depth_frame0_gauge.npy")
|
| 83 |
-
parser.add_argument("--dino-weights", type=Path,
|
| 84 |
-
|
| 85 |
-
parser.add_argument("--
|
| 86 |
-
parser.add_argument("--
|
| 87 |
-
help="
|
| 88 |
parser.add_argument("--no-mp4", action="store_true")
|
| 89 |
args = parser.parse_args()
|
| 90 |
if not 1 <= args.max_frames <= MAX_FRAMES or args.stride < 1:
|
|
@@ -104,13 +107,10 @@ def main() -> int:
|
|
| 104 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 105 |
run, ckpt = args.folder / "train", args.folder / "train" / "ckpt_32500"
|
| 106 |
cfg = resolve_run_config(run, ckpt)["cfg"]
|
| 107 |
-
cfg.model.point.attention_backend = args.attention_backend
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
cfg.model.dino.weights = str(args.dino_weights)
|
| 112 |
-
if args.dinov3_repo:
|
| 113 |
-
cfg.model.dino.repo = str(args.dinov3_repo)
|
| 114 |
|
| 115 |
bgr = read_frames(args.input, args.max_frames, args.stride)
|
| 116 |
height, width = bgr[0].shape[:2]
|
|
|
|
| 4 |
python infer_video_depth.py <this folder> --input clip.mp4 --out out_dir
|
| 5 |
python infer_video_depth.py <this folder> --input frames_dir/ --out out_dir --max-frames 21 --stride 2
|
| 6 |
|
| 7 |
+
Run it from a clone of github.com/NIRVANALAN/vgg_forecast_4d (commit 2310eec5 or later) with PYTHONPATH=<clone>/src,
|
| 8 |
+
on one GPU (a CPU works, slowly). Every external input is a flag: the DINOv3 ViT-B/16 weights (--dino-weights) and a
|
| 9 |
+
checkout of github.com/facebookresearch/dinov3 (--dinov3-repo). It reads no other file outside this folder and your
|
| 10 |
+
input: the released PointDiT-B checkpoint that the training config names is not read (every tensor comes from the EMA2
|
| 11 |
+
file; the model is bit-identical to one built over it). It builds the model through the repository's builder
|
| 12 |
(`build_point_model`), loads the EMA2 weights (`_load_weights`), computes the frozen DINOv3 ViT-B/16 features of the
|
| 13 |
frames, and samples with the repository's sampler (`sample_window_self_maps`: the shared Euler driver, one step from
|
| 14 |
Gaussian noise, the contracted depth state capped at 1.984375, bf16 autocast) exactly as the evaluator does.
|
|
|
|
| 83 |
parser.add_argument("--seed", type=int, default=0, help="seed of the Gaussian noise the sampler starts from")
|
| 84 |
parser.add_argument("--seed-key", help="the evaluator's noise key '<seed>:<dataset>:<sequence>' (reproduction)")
|
| 85 |
parser.add_argument("--hfov-degrees", type=float, help="horizontal field of view; writes depth_frame0_gauge.npy")
|
| 86 |
+
parser.add_argument("--dino-weights", type=Path, required=True,
|
| 87 |
+
help="dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth (sha256 73cec8be..., checked against the config)")
|
| 88 |
+
parser.add_argument("--dinov3-repo", type=Path, required=True, help="a checkout of github.com/facebookresearch/dinov3")
|
| 89 |
+
parser.add_argument("--attention-backend", default="sdpa",
|
| 90 |
+
help="Point attention: sdpa (default, needs no extra package) or fa2 (the recorded run's, needs flash-attn)")
|
| 91 |
parser.add_argument("--no-mp4", action="store_true")
|
| 92 |
args = parser.parse_args()
|
| 93 |
if not 1 <= args.max_frames <= MAX_FRAMES or args.stride < 1:
|
|
|
|
| 107 |
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 108 |
run, ckpt = args.folder / "train", args.folder / "train" / "ckpt_32500"
|
| 109 |
cfg = resolve_run_config(run, ckpt)["cfg"]
|
| 110 |
+
cfg.model.point.attention_backend = args.attention_backend
|
| 111 |
+
cfg.model.point.weights = "random" # model.point.checkpoint (the released checkpoint) is not read
|
| 112 |
+
cfg.model.dino.weights = str(args.dino_weights)
|
| 113 |
+
cfg.model.dino.repo = str(args.dinov3_repo)
|
|
|
|
|
|
|
|
|
|
| 114 |
|
| 115 |
bgr = read_frames(args.input, args.max_frames, args.stride)
|
| 116 |
height, width = bgr[0].shape[:2]
|
video-depth-pointdit/load_point.py
CHANGED
|
@@ -1,22 +1,28 @@
|
|
| 1 |
-
"""Build the video-depth PointDiT-B
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import sys
|
| 3 |
from pathlib import Path
|
| 4 |
|
| 5 |
-
import torch
|
| 6 |
-
|
| 7 |
from vggforecast.evaluation.checkpoint_loading import _load_weights, resolve_run_config
|
| 8 |
from vggforecast.training.model_loading import build_point_model
|
| 9 |
|
| 10 |
-
FOLDER = Path(sys.argv[1])
|
| 11 |
RUN, CKPT = FOLDER / "train", FOLDER / "train" / "ckpt_32500"
|
| 12 |
|
| 13 |
cfg = resolve_run_config(RUN, CKPT)["cfg"] # resolved_resume_29500.yaml + launch_resume_29500.json
|
| 14 |
-
cfg.model.point.
|
| 15 |
-
model
|
|
|
|
| 16 |
base_hw = tuple(int(v) * core.trunk.patch for v in core.trunk.position_source_grid)
|
| 17 |
-
loaded = _load_weights(model, core, CKPT, "ema2", base_hw) # every tensor
|
| 18 |
model.eval()
|
| 19 |
-
print(
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
print("point expert", type(model.mot.point).__name__, "blocks", len(core.trunk.blocks))
|
|
|
|
| 1 |
+
"""Build the video-depth PointDiT-B through the repository's builder and load its EMA2 weights (CPU, no Civo file).
|
| 2 |
+
|
| 3 |
+
python load_point.py <this folder>
|
| 4 |
+
|
| 5 |
+
Run from a clone of github.com/NIRVANALAN/vgg_forecast_4d with PYTHONPATH=<clone>/src. Nothing outside this folder is
|
| 6 |
+
read: the released PointDiT-B 512 checkpoint that the training config names is NOT read (`model.point.weights: random`
|
| 7 |
+
builds the same architecture, and every one of the 216 tensors then comes from the EMA2 file; the model after the load is
|
| 8 |
+
bit-identical to one built over the released checkpoint). The frozen DINOv3 encoder is not needed to load.
|
| 9 |
+
"""
|
| 10 |
import sys
|
| 11 |
from pathlib import Path
|
| 12 |
|
|
|
|
|
|
|
| 13 |
from vggforecast.evaluation.checkpoint_loading import _load_weights, resolve_run_config
|
| 14 |
from vggforecast.training.model_loading import build_point_model
|
| 15 |
|
| 16 |
+
FOLDER = Path(sys.argv[1])
|
| 17 |
RUN, CKPT = FOLDER / "train", FOLDER / "train" / "ckpt_32500"
|
| 18 |
|
| 19 |
cfg = resolve_run_config(RUN, CKPT)["cfg"] # resolved_resume_29500.yaml + launch_resume_29500.json
|
| 20 |
+
cfg.model.point.weights = "random" # do not read model.point.checkpoint
|
| 21 |
+
cfg.model.point.attention_backend = "sdpa" # the run used fa2 on a GPU; sdpa needs no extra package
|
| 22 |
+
model, core, provenance = build_point_model(cfg)
|
| 23 |
base_hw = tuple(int(v) * core.trunk.patch for v in core.trunk.position_source_grid)
|
| 24 |
+
loaded = _load_weights(model, core, CKPT, "ema2", base_hw) # every tensor comes from ema2
|
| 25 |
model.eval()
|
| 26 |
+
print(model.architecture, core.target_centering, loaded["completed_updates"], loaded["ema_decay"],
|
| 27 |
+
sum(p.numel() for p in model.parameters()))
|
| 28 |
+
# temporal_pointdit window_valid_mean_depth 32500 0.9996 140204928
|
|
|
video-depth-pointdit/manifest.json
CHANGED
|
@@ -21,23 +21,23 @@
|
|
| 21 |
"files": [
|
| 22 |
{
|
| 23 |
"path": "README.md",
|
| 24 |
-
"bytes":
|
| 25 |
-
"sha256": "
|
| 26 |
},
|
| 27 |
{
|
| 28 |
"path": "infer_video_depth.py",
|
| 29 |
-
"bytes":
|
| 30 |
-
"sha256": "
|
| 31 |
},
|
| 32 |
{
|
| 33 |
"path": "load_point.py",
|
| 34 |
-
"bytes":
|
| 35 |
-
"sha256": "
|
| 36 |
},
|
| 37 |
{
|
| 38 |
"path": "reproduce_evaluation.sh",
|
| 39 |
-
"bytes":
|
| 40 |
-
"sha256": "
|
| 41 |
},
|
| 42 |
{
|
| 43 |
"path": "rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_bonn.jsonl",
|
|
|
|
| 21 |
"files": [
|
| 22 |
{
|
| 23 |
"path": "README.md",
|
| 24 |
+
"bytes": 17774,
|
| 25 |
+
"sha256": "5062b47c21ad5247032a7b2af694b16646704bf60461ef48086830c0e34cfc64"
|
| 26 |
},
|
| 27 |
{
|
| 28 |
"path": "infer_video_depth.py",
|
| 29 |
+
"bytes": 10836,
|
| 30 |
+
"sha256": "05e428ba854c366ec5a76706ca26199fc506efe1381abc2961e395357aea4185"
|
| 31 |
},
|
| 32 |
{
|
| 33 |
"path": "load_point.py",
|
| 34 |
+
"bytes": 1646,
|
| 35 |
+
"sha256": "a53ae802629e7b16df4b84e7df89cc91b8c46d8a561a9b275f38a4bf094c0e69"
|
| 36 |
},
|
| 37 |
{
|
| 38 |
"path": "reproduce_evaluation.sh",
|
| 39 |
+
"bytes": 3492,
|
| 40 |
+
"sha256": "e319b66268356bdd1f183c5658b619098ed04a1abeb4b342a51d8d042eb5311c"
|
| 41 |
},
|
| 42 |
{
|
| 43 |
"path": "rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_bonn.jsonl",
|
video-depth-pointdit/manifest.sha256
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
2ef4877a1486026e9c8904b5e481a6f953b3fbf2694c5b441bbbb54bf41d1c58 rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_bonn.jsonl
|
| 6 |
ebd65468808940716fb759f5b7f6f8c8892b1c65947d759eccd4e3a0544c5b5a rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_kitti.jsonl
|
| 7 |
1940d1b65e64dc545002c415a139aff185f2afcf990a7f29fd41d5ecf3e2323d rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_sintel.jsonl
|
|
|
|
| 1 |
+
5062b47c21ad5247032a7b2af694b16646704bf60461ef48086830c0e34cfc64 README.md
|
| 2 |
+
05e428ba854c366ec5a76706ca26199fc506efe1381abc2961e395357aea4185 infer_video_depth.py
|
| 3 |
+
a53ae802629e7b16df4b84e7df89cc91b8c46d8a561a9b275f38a4bf094c0e69 load_point.py
|
| 4 |
+
e319b66268356bdd1f183c5658b619098ed04a1abeb4b342a51d8d042eb5311c reproduce_evaluation.sh
|
| 5 |
2ef4877a1486026e9c8904b5e481a6f953b3fbf2694c5b441bbbb54bf41d1c58 rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_bonn.jsonl
|
| 6 |
ebd65468808940716fb759f5b7f6f8c8892b1c65947d759eccd4e3a0544c5b5a rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_kitti.jsonl
|
| 7 |
1940d1b65e64dc545002c415a139aff185f2afcf990a7f29fd41d5ecf3e2323d rows/single_frame_test_video_depth_anything_aspect_preserving_depth_fit_sintel.jsonl
|
video-depth-pointdit/reproduce_evaluation.sh
CHANGED
|
@@ -1,24 +1,55 @@
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
# Re-scores this checkpoint (EMA2, update 32,500) on Sintel / Bonn / KITTI with the registered native-aspect depth-fit
|
| 3 |
# protocol, one 21-frame call per sequence, one step from Gaussian noise. Run from the root of a clone of
|
| 4 |
-
# NIRVANALAN/vgg_forecast_4d (commit 2310eec5 or later)
|
| 5 |
#
|
| 6 |
-
#
|
|
|
|
|
|
|
|
|
|
| 7 |
#
|
| 8 |
-
#
|
| 9 |
-
#
|
|
|
|
| 10 |
set -uo pipefail
|
| 11 |
-
(
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
export PYTHONPATH="$PWD/src" WANDB_MODE=disabled
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
RUN=$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
DECODE=$(python -B eval/temporal_point/video_depth_decode_arguments.py --run-dir "$RUN" --checkpoint "$CK" \
|
| 19 |
--centred-decode normalized_centred_depth) || exit 4
|
| 20 |
-
for ds in
|
| 21 |
python -B eval/temporal_point/checkpoint_evaluation.py --task video_depth --dataset $ds --run-dir "$RUN" \
|
| 22 |
-
--checkpoint "$CK" --sequence-frames window $DECODE --video-depth-protocol $PROTO
|
| 23 |
-
--base-steps 1 --depth-state-cap 1.984375 --out "$OUT/test_${PROTO}_${ds}.jsonl" || exit 5
|
| 24 |
done
|
|
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
# Re-scores this checkpoint (EMA2, update 32,500) on Sintel / Bonn / KITTI with the registered native-aspect depth-fit
|
| 3 |
# protocol, one 21-frame call per sequence, one step from Gaussian noise. Run from the root of a clone of
|
| 4 |
+
# github.com/NIRVANALAN/vgg_forecast_4d (commit 2310eec5 or later), with its requirements installed, on one GPU:
|
| 5 |
#
|
| 6 |
+
# export STREAM3R_ROOT=<checkout of github.com/NVlabs/STream3R at 7bdca8cf7ec206ff8b08c0941ad8286d72087d4f>
|
| 7 |
+
# bash reproduce_evaluation.sh <downloaded video-depth-pointdit folder> <output dir> \
|
| 8 |
+
# --dino-weights <dinov3_vitb16_pretrain_lvd1689m-73cec8be.pth> --dinov3-repo <dinov3 checkout> \
|
| 9 |
+
# --data-root <dir holding sintel/ bonn/ kitti/> [--attention-backend sdpa|fa2] [--datasets "sintel bonn kitti"]
|
| 10 |
#
|
| 11 |
+
# No Civo path is needed: the config's DINOv3 paths are replaced by the flags in a temporary copy of the run
|
| 12 |
+
# directory (the training config is not edited), and the released PointDiT-B checkpoint is not read (every tensor comes
|
| 13 |
+
# from the EMA2 file). Rows go to <output dir>/test_<protocol>_<dataset>.jsonl and compare with rows/.
|
| 14 |
set -uo pipefail
|
| 15 |
+
usage() { sed -n '2,12p' "$0" >&2; exit 2; }
|
| 16 |
+
(( $# >= 2 )) || usage
|
| 17 |
+
FOLDER=$(realpath "$1"); OUT=$(realpath -m "$2"); shift 2
|
| 18 |
+
DINO_WEIGHTS=; DINO_REPO=; DATA_ROOT=; ATTENTION=sdpa; DATASETS="sintel bonn kitti"
|
| 19 |
+
while (( $# )); do
|
| 20 |
+
case "$1" in
|
| 21 |
+
--dino-weights) DINO_WEIGHTS=$(realpath "$2"); shift 2;;
|
| 22 |
+
--dinov3-repo) DINO_REPO=$(realpath "$2"); shift 2;;
|
| 23 |
+
--data-root) DATA_ROOT=$(realpath "$2"); shift 2;;
|
| 24 |
+
--attention-backend) ATTENTION=$2; shift 2;;
|
| 25 |
+
--datasets) DATASETS=$2; shift 2;;
|
| 26 |
+
*) usage;;
|
| 27 |
+
esac
|
| 28 |
+
done
|
| 29 |
+
[[ -n $DINO_WEIGHTS && -n $DINO_REPO && -n $DATA_ROOT && -n ${STREAM3R_ROOT:-} ]] || { echo "missing flag or STREAM3R_ROOT" >&2; usage; }
|
| 30 |
export PYTHONPATH="$PWD/src" WANDB_MODE=disabled
|
| 31 |
+
(cd "$FOLDER" && sha256sum -c manifest.sha256 >/dev/null) || { echo "the folder does not match manifest.sha256" >&2; exit 3; }
|
| 32 |
+
mkdir -p "$OUT"
|
| 33 |
+
# A temporary run directory: the folder's config with the three external paths replaced, the folder's checkpoint.
|
| 34 |
+
RUN=$(mktemp -d "$OUT/run.XXXXXX")
|
| 35 |
+
python - "$FOLDER" "$RUN" "$DINO_WEIGHTS" "$DINO_REPO" "$ATTENTION" <<'PY'
|
| 36 |
+
import sys
|
| 37 |
+
from pathlib import Path
|
| 38 |
+
from omegaconf import OmegaConf
|
| 39 |
+
folder, run, weights, repo, attention = (Path(sys.argv[1]), Path(sys.argv[2]), *sys.argv[3:])
|
| 40 |
+
cfg = OmegaConf.load(folder / "train" / "resolved_resume_29500.yaml")
|
| 41 |
+
cfg.model.point.weights = "random" # the released checkpoint is not read
|
| 42 |
+
cfg.model.point.attention_backend = attention
|
| 43 |
+
cfg.model.dino.weights, cfg.model.dino.repo = weights, repo
|
| 44 |
+
OmegaConf.save(cfg, run / "resolved_resume_29500.yaml")
|
| 45 |
+
(run / "launch_resume_29500.json").write_bytes((folder / "train" / "launch_resume_29500.json").read_bytes())
|
| 46 |
+
(run / "ckpt_32500").symlink_to(folder / "train" / "ckpt_32500")
|
| 47 |
+
PY
|
| 48 |
+
CK=$RUN/ckpt_32500; PROTO=video_depth_anything_aspect_preserving_depth_fit
|
| 49 |
DECODE=$(python -B eval/temporal_point/video_depth_decode_arguments.py --run-dir "$RUN" --checkpoint "$CK" \
|
| 50 |
--centred-decode normalized_centred_depth) || exit 4
|
| 51 |
+
for ds in $DATASETS; do
|
| 52 |
python -B eval/temporal_point/checkpoint_evaluation.py --task video_depth --dataset $ds --run-dir "$RUN" \
|
| 53 |
+
--checkpoint "$CK" --data-root "$DATA_ROOT" --sequence-frames window $DECODE --video-depth-protocol $PROTO \
|
| 54 |
+
--weights ema2 --seeds 0 --base-steps 1 --depth-state-cap 1.984375 --out "$OUT/test_${PROTO}_${ds}.jsonl" || exit 5
|
| 55 |
done
|