use crate::core::Result;
pub mod stereo; pub mod depth; pub mod fusion; pub mod meshing;
pub use stereo::{
StereoMatcher, StereoMatchConfig, DisparityMap, DepthMap, StereoMatchResult,
RectificationParams,
};
pub use depth::{
DepthEstimator, DepthEstimationConfig, MultiViewDepthResult, NormalMap, CostMap,
ViewInfo, DepthHypothesis,
};
pub use fusion::{
PointCloudFusion, FusionConfig, FusedPoint, FusionResult, FusionStatistics,
DepthMapView,
};
pub use meshing::{
MeshReconstructor, MeshReconstructionConfig, ReconstructionAlgorithm,
TriangleMesh, Vertex, Triangle, MeshStatistics,
};
#[derive(Debug, Clone)]
pub struct MvsConfig {
pub stereo_config: StereoMatchConfig,
pub depth_config: DepthEstimationConfig,
pub fusion_config: FusionConfig,
pub mesh_config: MeshReconstructionConfig,
pub min_num_views: usize,
pub max_image_size: u32,
pub depth_range: (f32, f32),
}
#[derive(Debug, Clone)]
pub struct StereoConfig {
pub window_size: usize,
pub max_disparity: i32,
pub cost_threshold: f32,
}
impl Default for MvsConfig {
fn default() -> Self {
Self {
stereo_config: StereoMatchConfig::default(),
depth_config: DepthEstimationConfig::default(),
fusion_config: FusionConfig::default(),
mesh_config: MeshReconstructionConfig::default(),
min_num_views: 3,
max_image_size: 2048,
depth_range: (0.1, 100.0),
}
}
}
impl Default for StereoConfig {
fn default() -> Self {
Self {
window_size: 5,
max_disparity: 128,
cost_threshold: 0.1,
}
}
}
#[derive(Debug)]
pub struct MvsReconstructor {
config: MvsConfig,
stereo_matcher: StereoMatcher,
depth_estimator: DepthEstimator,
point_cloud_fusion: PointCloudFusion,
mesh_reconstructor: MeshReconstructor,
}
impl MvsReconstructor {
pub fn new(config: MvsConfig) -> Self {
let stereo_matcher = StereoMatcher::new(config.stereo_config.clone());
let depth_estimator = DepthEstimator::new(config.depth_config.clone());
let point_cloud_fusion = PointCloudFusion::new(config.fusion_config.clone());
let mesh_reconstructor = MeshReconstructor::new(config.mesh_config.clone());
Self {
config,
stereo_matcher,
depth_estimator,
point_cloud_fusion,
mesh_reconstructor,
}
}
pub fn reconstruct(
&self,
views: &[ViewInfo],
) -> Result<MvsReconstructionResult> {
println!("Starting MVS reconstruction with {} views", views.len());
let mut depth_results = Vec::new();
for (i, reference_view) in views.iter().enumerate() {
println!("Processing view {}/{}", i + 1, views.len());
let source_views: Vec<ViewInfo> = views
.iter()
.enumerate()
.filter(|(j, _)| *j != i)
.map(|(_, view)| view.clone())
.collect();
if source_views.len() >= self.config.min_num_views - 1 {
let depth_result = self.depth_estimator.estimate_depth(
reference_view,
&source_views,
)?;
depth_results.push((i, depth_result));
}
}
println!("Generated {} depth maps", depth_results.len());
let mut depth_map_views = Vec::new();
for (view_idx, depth_result) in depth_results {
let view = &views[view_idx];
depth_map_views.push(DepthMapView {
depth_map: depth_result.depth_map,
normal_map: Some(depth_result.normal_map),
cost_map: Some(depth_result.cost_map),
image: view.image.clone(),
});
}
let fusion_result = self.point_cloud_fusion.fuse_depth_maps(&depth_map_views)?;
println!("Fused {} points", fusion_result.points.len());
let mesh = self.mesh_reconstructor.reconstruct_mesh(&fusion_result)?;
println!("Generated mesh with {} vertices and {} triangles",
mesh.vertices.len(), mesh.triangles.len());
Ok(MvsReconstructionResult {
point_cloud: fusion_result,
mesh,
depth_maps: depth_map_views,
})
}
}
#[derive(Debug)]
pub struct MvsReconstructionResult {
pub point_cloud: FusionResult,
pub mesh: TriangleMesh,
pub depth_maps: Vec<DepthMapView>,
}