use scirs2_core::ndarray::Array2;
use crate::error::{Result, VisionError};
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum CompletionMethod {
NearestNeighbor,
BilateralGuided,
TotalVariation,
GuidedUpsampling,
InverseDistanceWeighted,
ConfidenceWeightedAverage,
KalmanFusion,
}
#[derive(Debug, Clone)]
pub struct DepthCompletionConfig {
pub method: CompletionMethod,
pub sigma_spatial: f64,
pub sigma_intensity: f64,
pub tv_lambda: f64,
pub max_iterations: usize,
pub convergence_tol: f64,
}
impl Default for DepthCompletionConfig {
fn default() -> Self {
Self {
method: CompletionMethod::NearestNeighbor,
sigma_spatial: 5.0,
sigma_intensity: 0.1,
tv_lambda: 0.1,
max_iterations: 100,
convergence_tol: 1e-4,
}
}
}
#[derive(Debug, Clone)]
pub struct SparseMeasurement {
pub row: usize,
pub col: usize,
pub depth: f64,
pub confidence: f64,
}
#[derive(Debug, Clone)]
pub struct SparseDepthMap {
pub height: usize,
pub width: usize,
pub measurements: Vec<SparseMeasurement>,
}
impl SparseDepthMap {
pub fn new(height: usize, width: usize, measurements: Vec<SparseMeasurement>) -> Result<Self> {
for m in &measurements {
if m.row >= height || m.col >= width {
return Err(VisionError::InvalidParameter(format!(
"measurement at ({}, {}) is out of bounds for {}x{} image",
m.row, m.col, height, width
)));
}
}
Ok(Self {
height,
width,
measurements,
})
}
pub fn validate_non_empty(&self) -> Result<()> {
if self.measurements.is_empty() {
return Err(VisionError::InvalidParameter(
"sparse depth map has no measurements".to_string(),
));
}
Ok(())
}
pub fn to_dense(&self) -> Array2<f64> {
let mut dense = Array2::zeros((self.height, self.width));
for m in &self.measurements {
dense[[m.row, m.col]] = m.depth;
}
dense
}
pub fn confidence_map(&self) -> Array2<f64> {
let mut conf = Array2::zeros((self.height, self.width));
for m in &self.measurements {
conf[[m.row, m.col]] = m.confidence;
}
conf
}
pub fn observation_mask(&self) -> Array2<bool> {
let mut mask = Array2::from_elem((self.height, self.width), false);
for m in &self.measurements {
mask[[m.row, m.col]] = true;
}
mask
}
}
#[derive(Debug, Clone)]
pub struct CompletionResult {
pub dense_depth: Array2<f64>,
pub confidence_map: Array2<f64>,
pub method_used: CompletionMethod,
pub iterations: usize,
}
#[derive(Debug, Clone)]
pub struct FusionConfig {
pub outlier_threshold: f64,
pub process_noise: f64,
pub measurement_noise: f64,
}
impl Default for FusionConfig {
fn default() -> Self {
Self {
outlier_threshold: 3.0,
process_noise: 0.01,
measurement_noise: 0.1,
}
}
}
#[derive(Debug, Clone)]
pub struct DepthSource {
pub source_id: String,
pub depth_map: Array2<f64>,
pub confidence: Array2<f64>,
pub noise_variance: f64,
}