Update COLMAP integration for 4.1.0: add GLOMAP mapper and matching type options

#1
Files changed (3) hide show
  1. colmap_mapper.sh +11 -22
  2. colmap_matcher.sh +102 -131
  3. colmap_reconstruction.sh +5 -7
colmap_mapper.sh CHANGED
@@ -8,7 +8,6 @@ settings_yaml="$4"
8
  calibration_yaml="$5"
9
  rgb_csv="$6"
10
  camera_name="$7"
11
- mapper_type="$8"
12
 
13
  exp_folder_colmap="${exp_folder}/colmap_${exp_id}"
14
  rgb_dir="${camera_name}"
@@ -26,29 +25,19 @@ then
26
  ba_refine_extra_params="1"
27
  fi
28
 
 
29
  database="${exp_folder_colmap}/colmap_database.db"
30
 
31
- if [ "${mapper_type}" == "glomap" ]
32
- then
33
- echo " global mapper (GLOMAP) ..."
34
- colmap global_mapper \
35
- --database_path ${database} \
36
- --image_path ${rgb_path} \
37
- --output_path ${exp_folder_colmap} \
38
- --GlobalMapper.ba_refine_focal_length ${ba_refine_focal_length} \
39
- --GlobalMapper.ba_refine_principal_point ${ba_refine_principal_point} \
40
- --GlobalMapper.ba_refine_extra_params ${ba_refine_extra_params}
41
- else
42
- echo " colmap mapper (COLMAP) ..."
43
- colmap mapper \
44
- --database_path ${database} \
45
- --image_path ${rgb_path} \
46
- --output_path ${exp_folder_colmap} \
47
- --Mapper.ba_refine_focal_length ${ba_refine_focal_length} \
48
- --Mapper.ba_refine_principal_point ${ba_refine_principal_point} \
49
- --Mapper.ba_refine_extra_params ${ba_refine_extra_params}
50
- fi
51
 
52
  echo " colmap model_converter ..."
53
  colmap model_converter \
54
- --input_path ${exp_folder_colmap}/0 --output_path ${exp_folder_colmap} --output_type TXT
 
 
 
8
  calibration_yaml="$5"
9
  rgb_csv="$6"
10
  camera_name="$7"
 
11
 
12
  exp_folder_colmap="${exp_folder}/colmap_${exp_id}"
13
  rgb_dir="${camera_name}"
 
25
  ba_refine_extra_params="1"
26
  fi
27
 
28
+ echo " colmap mapper ..."
29
  database="${exp_folder_colmap}/colmap_database.db"
30
 
31
+ colmap mapper \
32
+ --database_path ${database} \
33
+ --image_path ${rgb_path} \
34
+ --output_path ${exp_folder_colmap} \
35
+ --Mapper.ba_refine_focal_length ${ba_refine_focal_length} \
36
+ --Mapper.ba_refine_principal_point ${ba_refine_principal_point} \
37
+ --Mapper.ba_refine_extra_params ${ba_refine_extra_params}
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
  echo " colmap model_converter ..."
40
  colmap model_converter \
41
+ --input_path ${exp_folder_colmap}/0 --output_path ${exp_folder_colmap} --output_type TXT
42
+
43
+
colmap_matcher.sh CHANGED
@@ -11,106 +11,13 @@ rgb_csv="$6"
11
  matcher_type="$7"
12
  use_gpu="$8"
13
  camera_name="$9"
14
- matching_type="${10}"
15
 
16
  exp_folder_colmap="${exp_folder}/colmap_${exp_id}"
17
  rgb_dir=$(awk -F, 'NR==2 { split($2,a,"/"); print a[1]; exit }' "$rgb_csv")
18
  rgb_path="${sequence_path}/${rgb_dir}"
19
 
