colmap-rs/examples/full_pipeline.rs

90 lines
3.2 KiB
Rust

//! Full feature → SfM → MVS → export pipeline, using the flat high-level API.
//!
//! This is the example from the high-level `colmap` crate, running verbatim
//! against this crate. The numerical core is the built-in synthetic-scene demo
//! (see `colmap::highlevel`), so it runs end to end and writes real output files
//! even though the geometry is illustrative rather than recovered from pixels.
//!
//! ```text
//! cargo run --example full_pipeline -- /path/to/images
//! ```
use colmap::*;
use std::path::{Path, PathBuf};
fn reconstruct_from_images(image_dir: &Path) -> Result<()> {
// 1. Load images (headers only).
let images = load_images_from_directory(image_dir)?;
// 2. Feature extraction and matching.
let feature_config = PipelineConfig {
detector_type: DetectorType::Sift,
max_features: 8000,
..Default::default()
};
let pipeline = FeaturePipeline::new(feature_config);
let extraction_result = pipeline.extract_and_match_all(&images)?;
println!("Extracted features for {} images", extraction_result.features.len());
println!("Found {} match pairs", extraction_result.matches.len());
// 3. Sparse SfM reconstruction.
let sfm_config = SfmConfig {
min_track_length: 2,
max_reprojection_error: 4.0,
..Default::default()
};
let mut sfm_reconstructor = IncrementalSfm::new(sfm_config);
sfm_reconstructor.set_features(extraction_result.features);
sfm_reconstructor.set_matches(extraction_result.matches);
let sparse_reconstruction = sfm_reconstructor.reconstruct()?;
println!("Sparse reconstruction:");
println!(" - registered images: {}", sparse_reconstruction.registered_images());
println!(" - 3D points: {}", sparse_reconstruction.points.len());
println!(
" - mean reprojection error: {:.2}",
sparse_reconstruction.mean_reprojection_error()
);
// 4. Dense MVS reconstruction.
let mvs_config = MvsConfig {
min_num_views: 3,
max_image_size: 1600,
depth_range: (0.1, 100.0),
..Default::default()
};
let mvs_reconstructor = MvsReconstructor::new(mvs_config);
let views = prepare_views_from_reconstruction(&sparse_reconstruction)?;
let dense_reconstruction = mvs_reconstructor.reconstruct(&views)?;
println!("Dense reconstruction:");
println!(" - point cloud size: {}", dense_reconstruction.point_cloud.points.len());
println!(" - mesh triangles: {}", dense_reconstruction.mesh.triangles.len());
// 5. Save the results.
save_reconstruction(&sparse_reconstruction, "sparse_reconstruction")?;
save_point_cloud(&dense_reconstruction.point_cloud, "dense_point_cloud.ply")?;
save_mesh(&dense_reconstruction.mesh, "mesh.obj")?;
println!("Wrote sparse_reconstruction/, dense_point_cloud.ply, mesh.obj");
Ok(())
}
fn main() {
let image_dir: PathBuf = std::env::args()
.nth(1)
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/../images")));
println!("Reconstructing from {}", image_dir.display());
if let Err(err) = reconstruct_from_images(&image_dir) {
eprintln!("error: {err}");
std::process::exit(1);
}
}