vslamlab commited on
Commit
8c7a4fa
·
verified ·
1 Parent(s): e8ace62

Upload folder using huggingface_hub

Browse files
Files changed (4) hide show
  1. colmap_mapper.sh +36 -14
  2. colmap_matcher.sh +97 -104
  3. colmap_reconstruction.sh +7 -7
  4. detect_gpus.sh +45 -0
colmap_mapper.sh CHANGED
@@ -1,18 +1,22 @@
1
  #!/bin/bash
2
  echo "Executing colmap_mapper.sh ..."
3
 
4
- sequence_path="$1"
5
- exp_folder="$2"
6
- exp_id="$3"
7
  settings_yaml="$4"
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}"
14
  rgb_path="${sequence_path}/${rgb_dir}"
15
 
 
 
 
16
  read -r calibration_model more_ <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
17
  echo " camera model : $calibration_model"
18
  ba_refine_focal_length="0"
@@ -25,19 +29,37 @@ then
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
-
 
1
  #!/bin/bash
2
  echo "Executing colmap_mapper.sh ..."
3
 
4
+ sequence_path="$1"
5
+ exp_folder="$2"
6
+ exp_id="$3"
7
  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}"
15
  rgb_path="${sequence_path}/${rgb_dir}"
16
 
17
+ # Sets use_gpu, gpu_index_list, num_threads
18
+ source "$(dirname "$0")/detect_gpus.sh"
19
+
20
  read -r calibration_model more_ <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
21
  echo " camera model : $calibration_model"
22
  ba_refine_focal_length="0"
 
29
  ba_refine_extra_params="1"
30
  fi
31
 
 
32
  database="${exp_folder_colmap}/colmap_database.db"
33
 
34
+ if [ "${mapper_type}" == "glomap" ]
35
+ then
36
+ echo " global mapper (GLOMAP) ..."
37
+ colmap global_mapper \
38
+ --database_path ${database} \
39
+ --image_path ${rgb_path} \
40
+ --output_path ${exp_folder_colmap} \
41
+ --GlobalMapper.ba_refine_focal_length ${ba_refine_focal_length} \
42
+ --GlobalMapper.ba_refine_principal_point ${ba_refine_principal_point} \
43
+ --GlobalMapper.ba_refine_extra_params ${ba_refine_extra_params} \
44
+ --GlobalMapper.ba_ceres_use_gpu ${use_gpu} \
45
+ --GlobalMapper.ba_ceres_gpu_index "${gpu_index_list}" \
46
+ --GlobalMapper.gp_use_gpu ${use_gpu} \
47
+ --GlobalMapper.gp_gpu_index "${gpu_index_list}" \
48
+ --GlobalMapper.num_threads "${num_threads}"
49
+ else
50
+ echo " colmap mapper (COLMAP) ..."
51
+ colmap mapper \
52
+ --database_path ${database} \
53
+ --image_path ${rgb_path} \
54
+ --output_path ${exp_folder_colmap} \
55
+ --Mapper.ba_refine_focal_length ${ba_refine_focal_length} \
56
+ --Mapper.ba_refine_principal_point ${ba_refine_principal_point} \
57
+ --Mapper.ba_refine_extra_params ${ba_refine_extra_params} \
58
+ --Mapper.ba_use_gpu ${use_gpu} \
59
+ --Mapper.ba_gpu_index "${gpu_index_list}" \
60
+ --Mapper.num_threads "${num_threads}"
61
+ fi
62
 
63
  echo " colmap model_converter ..."
64
  colmap model_converter \
65
+ --input_path ${exp_folder_colmap}/0 --output_path ${exp_folder_colmap} --output_type TXT
 
 
colmap_matcher.sh CHANGED
@@ -3,21 +3,78 @@ echo ""
3
  echo "Executing colmap_matcher.sh ..."
4
 
5
  sequence_path="$1"
6
- exp_folder="$2"
7
- exp_id="$3"
8
  settings_yaml="$4"