20
- # matching_type: FeatureExtraction.type + FeatureMatching.type
21
- feature_matching_type=""
22
- feature_extraction_type="SIFT"
23
-
24
- case "${matching_type}" in
25
- sift_bruteforce)
26
- feature_extraction_type="SIFT"
27
- feature_matching_type="SIFT_BRUTEFORCE"
28
- ;;
29
- sift_lightglue)
30
- feature_extraction_type="SIFT"
31
- feature_matching_type="SIFT_LIGHTGLUE"
32
- ;;
33
- aliked_bruteforce)
34
- feature_extraction_type="ALIKED_N16ROT"
35
- feature_matching_type="ALIKED_BRUTEFORCE"
36
- ;;
37
- aliked_lightglue)
38
- feature_extraction_type="ALIKED_N16ROT"
39
- feature_matching_type="ALIKED_LIGHTGLUE"
40
- ;;
41
- *)
42
- echo "Unknown matching_type: ${matching_type}"
43
- exit 1
44
- ;;
45
- esac
46
-
47
- # Detect usable GPUs: extraction/matching run as a single job across all of
48
- # them, since COLMAP spawns one worker per listed GPU index and splits the
49
- # per-image / per-block workload internally.
50
- echo " detecting GPUs ..."
51
- echo " nvidia-smi -L:"
52
- nvidia-smi -L 2>&1 | sed 's/^/ /'
53
- echo " nvidia-smi --query-gpu=index,name,uuid --format=csv:"
54
- nvidia-smi --query-gpu=index,name,uuid --format=csv 2>&1 | sed 's/^/ /'
55
- echo " CUDA_VISIBLE_DEVICES: ${CUDA_VISIBLE_DEVICES}"
56
-
57
- if [ -n "${CUDA_VISIBLE_DEVICES}" ]; then
58
- # The scheduler already restricted this job to a specific device set (often
59
- # MIG slice UUIDs on HPC, which `nvidia-smi --query-gpu=index` does not
60
- # enumerate - it lists the whole node's GPUs, not what's gated to this job).
61
- # CUDA remaps whatever's listed here to ordinals 0..N-1 inside the process,
62
- # and COLMAP's gpu_index just calls cudaSetDevice(ordinal), so address by
63
- # ordinal count rather than trying to resolve real indices/UUIDs ourselves.
64
- num_gpus=$(echo "${CUDA_VISIBLE_DEVICES}" | tr ',' '\n' | grep -c .)
65
- gpu_ids=($(seq 0 $((num_gpus - 1))))
66
- else
67
- gpu_ids=($(nvidia-smi --query-gpu=index --format=csv,noheader 2>/dev/null))
68
- fi
69
- if [ "${#gpu_ids[@]}" -lt 1 ] || [ "${use_gpu}" == "0" ]; then
70
- gpu_ids=(0)
71
- fi
72
- gpu_index_list=$(IFS=,; echo "${gpu_ids[*]}")
73
- echo " use_gpu: ${use_gpu}"
74
- echo " detected gpu_ids: ${gpu_ids[*]}"
75
- echo " gpu_index_list passed to colmap: ${gpu_index_list}"
76
-
77
- # Bound CPU thread count too: num_threads=-1 (COLMAP's default) auto-detects
78
- # via APIs that on cgroup-limited HPC nodes often report the physical node's
79
- # total core count rather than what's actually allocated to this job. `nproc`
80
- # (not `nproc --all`) reports the affinity-restricted count instead, so it
81
- # respects whatever the scheduler's cgroup actually granted.
82
- num_threads=$(nproc)
83
- echo " num_threads: ${num_threads}"
84
-
85
- # Get calibration model and parameters
86
- read -r calibration_model params <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
87
-
88
- case "${calibration_model}" in
89
- unknown)
90
- colmap_camera_model="OPENCV"
91
- camera_params=""
92
- ;;
93
- pinhole)
94
- colmap_camera_model="PINHOLE"
95
- camera_params="${params// /,}"
96
- ;;
97
- radtan4)
98
- colmap_camera_model="OPENCV"
99
- camera_params="${params// /,}"
100
- ;;
101
- radtan5)
102
- colmap_camera_model="FULL_OPENCV"
103
- camera_params="${params// /,},0,0,0"
104
- ;;
105
- equid4)
106
- colmap_camera_model="OPENCV_FISHEYE"
107
- camera_params="${params// /,}"
108
- ;;
109
- *)
110
- echo "Unknown calibration_model: ${calibration_model}"
111
- exit 1
112
- ;;
113
- esac
114
 
115
  # Create colmap image list
116
  colmap_image_list="${exp_folder_colmap}/colmap_image_list.txt"
@@ -122,38 +29,95 @@ rm -rf ${database}
122
  colmap database_creator --database_path ${database}
123
 
124
  # Feature extractor
125
- echo " colmap feature_extractor (${feature_extraction_type}) ..."
126
- echo " gpu_index: ${gpu_index_list}"
127
- echo " camera model : ${calibration_model} (colmap: ${colmap_camera_model})"
128
- [ -n "${camera_params}" ] && echo " camera params: ${camera_params}"
129
-
130
- camera_params_args=()
131
- [ -n "${camera_params}" ] && camera_params_args=(--ImageReader.camera_params "${camera_params}")
132
 
 
 
 
133
  colmap feature_extractor \
