colmap 0.1.2

A comprehensive Rust library for COLMAP-style computer vision and 3D reconstruction
Documentation
//! COLMAP 基础重建示例
//!
//! 这个示例演示了如何使用 COLMAP Rust 库进行基本的 3D 重建流程。

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();
    
    // 步骤 1: 特征提取和匹配
    println!("\n🔍 步骤 1: 特征提取和匹配");
    feature_extraction_example(&images, &features)?;
    
    // 步骤 2: SfM 稀疏重建
    println!("\n🏗️ 步骤 2: SfM 稀疏重建");
    let reconstruction = sfm_reconstruction_example(&images, &features, &matches)?;
    
    // 步骤 3: MVS 密集重建
    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(())
}

/// SfM 重建示例
fn sfm_reconstruction_example(
    images: &[Image],
    _features: &HashMap<u32, Vec<Feature>>,
    _matches: &[(u32, u32, Vec<FeatureMatch>)],
) -> Result<ReconstructionResult> {
    println!("  🔄 开始 SfM 重建...");
    
    // 创建 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());
    }
    
    // 模拟添加一些 3D 点
    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)
}

/// MVS 重建示例
fn mvs_reconstruction_example(reconstruction: &ReconstructionResult) -> Result<()> {
    println!("  🌟 开始 MVS 密集重建...");
    
    // 创建 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());
    }
}