README.md
May 25, 2025 · View on GitHub
Notes
- This doc assume the current directory is the root directory of the project (Multi-SpatialMLLM).
- Create a directory
data/scannetto store the downloaded data.
cd Multi-SpatialMLLM
mkdir -p data/scannet
Download ScanNet data
- Follow the official website of ScanNet to get the download file
scannet_download.py. - Specify the data types we need to download:
FILETYPES = [ ".sens", ".aggregation.json", "_vh_clean.ply", "_vh_clean_2.0.010000.segs.json", "_vh_clean_2.ply", "_vh_clean.segs.json", "_vh_clean.aggregation.json", "_vh_clean_2.labels.ply", "_2d-instance.zip", "_2d-instance-filt.zip", "_2d-label.zip", "_2d-label-filt.zip", ] - Run the script to download the data:
python spatial_engine/utils/scannet_utils/scannet_download.py -o data/scannet - After downloading, you should have a folder structure like:
Multi-SpatialMLLM ├── data │ └── scannet │ ├── scans │ │ ├── scene0000_00 │ │ ├── ... │ └── ...
Process ScanNet data
-
Load point clouds, object point clouds, bounding boxes, etc.
python spatial_engine/utils/scannet_utils/batch_load_scannet_data.pyThis will generate a file called
scenes_train_info.pkl, which contains train and val splits. For convenience, we can split this info file to train and val (after update with image info if needed).import mmengine ori_train_info = mmengine.load("data/scannet/scannet_instance_data/scenes_train_val_info.pkl") # * load train scene id, read a txt, one line with one id, mmengine does not support txt format train_scene_ids = mmengine.list_from_file("data/scannet/meta_data/scannetv2_train.txt") train_scene_ids.sort() val_scene_ids = mmengine.list_from_file("data/scannet/meta_data/scannetv2_val.txt") val_scene_ids.sort() # * ori_train_info is a dict, key is scene_id # * according to the above train/val ids, split the info file to two separate files and save it. # * remember to check train + val = ori_train_info.keys() train_info = {k: ori_train_info[k] for k in train_scene_ids} val_info = {k: ori_train_info[k] for k in val_scene_ids} # * check assert len(train_info) + len(val_info) == len(ori_train_info) # * save mmengine.dump(train_info, "data/scannet/scannet_instance_data/scenes_train_info.pkl") mmengine.dump(val_info, "data/scannet/scannet_instance_data/scenes_val_info.pkl") -
Load posed images.
By default, we extract every image, if you want to export every nth image, you can set
frame_skip=nlike below.python spatial_engine/utils/scannet_utils/extract_posed_images.py --frame_skip 1Note that no matter what
frame_skipis, the extracted images will still be saved with the ID like00000.jpg,00001.jpg, etc. It also exports depth images, use imageio to read them and should divide 1000 to get the real depth value in meters. -
Update info_file with posed images information, this costs about 40 mins for if extracting all images. In this project, we only use every 5th image, so you need to set
frame_skip=5in the script to skip images. Note that the you still need to setframe_skip=1in theextract_posed_images.pyto make sure the image ids are consistent with our setting.python spatial_engine/utils/scannet_utils/update_info_file_with_images.pyThe images_info contains information like:
# Update the image data dictionary with this image's information image_data[image_id] = { "image_path": image_path, "depth_image_path": depth_image_path, "extrinsic_matrix": extrinsic_matrix } # Update the scene_info dictionary for the current scene_id scene_info[scene_id].update({ "num_posed_images": num_posed_images, "images": image_data, "intrinsic_matrix": intrinsic_matrix })
Final Results
After processing, you should have a folder structure like:
Multi-SpatialMLLM
├── data
│ └── scannet
│ ├── meta_data
│ ├── scans
│ │ ├── scene0000_00
│ │ ├── ...
│ ├── posed_images
│ │ ├── scene0000_00
│ │ ├── ...
│ └── scannet_instance_data
│ ├── scene0000_00
│ ├── ...
│ ├── scenes_train_info.pkl
│ └── scenes_val_info.pkl
The scannet_instance_data contains the point clouds of the whole scene and each instance both with axis-aligned and not axis-aligned world coordinate.