134
- --database_path ${database} \
135
- --image_path ${rgb_path} \
136
- --image_list_path ${colmap_image_list} \
137
- --ImageReader.camera_model "${colmap_camera_model}" \
138
- --ImageReader.single_camera 1 \
139
- --ImageReader.single_camera_per_folder 1 \
140
- --FeatureExtraction.type ${feature_extraction_type} \
141
- --FeatureExtraction.use_gpu ${use_gpu} \
142
- --FeatureExtraction.gpu_index "${gpu_index_list}" \
143
- --FeatureExtraction.num_threads "${num_threads}" \
144
- "${camera_params_args[@]}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
  # Exhaustive Feature Matcher
147
- if [ "${matcher_type}" == "exhaustive" ];
148
  then
149
- echo " colmap exhaustive_matcher (${feature_matching_type}) ..."
150
- echo " gpu_index: ${gpu_index_list}"
151
  colmap exhaustive_matcher \
152
- --database_path "${database}" \
153
- --FeatureMatching.type "${feature_matching_type}" \
154
- --FeatureMatching.use_gpu "${use_gpu}" \
155
- --FeatureMatching.gpu_index "${gpu_index_list}" \
156
- --FeatureMatching.num_threads "${num_threads}"
157
  fi
158
 
159
  # Sequential Feature Matcher
@@ -162,23 +126,30 @@ then
162
  num_rgb=$(( $(wc -l < "$rgb_csv") - 1 ))
163
 
164
  # Pick vocabulary tree based on the number of images
165
- vocabulary_tree="Baselines/colmap/vocab_tree_flickr100K_words32K.bin"
166
  if [ "$num_rgb" -gt 1000 ]; then
167
- vocabulary_tree="Baselines/colmap/vocab_tree_flickr100K_words256K.bin"
168
  fi
169
  if [ "$num_rgb" -gt 10000 ]; then
170
- vocabulary_tree="Baselines/colmap/vocab_tree_flickr100K_words1M.bin"
171
  fi
172
 
173
- echo " colmap sequential_matcher (${feature_matching_type}) ..."
174
  echo " Vocabulary Tree: $vocabulary_tree"
175
- echo " gpu_index: ${gpu_index_list}"
176
  colmap sequential_matcher \
177
  --database_path "${database}" \
178
  --SequentialMatching.loop_detection 1 \
179
  --SequentialMatching.vocab_tree_path ${vocabulary_tree} \
180
- --FeatureMatching.type "${feature_matching_type}" \
181
- --FeatureMatching.use_gpu "${use_gpu}" \
182
- --FeatureMatching.gpu_index "${gpu_index_list}" \
183
- --FeatureMatching.num_threads "${num_threads}"
184
- fi
 
 
 
 
 
 
 
 
 
11
  matcher_type="$7"
12
  use_gpu="$8"
13
  camera_name="$9"
 
14
 
15
  exp_folder_colmap="${exp_folder}/colmap_${exp_id}"
16
  rgb_dir=$(awk -F, 'NR==2 { split($2,a,"/"); print a[1]; exit }' "$rgb_csv")
17
  rgb_path="${sequence_path}/${rgb_dir}"
18
 
19
+ # Get calibration model
20
+ read -r calibration_model more_ <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  # Create colmap image list
23
  colmap_image_list="${exp_folder_colmap}/colmap_image_list.txt"
 
29
  colmap database_creator --database_path ${database}
30
 
31
  # Feature extractor
32
+ echo " colmap feature_extractor ..."
 
 
 
 
 
 
33
 
34
+ if [ "${calibration_model}" == "unknown" ]
35
+ then
36
+ echo " camera model : $calibration_model"
37
  colmap feature_extractor \
