Spatial Understanding from Videos: Structured Prompts Meet Simulation Data
NeurIPS 2025 Spotlight
Haoyu Zhang1,2, Meng Liu3,4, Zaijing Li1,2, Haokun Wen1,
Weili Guan1, Yaowei Wang1,2, Liqiang Nie1
1 Harbin Institute of Technology (Shenzhen) ·
2 Pengcheng Laboratory
3 Shandong Jianzhu University ·
4 Zhongguancun Academy
SpaceEra++: A Unified Framework Towards 3D Spatial Reasoning in Video
Accepted by IEEE Transactions on Pattern Analysis and Machine Intelligence (TPAMI), 2026 · Early Access
Weili Guan1,2, Haoyu Zhang1,3, Meng Liu4,5,
Qianlong Xiang1,6,2, Yaowei Wang1,4, Liqiang Nie1
1 Harbin Institute of Technology (Shenzhen) ·
2 Shenzhen Loop Area Institute
3 Pengcheng Laboratory ·
4 Shandong University
5 Zhongguancun Academy ·
6 City University of Hong Kong
SpatialMind ·
ScanForgeQA ·
ScenePick ·
SpaceAlign
Overview · Installation · Training · Inference · Methods · Citation
This repository contains the code for both versions of SpaceEra:
| Version | Venue | Main components | Purpose |
|---|---|---|---|
| SpaceEra | NeurIPS 2025 Spotlight | SpatialMind, ScanForgeQA | Structured inference and synthetic spatial QA data |
| SpaceEra++ | IEEE TPAMI 2026, accepted | ScenePick, SpaceAlign | Informative frame selection and spatially constrained GRPO |
The integrated workflow is:
Training
ScanForgeQA ──► ScenePick ──► Vision-Language Model ──► SpaceAlign GRPO
Inference
Video sample ──► ScenePick ──► SpatialMind ──► Vision-Language Model ──► Answer
Note
The commands below use Qwen/Qwen2.5-VL-7B-Instruct as a reference example. It can be replaced through --model with another Transformers/TRL-compatible vision-language model. Depending on the architecture, adjust the processor/media loader and --lora-target-modules accordingly.
| Component | Stage | Implementation |
|---|---|---|
| 🧠 SpatialMind | Inference | Scene decomposition and question decomposition prompts |
| 🏗️ ScanForgeQA | Data | Scene construction, scan creation, and spatial QA generation |
| 🎞️ ScenePick | Input | VGGT reconstruction, semantic voxel weighting, and greedy frame selection |
| 🎯 SpaceAlign | Training | Format, task, absolute-coordinate, and relative-relation rewards |
| 🔗 Integrated workflow | End to end | ScanForgeQA adapters, cached preprocessing, GRPO training, and VLM inference |
.
├── asset/ # Paper figures
├── examples/
│ ├── scene0277_02.mp4 # Example scanning video
│ ├── scene_spec.json # Scene construction example
│ ├── grounding_boxes.json # ScenePick semantic boxes
│ ├── scanforgeqa_training_sample.jsonl
│ └── spacealign_reward.json
├── scripts/
│ ├── prepare_scanforgeqa.py # ScanForgeQA -> ScenePick cache
│ ├── train_spacealign.py # SpaceAlign GRPO training
│ └── infer_spaceera.py # ScenePick + SpatialMind inference
├── src/spaceera/
│ ├── scanforgeqa/ # Conference: dataset construction
│ ├── spatialmind/ # Conference: prompting
│ ├── scenepick/ # Journal: frame selection
│ ├── spacealign/ # Journal: spatial rewards
│ ├── workflows/ # Integrated data and prompt pipeline
│ ├── schemas.py
│ └── cli.py
├── tests/
├── max_coverage_cal_batch.py # Legacy ScenePick entry point
├── max_coverage_cal.py # Legacy alias
└── pyproject.toml
python3 -m pip install -e .python3 -m pip install -e '.[scenepick,training]'Python 3.10 or newer is recommended. The complete stack includes PyTorch, Transformers, TRL, PEFT, Datasets, and Qwen vision utilities. It pins trl==0.21.0; PyTorch SDPA is used by default, while Flash Attention remains optional.
ScenePick additionally expects the official VGGT package to be importable as vggt:
git clone https://github.com/facebookresearch/vggt.git
cd vggt
python3 -m pip install -e .VGGT weights can be provided as a Hugging Face model ID such as facebook/VGGT-1B or as a local checkpoint directory.
Tip
Grounded SAM 2 is optional. Without question-specific grounding boxes, ScenePick runs the spatial-coverage-only variant.
The training path is deliberately split into a deterministic ScenePick preparation stage and a model-training stage. This prevents VGGT reconstruction from being repeated in every epoch.
Training accepts JSON or JSONL. A canonical sample looks like:
{
"sample_id": "scene0001_qa0001",
"video_path": "videos/scene0001.mp4",
"question": "What is the distance between the sofa and table?",
"answer": "2.0 meters",
"question_type": "absolute_distance",
"selected_frames": [],
"ground_truth_coordinates": {
"sofa": [2, 3],
"table": [6, 3]
},
"category_counts": {
"sofa": 1,
"table": 1
},
"grounding_boxes": {}
}Required fields are video_path, question, and answer.
selected_framesmay be empty; ScenePick will populate it.ground_truth_coordinatesenables the complete SpaceAlign spatial rewards.- If
scene_graph_pathis provided instead, 10×10 grid coordinates are derived automatically. grounding_boxesenables question-aware semantic weighting.- Common aliases such as
video,source_video,qa_id,problem, andsolutionare accepted.
Run cached ScenePick preprocessing:
python3 scripts/prepare_scanforgeqa.py \
--dataset /path/to/scanforgeqa_train.jsonl \
--video-root /path/to/ScanForgeQA \
--vggt-model facebook/VGGT-1B \
--num-frames 32 \
--max-candidates 64 \
--output outputs/scanforgeqa_train_scenepick.jsonlQuestions sharing the same video reuse one VGGT reconstruction. Only one video's dense point maps are retained in memory at a time.
The following command uses Qwen2.5-VL-7B-Instruct as an example backbone:
accelerate launch scripts/train_spacealign.py \
--dataset outputs/scanforgeqa_train_scenepick.jsonl \
--model Qwen/Qwen2.5-VL-7B-Instruct \
--output-dir outputs/spacealign-qwen2.5-vl-7b \
--num-generations 4 \
--batch-size 1 \
--gradient-accumulation-steps 8 \
--dtype bfloat16The example configuration applies LoRA to q_proj and v_proj. For another backbone:
--model organization/another-vlm \
--lora-target-modules q_proj k_proj v_proj o_projSpaceAlign trains the model to return:
<spatial_map>{"object": [x, y]}</spatial_map>
<think>spatial reasoning</think>
<answer>final answer</answer>
The four reward components are logged independently:
| Reward | Function |
|---|---|
R_format |
Checks the required response structure |
R_task |
Scores multiple-choice, text, or numerical correctness |
R_abs |
Measures normalized object-coordinate accuracy |
R_rel |
Measures pairwise direction and distance consistency |
An unprepared dataset can also be passed directly to train_spacealign.py; add --vggt-model and ScenePick will run before training.
Validate records without loading model weights:
python3 scripts/train_spacealign.py \
--dataset outputs/scanforgeqa_train_scenepick.jsonl \
--dry-runImportant
GRPO generates multiple completions for every visual prompt and is substantially more memory-intensive than SFT. Use an Accelerate/DeepSpeed configuration appropriate for the available GPUs.
Inference combines ScenePick-selected frames with a SpatialMind prompt and the chosen vision-language model.
python3 scripts/infer_spaceera.py \
--dataset outputs/scanforgeqa_train_scenepick.jsonl \
--sample-id scene0001_qa0001 \
--model Qwen/Qwen2.5-VL-7B-Instruct \
--adapter outputs/spacealign-qwen2.5-vl-7b \
--output outputs/prediction.jsonOmit --adapter to use the original backbone. Replace --model to evaluate another compatible VLM.
Add ScenePick parameters:
python3 scripts/infer_spaceera.py \
--dataset /path/to/raw_samples.jsonl \
--sample-id scene0001_qa0001 \
--vggt-model facebook/VGGT-1B \
--num-frames 32 \
--max-candidates 64 \
--model Qwen/Qwen2.5-VL-7B-Instruct \
--output outputs/prediction.jsonWhen scene_graph_path is available, SpatialMind includes its structured scene representation. Otherwise, it instructs the VLM to perform local modeling, coordinate mapping, cognition generation, and question decomposition directly from the selected frames.
Inspect the complete model input without loading VLM weights:
python3 scripts/infer_spaceera.py \
--dataset outputs/scanforgeqa_train_scenepick.jsonl \
--sample-id scene0001_qa0001 \
--dry-run \
--output outputs/inference_input.jsonSpatialMind decomposes spatial reasoning into two coordinated stages:
- Scene decomposition: local modeling, coordinate mapping, and cognition generation.
- Question decomposition: classify the spatial task and construct explicit reasoning steps.
The implementation supports relative distance, object count, appearance order, relative direction, object size, absolute distance, room size, and route planning.
ScanForgeQA provides a three-stage synthetic data pipeline:
- Scene construction from structured room and object specifications.
- Scan creation using orbit and navigation camera trajectories.
- QA generation from scene geometry and object annotations.
Minimal conference-version example:
spaceera build-scene \
--scene-spec examples/scene_spec.json \
--output outputs/scene_graph.json
spaceera build-scan \
--scene-graph outputs/scene_graph.json \
--output outputs/scan_sequence.json \
--blender-script outputs/scan_camera.py
spaceera generate-qa \
--scene-graph outputs/scene_graph.json \
--video-path /path/to/rendered_scan.mp4 \
--output outputs/qa_pairs.jsonSupplying --video-path writes the video and scene-graph references required by integrated training.
ScenePick combines geometric coverage with question-related object semantics:
- Uniformly pre-sample candidate frames.
- Reconstruct depth, camera poses, and 3D points with VGGT.
- Ground question-related objects and assign semantic weights.
- Voxelize valid 3D points.
- Greedily maximize weighted coverage.
Run it directly on the included video:
spaceera scenepick \
--video-dir examples/scene0277_02.mp4 \
--model facebook/VGGT-1B \
--num-frames 32 \
--max-candidates 64 \
--output outputs/scene0277_02_scenepick.jsonFor semantic sampling, add:
--grounding-json examples/grounding_boxes.jsonGrounding JSON uses {frame_name_or_path: [[x1, y1, x2, y2], ...]}. Without it, all points receive equal weight and the command reproduces the spatial-coverage-only ablation.
Core reward functions are available from spaceera.spacealign, while TRL-compatible batch adapters live in spaceera.spacealign.trl_rewards.
Evaluate the standalone example:
spaceera spacealign-reward \
--input examples/spacealign_reward.json \
--output outputs/reward.jsonreason_steps.py: inspect question decomposition.gen_scene_exp.py: inspect scene decomposition.nav_script.py: export an example Blender camera path.max_coverage_cal_batch.py: backward-compatible ScenePick entry point.
@inproceedings{NEURIPS2025_9541101f,
author = {Zhang, Haoyu and Liu, Meng and Li, Zaijing and Wen, Haokun and Guan, Weili and Wang, Yaowei and Nie, Liqiang},
booktitle = {Advances in Neural Information Processing Systems},
editor = {D. Belgrave and C. Zhang and H. Lin and R. Pascanu and P. Koniusz and M. Ghassemi and N. Chen},
pages = {103202--103229},
publisher = {Curran Associates, Inc.},
title = {Spatial Understanding from Videos: Structured Prompts Meet Simulation Data},
url = {https://proceedings.neurips.cc/paper_files/paper/2025/file/9541101fbc2f24bce5f2462b95db88c4-Paper-Conference.pdf},
volume = {38},
year = {2025}
}@article{guan2026spaceerapp,
author = {Guan, Weili and Zhang, Haoyu and Liu, Meng and Xiang, Qianlong and Wang, Yaowei and Nie, Liqiang},
journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence},
title = {SpaceEra++: A Unified Framework Towards 3D Spatial Reasoning in Video},
year = {2026},
pages = {1--15},
doi = {10.1109/TPAMI.2026.3692302}
}We thank the authors of VSI-Bench, VGGT, Grounded SAM 2, Blender, Hugging Face Transformers/TRL, and LLaMA-Factory for their released tools and resources.



