Views
No views yet
Derived fromroboflow/rf-detr(Apache-2.0); significant changes were made — see Attribution & license.

TemporalPreEmbed block — differs; the patch embed → DINOv2 → LW-DETR decoder downstream is identical to upstream RF-DETR and loads its pretrained weights verbatim.R ≡ 0 and (for bgsub/bgsubcoh) the add-weight term vanishes on static
input, so the backbone receives exactly the current frame → identical to the single-frame
baseline. The temporal contribution is learned from there.| Upstream RF-DETR | RF-DETR-Temporal | |
|---|---|---|
| Input | 1 frame, (B,3,H,W) | 3 stacked frames, (B,9,H,W), last = current |
| Multi-channel | widens the patch-embed conv (sums channels → averages frames) | TemporalPreEmbed reduces 9→3 before the unmodified 3ch patch embed |
| Pretrained patch embed | lossily widened | loaded unchanged; new module absorbed by strict=False |
| Init behaviour | — | exact single-frame parity; temporal learned as a residual |
| New config | — | in_channels, temporal_fusion ∈ {none, preembed, bgsub, bgsubcoh} |
| Training | PyTorch-Lightning stack | standalone DDP script + manifest loader + temporal-aware augmentation |
| Tooling | — | diagnostics/ suite (parity, motion-/size-stratified eval, …) |
Conv2d to 9 channels makes the embedding
compute the temporal average of the frames — a low-pass / motion-blur op that destroys the
change signal and feeds the backbone an out-of-distribution blurred image.TemporalPreEmbed. Reduce 9→3 channels with a small motion-aware module
before the unmodified 3-channel patch embed, so DINOv2/RF-DETR weights load verbatim and the
model starts at single-frame parity. Three fusion modes (preembed, bgsub, bgsubcoh) trade
off how the temporal/motion signal is injected.preembed it is a zero-init residual on
motion (frame) differences — it adds nothing at initialisation (so the model starts exactly at the
single-frame baseline) and learns the temporal cue as a residual from there:
1pip install uv && uv sync --all-groups # PyTorch >=2.2,<3; transformers >=5,<6; Python >=3.10
2
3# provide your data as two manifests — data_manifests/{train,valid}.txt — one clip per line:
4# /abs/frame0|/abs/frame1|/abs/frame2|<labels>
5# where <labels> are YOLO "cls cx cy w h" boxes for the LAST (current) frame. See docs/training.md.
6
7# train on 4 GPUs (coherence-gated motion add-weight + moving small-object augmentation)
8DATA_DIR=data_manifests NUM_GPUS=4 RESOLUTION=952 \
9TEMPORAL_FUSION=bgsubcoh AUG_SMALLOBJ_P=0.5 AUG_SMALLOBJ_MOTION=14 \
10uv run --no-sync python train_temporal_base_v4.py| Configuration | Aggregate mAP@0.5 | Synthetic small-object mAP@0.5 |
|---|---|---|
| single-frame baseline | 0.875 | — |
| naive 9-channel (temporal averaging) | ~0.892 | — |
preembed (temporal) | 0.907 | ~0.06 |
preembed + small-object augmentation | ~0.88 | ~0.80 |
bgsub (plain motion add-weight) | 0.891 | — |
bgsubcoh + moving-object augmentation | in progress | in progress |
src/rfdetr/ # upstream RF-DETR (Apache-2.0), minimally modified
└── models/backbone/temporal_fusion.py # ★ TemporalPreEmbed (9ch→3ch motion fusion)
train_temporal_base_v4.py # ★ DDP training entrypoint + dataset + augmentations
diagnostics/ # ★ probes + stratified evaluators
export_onnx.py # ONNX export (9-channel temporal model)
docs/ # detailed design / training / findingsruns/, onnx_exports/, data_manifests/, and all
*.pth/*.onnx/*.mp4 artifacts (see .gitignore).LICENSE is retained
and all upstream source files keep their original license headers. Per Apache §4, this notice
states that significant changes were made: a new temporal pre-embedding module and fusion
modes, 9-channel input wiring, a small-object augmentation, and standalone training/diagnostics
tooling. The DINOv2-with-Registers backbone code is itself derived from HuggingFace Transformers
(see that file's header).