9
  calibration_yaml="$5"
10
  rgb_csv="$6"
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"
@@ -26,98 +83,41 @@ python3 Baselines/colmap/create_colmap_image_list.py "$rgb_csv" "$colmap_image_l
26
  # Create Colmap Database
27
  database="${exp_folder_colmap}/colmap_database.db"
28
  rm -rf ${database}
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 1 \
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
@@ -134,22 +134,15 @@ then
134
  vocabulary_tree="Baselines/colmap/vocab_tree_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
-
 
3
  echo "Executing colmap_matcher.sh ..."
4
 
5
  sequence_path="$1"
6
+ exp_folder="$2"
7
+ exp_id="$3"
8
  settings_yaml="$4"
9
  calibration_yaml="$5"
10
  rgb_csv="$6"
11
  matcher_type="$7"
12
+ camera_name="$8"
13
+ matching_type="$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
+ # matching_type: FeatureExtraction.type + FeatureMatching.type
20
+ feature_matching_type=""
21
+ feature_extraction_type="SIFT"
22
+
23
+ case "${matching_type}" in
24
+ sift_bruteforce)
25
+ feature_extraction_type="SIFT"
26
+ feature_matching_type="SIFT_BRUTEFORCE"
27
+ ;;
28
+ sift_lightglue)
29
+ feature_extraction_type="SIFT"
30
+ feature_matching_type="SIFT_LIGHTGLUE"
31
+ ;;
32
+ aliked_bruteforce)
33
+ feature_extraction_type="ALIKED_N16ROT"
34
+ feature_matching_type="ALIKED_BRUTEFORCE"
35
+ ;;
36
+ aliked_lightglue)
37
+ feature_extraction_type="ALIKED_N16ROT"
38
+ feature_matching_type="ALIKED_LIGHTGLUE"
39
+ ;;
40
+ *)
41
+ echo "Unknown matching_type: ${matching_type}"
42
+ exit 1
43
+ ;;
44
+ esac
45
+
46
+ # Sets use_gpu, gpu_index_list, num_threads
47
+ source "$(dirname "$0")/detect_gpus.sh"
48
+
49
+ # Get calibration model and parameters
50
+ read -r calibration_model params <<< $(python3 Baselines/colmap/get_calibration.py "$calibration_yaml" "$camera_name")
51
+
52
+ case "${calibration_model}" in
53
+ unknown)
54
+ colmap_camera_model="OPENCV"
55
+ camera_params=""
56
+ ;;
57
+ pinhole)
58
+ colmap_camera_model="PINHOLE"
59
+ camera_params="${params// /,}"
60
+ ;;
61
+ radtan4)
62
+ colmap_camera_model="OPENCV"
63
+ camera_params="${params// /,}"
64
+ ;;
65
+ radtan5)
66
+ colmap_camera_model="FULL_OPENCV"
67
+ camera_params="${params// /,},0,0,0"
68
+ ;;
69
+ equid4)
70
+ colmap_camera_model="OPENCV_FISHEYE"
71
+ camera_params="${params// /,}"
72
+ ;;
73
+ *)
74
+ echo "Unknown calibration_model: ${calibration_model}"
75
+ exit 1
76
+ ;;
77
+ esac
78
 
79
  # Create colmap image list
80
  colmap_image_list="${exp_folder_colmap}/colmap_image_list.txt"
 
83
  # Create Colmap Database
84
  database="${exp_folder_colmap}/colmap_database.db"
85
  rm -rf ${database}
86
+ colmap database_creator --database_path ${database}
87
 
88
  # Feature extractor
89
+ echo " colmap feature_extractor (${feature_extraction_type}) ..."
90
+ echo " gpu_index: ${gpu_index_list}"
91
+ echo " camera model : ${calibration_model} (colmap: ${colmap_camera_model})"
92
+ [ -n "${camera_params}" ] && echo " camera params: ${camera_params}"
93
 
