colmap 0.1.2

A comprehensive Rust library for COLMAP-style computer vision and 3D reconstruction
Documentation
//! COLMAP 特征提取和匹配示例
//!
//! 这个示例演示了如何使用 COLMAP Rust 库进行特征提取和匹配。

use colmap::core::{Image, Feature, Result, FeatureMatch};
use colmap::feature::{FeatureConfig, MatchConfig};
use std::collections::HashMap;

fn main() -> Result<()> {
    println!("=== COLMAP 特征匹配示例 ===");
    
    // 创建示例图像数据
    let images = create_sample_images();
    
    // SIFT 特征提取示例
    println!("\n🔍 SIFT 特征提取示例");
    sift_feature_extraction(&images)?;
    
    // ORB 特征提取示例
    println!("\n🎯 ORB 特征提取示例");
    orb_feature_extraction(&images)?;
    
    // 特征匹配示例
    println!("\n🔗 特征匹配示例");
    feature_matching_example(&images)?;
    
    println!("\n✅ 特征处理完成!");
    Ok(())
}

/// SIFT 特征提取示例
fn sift_feature_extraction(images: &[Image]) -> Result<()> {
    println!("  📸 使用 SIFT 检测器处理 {} 张图像", images.len());
    
    let _config = FeatureConfig {
        max_features: 2000,
        quality_threshold: 0.01,
        ..Default::default()
    };
    
    for image in images {
        // 模拟 SIFT 特征提取
        let features = simulate_sift_features(image, 1500);
        println!("    - 图像 {}: {} 个 SIFT 特征", image.id, features.len());
    }
    
    println!("  ✓ SIFT 特征提取完成");
    Ok(())
}

/// ORB 特征提取示例
fn orb_feature_extraction(images: &[Image]) -> Result<()> {
    println!("  🎯 使用 ORB 检测器处理 {} 张图像", images.len());
    
    let _config = FeatureConfig {
        max_features: 1000,
        quality_threshold: 0.02,
        ..Default::default()
    };
    
    for image in images {
        // 模拟 ORB 特征提取
        let features = simulate_orb_features(image, 800);
        println!("    - 图像 {}: {} 个 ORB 特征", image.id, features.len());
    }
    
    println!("  ✓ ORB 特征提取完成");
    Ok(())
}

/// 特征匹配示例
fn feature_matching_example(images: &[Image]) -> Result<()> {
    println!("  🔗 执行特征匹配...");
    
    // 为每个图像生成特征
    let mut all_features = HashMap::new();
    for image in images {
        let features = simulate_sift_features(image, 1000);
        all_features.insert(image.id, features);
    }
    
    let _config = MatchConfig {
        max_distance: 0.8,
        cross_check: true,
        ..Default::default()
    };
    
    let mut total_matches = 0;
    
    // 执行图像对匹配
    for i in 0..images.len() {
        for j in (i + 1)..images.len() {
            let image1_id = images[i].id;
            let image2_id = images[j].id;
            
            let features1 = &all_features[&image1_id];
            let features2 = &all_features[&image2_id];
            
            // 模拟特征匹配
            let matches = simulate_feature_matching(features1, features2, 150, image1_id, image2_id);
            total_matches += matches.len();
            
            println!("    - 图像 {} <-> {}: {} 个匹配", image1_id, image2_id, matches.len());
        }
    }
    
    println!("  ✓ 特征匹配完成,总匹配数: {}", total_matches);
    Ok(())
}

/// 创建示例图像
fn create_sample_images() -> Vec<Image> {
    (0..4)
        .map(|i| 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,
        })
        .collect()
}

/// 模拟 SIFT 特征提取
fn simulate_sift_features(image: &Image, count: usize) -> Vec<Feature> {
    (0..count)
        .map(|i| Feature {
            point: nalgebra::Point2::new(
                (i as f64 * 0.1 + image.id as f64 * 100.0) % image.size.0 as f64,
                (i as f64 * 0.07 + image.id as f64 * 50.0) % image.size.1 as f64,
            ),
            descriptor: vec![((i * 17 + image.id as usize * 23) % 256) as u8; 128],
            scale: 1.0,
            angle: 0.0,
            response: 0.5,
            octave: 0,
            point3d_id: None,
        })
        .collect()
}