38
+ --database_path ${database} \
39
+ --image_path ${rgb_path} \
40
+ --image_list_path ${colmap_image_list} \
41
+ --ImageReader.camera_model SIMPLE_PINHOLE \
42
+ --ImageReader.single_camera 1 \
43
+ --ImageReader.single_camera_per_folder 1 \
44
+ --FeatureExtraction.use_gpu ${use_gpu}
45
+ fi
46
+
47
+ if [ "${calibration_model}" == "pinhole" ]
48
+ then
49
+ read -r calibration_model fx fy cx cy <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
50
+ echo " camera model : $calibration_model"
51
+ echo " fx: $fx , fy: $fy , cx: $cx , cy: $cy"
52
+ colmap feature_extractor \
53
+ --database_path ${database} \
54
+ --image_path ${rgb_path} \
55
+ --image_list_path ${colmap_image_list} \
56
+ --ImageReader.camera_model PINHOLE \
57
+ --ImageReader.single_camera 1 \
58
+ --ImageReader.single_camera_per_folder 1 \
59
+ --FeatureExtraction.use_gpu ${use_gpu} \
60
+ --ImageReader.camera_params "${fx},${fy},${cx},${cy}"
61
+ fi
62
+
63
+ if [ "${calibration_model}" == "radtan4" ]
64
+ then
65
+ read -r calibration_model fx fy cx cy k1 k2 p1 p2 <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
66
+ echo " camera model : $calibration_model"
67
+ echo " fx: $fx , fy: $fy , cx: $cx , cy: $cy"
68
+ echo " k1: $k1 , k2: $k2 , p1: $p1 , p2: $p2"
69
+ colmap feature_extractor \
70
+ --database_path ${database} \
71
+ --image_path ${rgb_path} \
72
+ --image_list_path ${colmap_image_list} \
73
+ --ImageReader.camera_model "OPENCV" \
74
+ --ImageReader.single_camera 1 \
75
+ --ImageReader.single_camera_per_folder 0 \
76
+ --FeatureExtraction.use_gpu ${use_gpu} \
77
+ --ImageReader.camera_params "${fx},${fy},${cx},${cy},${k1},${k2},${p1},${p2}"
78
+ fi
79
+
80
+ if [ "${calibration_model}" == "radtan5" ]
81
+ then
82
+ read -r calibration_model fx fy cx cy k1 k2 p1 p2 k3 <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
83
+ echo " camera model : $calibration_model"
84
+ echo " fx: $fx , fy: $fy , cx: $cx , cy: $cy"
85
+ echo " k1: $k1 , k2: $k2 , p1: $p1 , p2: $p2, k3: $k3"
86
+ colmap feature_extractor \
87
+ --database_path ${database} \
88
+ --image_path ${rgb_path} \
89
+ --image_list_path ${colmap_image_list} \
90
+ --ImageReader.camera_model "FULL_OPENCV" \
91
+ --ImageReader.single_camera 1 \
92
+ --ImageReader.single_camera_per_folder 1 \
93
+ --FeatureExtraction.use_gpu ${use_gpu} \
94
+ --ImageReader.camera_params "${fx},${fy},${cx},${cy},${k1},${k2},${p1},${p2},${k3},0,0,0"
95
+ fi
96
+
97
+ if [ "${calibration_model}" == "equid4" ]
98
+ then
99
+ read -r calibration_model fx fy cx cy k1 k2 k3 k4 <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
100
+ echo " camera model : $calibration_model"
101
+ echo " fx: $fx , fy: $fy , cx: $cx , cy: $cy"
102
+ echo " k1: $k1 , k2: $k2 , k3: $k3 , k4: $k4"
103
+ colmap feature_extractor \
104
+ --database_path ${database} \
105
+ --image_path ${rgb_path} \
106
+ --image_list_path ${colmap_image_list} \
107
+ --ImageReader.camera_model "OPENCV_FISHEYE"\
108
+ --ImageReader.single_camera 1 \
109
+ --ImageReader.single_camera_per_folder 1 \
110
+ --FeatureExtraction.use_gpu ${use_gpu} \
111
+ --ImageReader.camera_params "${fx},${fy},${cx},${cy},${k1},${k2},${k3},${k4}"
112
+ fi
113
 
114
  # Exhaustive Feature Matcher
115
+ if [ "${matcher_type}" == "exhaustive" ]
116
  then
117
+ echo " colmap exhaustive_matcher ..."
 
118
  colmap exhaustive_matcher \
119
+ --database_path ${database} \
120
+ --FeatureMatching.use_gpu ${use_gpu}
 
 
 
121
  fi
122
 
123
  # Sequential Feature Matcher
 
126
  num_rgb=$(( $(wc -l < "$rgb_csv") - 1 ))
127
 
128
  # Pick vocabulary tree based on the number of images
129
+ vocabulary_tree="Baselines/colmap/vocab_tree_faiss_flickr100K_words32K.bin"
130
  if [ "$num_rgb" -gt 1000 ]; then
131
+ vocabulary_tree="Baselines/colmap/vocab_tree_faiss_flickr100K_words256K.bin"
132
  fi