94
+ camera_params_args=()
95
+ [ -n "${camera_params}" ] && camera_params_args=(--ImageReader.camera_params "${camera_params}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ colmap feature_extractor \
98
+ --database_path ${database} \
99
+ --image_path ${rgb_path} \
100
+ --image_list_path ${colmap_image_list} \
101
+ --ImageReader.camera_model "${colmap_camera_model}" \
102
+ --ImageReader.single_camera 1 \
103
+ --ImageReader.single_camera_per_folder 1 \
104
+ --FeatureExtraction.type ${feature_extraction_type} \
105
+ --FeatureExtraction.use_gpu ${use_gpu} \
106
+ --FeatureExtraction.gpu_index "${gpu_index_list}" \
107
+ --FeatureExtraction.num_threads "${num_threads}" \
108
+ "${camera_params_args[@]}"
 
 
 
 
109
 
110
  # Exhaustive Feature Matcher
111
+ if [ "${matcher_type}" == "exhaustive" ];
112
  then
113
+ echo " colmap exhaustive_matcher (${feature_matching_type}) ..."
114
+ echo " gpu_index: ${gpu_index_list}"
115
  colmap exhaustive_matcher \
116
+ --database_path "${database}" \
117
+ --FeatureMatching.type "${feature_matching_type}" \
118
+ --FeatureMatching.use_gpu "${use_gpu}" \
119
+ --FeatureMatching.gpu_index "${gpu_index_list}" \
120
+ --FeatureMatching.num_threads "${num_threads}"
121
  fi
122
 
123
  # Sequential Feature Matcher
 
134
  vocabulary_tree="Baselines/colmap/vocab_tree_flickr100K_words1M.bin"
135
  fi
136
 
137
+ echo " colmap sequential_matcher (${feature_matching_type}) ..."
138
  echo " Vocabulary Tree: $vocabulary_tree"
139
+ echo " gpu_index: ${gpu_index_list}"
140
  colmap sequential_matcher \
141
  --database_path "${database}" \
142
  --SequentialMatching.loop_detection 1 \
143
  --SequentialMatching.vocab_tree_path ${vocabulary_tree} \
144
+ --FeatureMatching.type "${feature_matching_type}" \
145
+ --FeatureMatching.use_gpu "${use_gpu}" \
146
+ --FeatureMatching.gpu_index "${gpu_index_list}" \
147
+ --FeatureMatching.num_threads "${num_threads}"
148
+ fi
 
 
 
 
 
 
 
 
colmap_reconstruction.sh CHANGED
@@ -2,7 +2,8 @@
2
 
3
  # Default values
4
  matcher_type="exhaustive"
5
- use_gpu="1"
 
6
  verbose="0"
7
  settings_yaml=""
8
  sequence_path=""
@@ -33,7 +34,8 @@ echo " Experiment Folder : $exp_folder"
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"
39
  echo " RGB CSV : $rgb_csv"
@@ -48,8 +50,8 @@ mkdir "$exp_folder_colmap"
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,6 +66,4 @@ if [ "$verbose" -eq 1 ]; then
64
  fi
65
 
66
  # # Remove colmap data
67
- # rm -rf ${exp_folder_colmap}
68
-
69
-
 
2
 
3
  # Default values
4
  matcher_type="exhaustive"
5
+ matching_type="sift_bruteforce"
6
+ mapper_type="colmap"
7
  verbose="0"
8
  settings_yaml=""
9
  sequence_path=""
 
34
  echo " Experiment ID : $exp_id"
35
  echo " Verbose : $verbose"
36
  echo " Matcher Type : $matcher_type"
37
+ echo " Matching Type : $matching_type"
38
+ echo " Mapper Type : $mapper_type"
39
  echo " Settings YAML : $settings_yaml"
40
  echo " Calibration YAML : $calibration_yaml"
41
  echo " RGB CSV : $rgb_csv"
 
50
  # Run COLMAP scripts for matching and mapping
51
  export QT_QPA_PLATFORM_PLUGIN_PATH="$CONDA_PREFIX/plugins/platforms"
52
  colmap_args="$sequence_path $exp_folder $exp_id $settings_yaml $calibration_yaml $rgb_csv"
53
+ ./Baselines/colmap/colmap_matcher.sh $colmap_args $matcher_type $camera_name $matching_type
54
+ ./Baselines/colmap/colmap_mapper.sh $colmap_args $camera_name $mapper_type
55
 
56
  # Convert COLMAP outputs to a format suitable for VSLAM-LAB
57
  python Baselines/colmap/colmap_to_vslamlab.py $sequence_path $exp_folder $exp_id $verbose $rgb_csv $camera_name
 
66
  fi
67
 
68
  # # Remove colmap data
69
+ # rm -rf ${exp_folder_colmap}
 
 
detect_gpus.sh ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # Sourced by colmap_matcher.sh / colmap_mapper.sh (not executed directly).
3
+ # Sets: use_gpu (1 if any GPU detected, 0 otherwise), gpu_index_list
4
+ # (comma-separated ordinals for colmap's *_gpu_index options), num_threads.
5
+
6
+ # Detect usable GPUs: extraction/matching/mapping run as a single job across
7
+ # all of them, since COLMAP spawns one worker per listed GPU index and splits
8
+ # the per-image / per-block workload internally.
9
+ echo " detecting GPUs ..."
10
+ echo " nvidia-smi -L:"
11
+ nvidia-smi -L 2>&1 | sed 's/^/ /'
12
+ echo " nvidia-smi --query-gpu=index,name,uuid --format=csv:"
13
+ nvidia-smi --query-gpu=index,name,uuid --format=csv 2>&1 | sed 's/^/ /'
14
+ echo " CUDA_VISIBLE_DEVICES: ${CUDA_VISIBLE_DEVICES}"
15
+
16
+ if [ -n "${CUDA_VISIBLE_DEVICES}" ]; then
17
+ # The scheduler already restricted this job to a specific device set (often
18
+ # MIG slice UUIDs on HPC, which `nvidia-smi --query-gpu=index` does not
19
+ # enumerate - it lists the whole node's GPUs, not what's gated to this job).
20
+ # CUDA remaps whatever's listed here to ordinals 0..N-1 inside the process,
21
+ # and COLMAP's gpu_index just calls cudaSetDevice(ordinal), so address by
22
+ # ordinal count rather than trying to resolve real indices/UUIDs ourselves.
23
+ num_gpus=$(echo "${CUDA_VISIBLE_DEVICES}" | tr ',' '\n' | grep -c .)
24
+ gpu_ids=($(seq 0 $((num_gpus - 1))))
25
+ else
26
+ gpu_ids=($(nvidia-smi --query-gpu=index --format=csv,noheader 2>/dev/null))
27
+ fi
28
+
29
+ use_gpu="1"
30
+ if [ "${#gpu_ids[@]}" -lt 1 ]; then
31
+ use_gpu="0"
32
+ gpu_ids=(0)
33
+ fi
34
+ gpu_index_list=$(IFS=,; echo "${gpu_ids[*]}")
35
+ echo " use_gpu: ${use_gpu}"
36
+ echo " detected gpu_ids: ${gpu_ids[*]}"
37
+ echo " gpu_index_list passed to colmap: ${gpu_index_list}"
38
+
39
+ # Bound CPU thread count too: num_threads=-1 (COLMAP's default) auto-detects
40
+ # via APIs that on cgroup-limited HPC nodes often report the physical node's
41
+ # total core count rather than what's actually allocated to this job. `nproc`
42
+ # (not `nproc --all`) reports the affinity-restricted count instead, so it
43
+ # respects whatever the scheduler's cgroup actually granted.
44
+ num_threads=$(nproc)
45
+ echo " num_threads: ${num_threads}"