use crate::misc::type_aliases::Float;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum InverseDepth {
Unknown,
Discarded,
WithVariance(Float, Float),
}
pub fn from_depth(scale: Float, depth: u16, variance: Float) -> InverseDepth {
match depth {
0 => InverseDepth::Unknown,
_ => InverseDepth::WithVariance(scale / Float::from(depth), variance),
}
}
#[allow(clippy::cast_precision_loss)]
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_sign_loss)]
pub fn to_depth(scale: Float, idepth: InverseDepth) -> u16 {
match idepth {
InverseDepth::WithVariance(x, _) => (scale / x).round() as u16,
_ => 0,
}
}
pub fn fuse<F>(
a: InverseDepth,
b: InverseDepth,
c: InverseDepth,
d: InverseDepth,
strategy: F,
) -> InverseDepth
where
F: Fn(&[(Float, Float)]) -> InverseDepth,
{
strategy(
[a, b, c, d]
.iter()
.filter_map(with_variance)
.collect::<Vec<_>>()
.as_slice(),
)
}
fn with_variance(idepth: &InverseDepth) -> Option<(Float, Float)> {
if let InverseDepth::WithVariance(idepth, var) = *idepth {
Some((idepth, var))
} else {
None
}
}
pub fn strategy_dso_mean(valid_values: &[(Float, Float)]) -> InverseDepth {
match valid_values {
[(d1, v1)] => InverseDepth::WithVariance(*d1, *v1),
[(d1, v1), (d2, v2)] => {
let sum = v1 + v2;
InverseDepth::WithVariance((d1 * v1 + d2 * v2) / sum, sum)
}
[(d1, v1), (d2, v2), (d3, v3)] => {
let sum = v1 + v2 + v3;
InverseDepth::WithVariance((d1 * v1 + d2 * v2 + d3 * v3) / sum, sum)
}
[(d1, v1), (d2, v2), (d3, v3), (d4, v4)] => {
let sum = v1 + v2 + v3 + v4;
InverseDepth::WithVariance((d1 * v1 + d2 * v2 + d3 * v3 + d4 * v4) / sum, sum)
}
_ => InverseDepth::Unknown,
}
}
pub fn strategy_statistically_similar(valid_values: &[(Float, Float)]) -> InverseDepth {
match valid_values {
[(d1, v1)] => InverseDepth::WithVariance(*d1, 2.0 * v1), [(d1, v1), (d2, v2)] => {
let new_d = (d1 * v2 + d2 * v1) / (v1 + v2);
let new_v = (v1 + v2) / 2.0; if (d1 - new_d).powi(2) < new_v && (d2 - new_d).powi(2) < new_v {
InverseDepth::WithVariance(new_d, new_v)
} else {
InverseDepth::Discarded
}
}
[(d1, v1), (d2, v2), (d3, v3)] => {
let v12 = v1 * v2;
let v13 = v1 * v3;
let v23 = v2 * v3;
let new_d = (d1 * v23 + d2 * v13 + d3 * v12) / (v12 + v13 + v23);
let new_v = 2.0 * (v1 + v2 + v3) / 9.0; if (d1 - new_d).powi(2) < new_v
&& (d2 - new_d).powi(2) < new_v
&& (d3 - new_d).powi(2) < new_v
{
InverseDepth::WithVariance(new_d, new_v)
} else {
InverseDepth::Discarded
}
}
[(d1, v1), (d2, v2), (d3, v3), (d4, v4)] => {
let v123 = v1 * v2 * v3;
let v234 = v2 * v3 * v4;
let v341 = v3 * v4 * v1;
let v412 = v4 * v1 * v2;
let sum_v1234 = v123 + v234 + v341 + v412;
let new_d = (d1 * v234 + d2 * v341 + d3 * v412 + d4 * v123) / sum_v1234;
let new_v = (v1 + v2 + v3 + v4) / 8.0; if (d1 - new_d).powi(2) < new_v
&& (d2 - new_d).powi(2) < new_v
&& (d3 - new_d).powi(2) < new_v
&& (d4 - new_d).powi(2) < new_v
{
InverseDepth::WithVariance(new_d, new_v)
} else {
InverseDepth::Discarded
}
}
_ => InverseDepth::Unknown,
}
}