3D Semantic Map Generation from CityGML and COLMAP
April 10, 2026 · View on GitHub
Introduction
This project provides a pipeline for generating semantic segmentation maps from CityGML models and COLMAP reconstruction results, as part of the GS4City project.
The main workflow includes:
- Converting CityGML to OBJ
- Extracting a subset COLMAP model from a full reconstruction
- Extracting semantic ID mappings
- Generating semantic maps by raycasting from OBJ and COLMAP cameras
Project Structure
Below is the required directory structure before running any scripts:
project/
├── data/
│ ├── xxx/ # full COLMAP parameter folder
│ │ ├── undistorted/
│ │ │ └── sparse/
│ │ │ └── 0/
│ │ │ ├── cameras.txt
│ │ │ ├── images.txt
│ │ │ └── points3D.txt
│ │ │
│ │ └── scene_reference_frame.json
│ │ # coordinate transform (geographic → COLMAP)
│ │ # generated by Pix4Dmatic
│ │
│ ├── model_xxx/ # CityGML input folder
│ │ └── *.gml # one or multiple CityGML files
│ │
│ └── subset_xxx/
│ └── undistorted/
│ └── images/ # manually selected subset images
│ ├── *.jpg / *.png
│
├── output/
│
├── prepare_model.py
├── prepare_colmap.py
├── prepare_gmltable.py
└── model2mask.py
Requirements
Core Software (install separately)
-
COLMAP (used for COLMAP model extraction and conversion)
-
cjio (used for CityJSON / CityGML model conversion) https://github.com/cityjson/cjio
Python Dependencies
- Python 3.9+
- numpy
- scikit-learn
- plyfile
- tqdm
Install Python dependencies:
pip install numpy scikit-learn plyfile tqdm
CityGML to OBJ Conversion
Script
prepare_model.py
Input
data/model_xxx/*.gmldata/xxx/scene_reference_frame.json
Function
- merge multiple CityGML files
- convert to CityJSON
- apply coordinate transformation (to COLMAP system)
- export OBJ
- generate instance-to-CityJSON mapping
Usage
python prepare_model.py \
--parameter_dir xxx \
--model_dir model_xxx \
--z_offset 45.66
Output (generated in model_xxx/)
merged.json
*.obj
id_mapping.json
Notes
scene_reference_frame.jsonis used to align CityGML to COLMAP coordinatesz_offsetis empirically set and may require adjustment per dataset
COLMAP Sub-model Extraction
Script
prepare_colmap.py
Input
data/xxx/undistorted/sparse/0/data/subset_xxx/undistorted/images/
Function
- filter COLMAP model by subset images
- keep related cameras and 3D points
- convert to BIN format
- export PLY point cloud
- estimate normals
Usage
python prepare_colmap.py \
--building_name subset_xxx \
--parameter_dir xxx \
--colmap_exe ".../Colmap/colmap.bat" \
--neighbors 20
Output (generated in subset_xxx/undistorted/)
sparse_txt/
├── cameras.txt
├── images.txt
└── points3D.txt
sparse/
└── 0/
├── cameras.bin
├── images.bin
├── points3D.bin
└── points3D.ply
CityJSON Semantic Extraction
Script
prepare_gmltable.py
Input
data/model_xxx/merged.json
Function
- extract semantic hierarchy from CityJSON
- flatten into a table (building / surface / part)
Usage
python prepare_gmltable.py \
--model_dir model_xxx
Output (generated in model_xxx/)
city_semantics.json
Semantic Map Generation
Script
model2mask.py
Input
data/model_xxx/*.objdata/subset_xxx/undistorted/sparse_txt/data/subset_xxx/undistorted/images/
Function
- load mesh + semantic labels
- load COLMAP cameras
- perform raycasting
- generate semantic maps
Usage
python generate_maps.py \
--building_name subset_xxx \
--parameter_dir subset_xxx \
--model_dir model_xxx \
--level surface \
--inst \
--vis
Main arguments
--level:feature/surface/part--inst: instance map or class map--vis: save visualization--scale: resolution scale
Output
output/<building_name>_<timestamp>/
Includes:
.npysemantic maps.pngvisualization (optional)
Prerequisites
- CityGML to OBJ Conversion
- COLMAP Sub-model Extraction
must be completed before running this step.
Notes
- Ensure OBJ and COLMAP are in the same coordinate system
- Adjust
z_offsetif alignment is off - The program prints center differences for debugging
- Semantic ID consistency is critical