133
  if [ "$num_rgb" -gt 10000 ]; then
134
+ vocabulary_tree="Baselines/colmap/vocab_tree_faiss_flickr100K_words1M.bin"
135
  fi
136
 
137
+ echo " colmap sequential_matcher ..."
138
  echo " Vocabulary Tree: $vocabulary_tree"
 
139
  colmap sequential_matcher \
140
  --database_path "${database}" \
141
  --SequentialMatching.loop_detection 1 \
142
  --SequentialMatching.vocab_tree_path ${vocabulary_tree} \
143
+ --FeatureMatching.use_gpu "${use_gpu}"
144
+ fi
145
+
146
+ # LightGlue Feature Matcher
147
+ if [ "${matcher_type}" == "custom" ]
148
+ then
149
+ colmap exhaustive_matcher \
150
+ --database_path ${database} \
151
+ --FeatureMatching.use_gpu ${use_gpu}
152
+
153
+ pixi run -e lightglue python3 Baselines/colmap/feature_matcher.py --database ${database} --rgb_path ${rgb_path} --rgb_csv ${rgb_csv}
154
+ fi
155
+
colmap_reconstruction.sh CHANGED
@@ -2,8 +2,6 @@
2
 
3
  # Default values
4
  matcher_type="exhaustive"
5
- matching_type="sift_bruteforce"
6
- mapper_type="colmap"
7
  use_gpu="1"
8
  verbose="0"
9
  settings_yaml=""
@@ -35,8 +33,6 @@ echo " Experiment Folder : $exp_folder"
35
  echo " Experiment ID : $exp_id"
36
  echo " Verbose : $verbose"
37
  echo " Matcher Type : $matcher_type"
38
- echo " Matching Type : $matching_type"
39
- echo " Mapper Type : $mapper_type"
40
  echo " Use GPU : $use_gpu"
41
  echo " Settings YAML : $settings_yaml"
42
  echo " Calibration YAML : $calibration_yaml"
@@ -52,8 +48,8 @@ mkdir "$exp_folder_colmap"
52
  # Run COLMAP scripts for matching and mapping
53
  export QT_QPA_PLATFORM_PLUGIN_PATH="$CONDA_PREFIX/plugins/platforms"
54
  colmap_args="$sequence_path $exp_folder $exp_id $settings_yaml $calibration_yaml $rgb_csv"
55
- ./Baselines/colmap/colmap_matcher.sh $colmap_args $matcher_type $use_gpu $camera_name $matching_type
56
- ./Baselines/colmap/colmap_mapper.sh $colmap_args $camera_name $mapper_type
57
 
58
  # Convert COLMAP outputs to a format suitable for VSLAM-LAB
59
  python Baselines/colmap/colmap_to_vslamlab.py $sequence_path $exp_folder $exp_id $verbose $rgb_csv $camera_name
@@ -68,4 +64,6 @@ if [ "$verbose" -eq 1 ]; then
68
  fi
69
 
70
  # # Remove colmap data
71
- # rm -rf ${exp_folder_colmap}
 
 
 
2
 
3
  # Default values
4
  matcher_type="exhaustive"
 
 
5
  use_gpu="1"
6
  verbose="0"
7
  settings_yaml=""
 
33
  echo " Experiment ID : $exp_id"
34
  echo " Verbose : $verbose"
35
  echo " Matcher Type : $matcher_type"
 
 
36
  echo " Use GPU : $use_gpu"
37
  echo " Settings YAML : $settings_yaml"
38
  echo " Calibration YAML : $calibration_yaml"
 
48
  # Run COLMAP scripts for matching and mapping
49
  export QT_QPA_PLATFORM_PLUGIN_PATH="$CONDA_PREFIX/plugins/platforms"
50
  colmap_args="$sequence_path $exp_folder $exp_id $settings_yaml $calibration_yaml $rgb_csv"
51
+ ./Baselines/colmap/colmap_matcher.sh $colmap_args $matcher_type $use_gpu $camera_name
52
+ ./Baselines/colmap/colmap_mapper.sh $colmap_args $camera_name
53
 
54
  # Convert COLMAP outputs to a format suitable for VSLAM-LAB
55
  python Baselines/colmap/colmap_to_vslamlab.py $sequence_path $exp_folder $exp_id $verbose $rgb_csv $camera_name
 
64
  fi
65
 
66
  # # Remove colmap data
67
+ # rm -rf ${exp_folder_colmap}
68
+
69
+