/// 模拟 ORB 特征提取
fn simulate_orb_features(image: &Image, count: usize) -> Vec<Feature> {
    (0..count)
        .map(|i| Feature {
            point: nalgebra::Point2::new(
                (i as f64 * 0.13 + image.id as f64 * 80.0) % image.size.0 as f64,
                (i as f64 * 0.11 + image.id as f64 * 60.0) % image.size.1 as f64,
            ),
            descriptor: vec![((i * 19 + image.id as usize * 31) % 256) as u8; 32],
            scale: 1.0,
            angle: 0.0,
            response: 0.5,
            octave: 0,
            point3d_id: None,
        })
        .collect()
}

/// 模拟特征匹配
fn simulate_feature_matching(
    features1: &[Feature],
    features2: &[Feature],
    max_matches: usize,
    image1_id: u32,
    image2_id: u32,
) -> Vec<FeatureMatch> {
    let actual_matches = max_matches.min(features1.len()).min(features2.len());
    
    (0..actual_matches)
        .map(|i| FeatureMatch {
            image1_id,
            image2_id,
            feature1_idx: i,
            feature2_idx: i,
            distance: 0.3 + (i as f32 * 0.001) % 0.4,
            confidence: 0.8 - (i as f32 * 0.001),
        })
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_sample_images_creation() {
        let images = create_sample_images();
        assert_eq!(images.len(), 4);
        
        for (i, image) in images.iter().enumerate() {
            assert_eq!(image.id, i as u32);
            assert_eq!(image.size.0, 1920);
            assert_eq!(image.size.1, 1080);
        }
    }
    
    #[test]
    fn test_sift_features_simulation() {
        let image = Image {
            id: 0,
            name: "test.jpg".to_string(),
            camera_id: 0,
            size: (640, 480),
            pose: None,
            features: Vec::new(),
            registered: false,
            quality_score: 0.0,
        };
        
        let features = simulate_sift_features(&image, 100);
        assert_eq!(features.len(), 100);
        assert_eq!(features[0].descriptor.len(), 128);
    }
    
    #[test]
    fn test_orb_features_simulation() {
        let image = Image {
            id: 1,
            name: "test.jpg".to_string(),
            camera_id: 0,
            size: (640, 480),
            pose: None,
            features: Vec::new(),
            registered: false,
            quality_score: 0.0,
        };
        
        let features = simulate_orb_features(&image, 50);
        assert_eq!(features.len(), 50);
        assert_eq!(features[0].descriptor.len(), 32);
    }
    
    #[test]
    fn test_feature_matching_simulation() {
        let features1 = vec![
            Feature {
                point: nalgebra::Point2::new(100.0, 100.0),
                descriptor: vec![0u8; 128],
                scale: 1.0,
                angle: 0.0,
                response: 0.5,
                octave: 0,
                point3d_id: None,
            },
            Feature {
                point: nalgebra::Point2::new(200.0, 200.0),
                descriptor: vec![1u8; 128],
                scale: 1.0,
                angle: 0.0,
                response: 0.5,
                octave: 0,
                point3d_id: None,
            },
        ];
        
        let features2 = vec![
            Feature {
                point: nalgebra::Point2::new(105.0, 105.0),
                descriptor: vec![0u8; 128],
                scale: 1.0,
                angle: 0.0,
                response: 0.5,
                octave: 0,
                point3d_id: None,
            },
            Feature {
                point: nalgebra::Point2::new(205.0, 205.0),
                descriptor: vec![1u8; 128],
                scale: 1.0,
                angle: 0.0,
                response: 0.5,
                octave: 0,
                point3d_id: None,
            },
        ];
        
        let matches = simulate_feature_matching(&features1, &features2, 10, 0, 1);
        assert_eq!(matches.len(), 2);
        assert!(matches[0].distance >= 0.3 && matches[0].distance <= 0.7);
    }
}