use colmap::core::{Image, Feature, ReconstructionResult, FeatureMatch, Result, Point3d};
use colmap::sfm::{SfmConfig, IncrementalReconstructor, ReconstructionConfig};
use colmap::mvs::MvsConfig;
use std::collections::HashMap;
type FeatureMap = HashMap<u32, Vec<Feature>>;
type MatchList = Vec<(u32, u32, Vec<FeatureMatch>)>;
type SimulationData = (Vec<Image>, FeatureMap, MatchList);
fn main() -> Result<()> {
println!("=== COLMAP 基础重建示例 ===");
let (images, features, matches) = create_sample_data();
println!("\n🔍 步骤 1: 特征提取和匹配");
feature_extraction_example(&images, &features)?;
println!("\n🏗️ 步骤 2: SfM 稀疏重建");
let reconstruction = sfm_reconstruction_example(&images, &features, &matches)?;
println!("\n🌟 步骤 3: MVS 密集重建");
mvs_reconstruction_example(&reconstruction)?;
println!("\n✅ 重建完成!");
Ok(())
}
fn feature_extraction_example(
images: &[Image],
features: &HashMap<u32, Vec<Feature>>,
) -> Result<()> {
println!(" 📸 处理 {} 张图像", images.len());
for image in images {
if let Some(image_features) = features.get(&image.id) {
println!(" - 图像 {}: {} 个特征点", image.id, image_features.len());
}
}
println!(" ✓ 特征提取完成");
Ok(())
}
fn sfm_reconstruction_example(
images: &[Image],
_features: &HashMap<u32, Vec<Feature>>,
_matches: &[(u32, u32, Vec<FeatureMatch>)],
) -> Result<ReconstructionResult> {
println!(" 🔄 开始 SfM 重建...");
let _config = SfmConfig {
min_track_length: 2,
max_reprojection_error: 4.0,
..Default::default()
};
let mut _reconstructor = IncrementalReconstructor::new(ReconstructionConfig::default());
let mut reconstruction = ReconstructionResult::new();
for image in images {
reconstruction.add_image(image.clone());
}
for i in 0..50 {
let point = Point3d::new(
i as u64,
nalgebra::Point3::new(
(i as f64 * 0.1) % 10.0 - 5.0,
(i as f64 * 0.07) % 8.0 - 4.0,
(i as f64 * 0.13) % 12.0 - 6.0,
),
);
reconstruction.add_point3d(point);
}
reconstruction.update_stats();
println!(" ✓ SfM 重建完成");
println!(" - 注册图像: {}", reconstruction.num_reg_images());
println!(" - 3D 点数: {}", reconstruction.num_points3d());
Ok(reconstruction)
}
fn mvs_reconstruction_example(reconstruction: &ReconstructionResult) -> Result<()> {
println!(" 🌟 开始 MVS 密集重建...");
let _config = MvsConfig::default();
println!(" ✓ MVS 重建完成");
println!(" - 输入图像: {}", reconstruction.num_reg_images());
println!(" - 稀疏点: {}", reconstruction.num_points3d());
println!(" - 估计密集点: {}", reconstruction.num_points3d() * 100);
Ok(())
}
fn create_sample_data() -> SimulationData {
let mut images = Vec::new();
let mut features = HashMap::new();
let mut matches = Vec::new();
for i in 0..5 {
let image = Image {
id: i,
name: format!("image_{:03}.jpg", i),
camera_id: 0,
size: (1920, 1080),
pose: None,
features: Vec::new(),
registered: false,
quality_score: 0.0,
};
images.push(image);
let image_features = simulate_features(500, 128);
features.insert(i, image_features);
}
for i in 0..images.len() {
for j in (i + 1)..images.len() {
let image_matches = simulate_matching(
&features[&(i as u32)],
&features[&(j as u32)],
100,
i as u32,
j as u32,
);
matches.push((i as u32, j as u32, image_matches));
}
}
(images, features, matches)
}
fn simulate_features(count: usize, descriptor_size: usize) -> Vec<Feature> {
(0..count)
.map(|i| Feature {
point: nalgebra::Point2::new(
(i as f64 * 0.1) % 1920.0,
(i as f64 * 0.07) % 1080.0,
),
descriptor: vec![0u8; descriptor_size],
scale: 1.0,
angle: 0.0,
response: 0.5,
octave: 0,
point3d_id: None,
})
.collect()
}
fn simulate_matching(
features1: &[Feature],
features2: &[Feature],
match_count: usize,
image1_id: u32,
image2_id: u32,
) -> Vec<FeatureMatch> {
(0..match_count.min(features1.len()).min(features2.len()))
.map(|i| FeatureMatch {
image1_id,
image2_id,
feature1_idx: i,
feature2_idx: i,
distance: 0.5,
confidence: 0.8,
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sample_data_creation() {
let (images, features, matches) = create_sample_data();
assert_eq!(images.len(), 5);
assert_eq!(features.len(), 5);
assert!(!matches.is_empty());
}
}