Skip to content

Commit 78fbc47

Browse files
Fix pyramid downsampling interpolation, and more.
Changes to: - Curve interpolation. - Resample interpolation. - Downsampling algorthim to maintain key features. - Downsampling, maintaining end-points. - Curve fitting with interpolation method. - Test programs simplfied to reduce line count. - Test image output file names. - f64 to 'Real' type. This is a big change, but basically this change is a simplification of test code, fixing of the pyramid down-sampling algorithm, and unification around new, reuseable interpolation code.
1 parent d56da4d commit 78fbc47

File tree

116 files changed

+1767
-1485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+1767
-1485
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ argmin = { version = "0.10.0", default-features = true, features = ["serde1"] }
2424
argmin-math = { version = "0.4", default-features = true, features = ["primitives", "vec", "ndarray_latest"] }
2525
criterion = { version = "0.5.1", default-features = false, features = ["html_reports"] }
2626
exr = "1.72.0"
27+
enum_dispatch = "0.3.13"
2728
fastapprox = "0.3.1"
2829
finitediff = { version = "0.1.4", features = ["ndarray"] }
2930
half = { version = "2.4.1", default-features = false, features = ["std", "num-traits"] }

lib/rust/mmscenegraph/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ anyhow = { workspace = true }
1919
approx = { workspace = true }
2020
argmin = { workspace = true }
2121
argmin-math = { workspace = true }
22+
enum_dispatch = { workspace = true }
2223
fastapprox = { workspace = true }
2324
finitediff = { workspace = true }
2425
log = { workspace = true }

lib/rust/mmscenegraph/src/constant.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ pub const MM_TO_CM: Real = 0.1;
4848
pub const _CM_TO_MM: Real = 10.0;
4949
pub const INCH_TO_MM: Real = 25.4;
5050
pub const _INCH_TO_CM: Real = 2.54;
51+
52+
// Number constants.
53+
pub const REAL_E: f64 = std::f64::consts::E;

lib/rust/mmscenegraph/src/curve/detect/keypoints.rs

Lines changed: 89 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -112,30 +112,28 @@ fn compute_velocity_importance(velocity: Real, acceleration: Real) -> Real {
112112
}
113113

114114
/// Detect keypoints specific to animation curves
115-
fn detect_level_keypoints(
116-
level: &PyramidLevel,
117-
existing_keypoints: &[RankedKeypoint],
115+
pub fn detect_level_keypoints(
116+
times: &[Real],
117+
values: &[Real],
118+
velocity: &[Real],
119+
acceleration: &[Real],
120+
curvature: &[Real],
118121
current_level: usize,
119122
) -> Vec<RankedKeypoint> {
120-
debug!("detect_level_keypoints: level.level={:?}", level.level);
121-
debug!("detect_level_keypoints: level.scale={:?}", level.scale());
123+
debug!("detect_level_keypoints: times.len()={}", times.len());
124+
debug!("detect_level_keypoints: values.len()={}", values.len());
125+
debug!("detect_level_keypoints: velocity.len()={}", velocity.len());
122126
debug!(
123-
"detect_level_keypoints: existing_keypoints.len()={:?}",
124-
existing_keypoints.len()
127+
"detect_level_keypoints: acceleration.len()={}",
128+
acceleration.len()
125129
);
126130
debug!(
127-
"detect_level_keypoints: existing_keypoints={:?}",
128-
existing_keypoints
131+
"detect_level_keypoints: curvature.len()={}",
132+
curvature.len()
129133
);
130-
debug!("detect_level_keypoints: current_level={:?}", current_level);
131-
132-
let mut keypoints = Vec::new();
133-
let times = &level.times;
134-
let values = &level.values;
135-
let velocity = &level.velocity;
136-
let acceleration = &level.acceleration;
137-
let curvature = &level.curvature;
134+
debug!("detect_level_keypoints: current_level={}", current_level);
138135

136+
let mut keypoints = Vec::with_capacity(times.len() / 2);
139137
for i in 1..times.len() - 1 {
140138
let curr_time = times[i];
141139
let _prev_time = times[i - 1];
@@ -190,24 +188,14 @@ fn detect_level_keypoints(
190188
keypoint_type = Some(KeypointType::VelocityPeak);
191189
}
192190

193-
// If point is important and not near existing keypoints
194191
if let Some(kp_type) = keypoint_type {
195-
let level_scale = level.scale();
196-
// let level_scale = level.inverse_scale();
197-
198-
if !is_near_existing_keypoint(
199-
curr_time,
200-
level_scale,
201-
existing_keypoints,
202-
) {
203-
keypoints.push(RankedKeypoint {
204-
time: curr_time,
205-
value: curr_value,
206-
importance,
207-
level_detected: current_level,
208-
keypoint_type: kp_type,
209-
});
210-
}
192+
keypoints.push(RankedKeypoint {
193+
time: curr_time,
194+
value: curr_value,
195+
importance,
196+
level_detected: current_level,
197+
keypoint_type: kp_type,
198+
});
211199
}
212200
}
213201

@@ -222,6 +210,67 @@ fn detect_level_keypoints(
222210
keypoints
223211
}
224212

213+
/// Detect keypoints specific to animation curves
214+
fn detect_level_and_combine_keypoints(
215+
level: &PyramidLevel,
216+
existing_keypoints: &[RankedKeypoint],
217+
current_level: usize,
218+
) -> Vec<RankedKeypoint> {
219+
debug!(
220+
"detect_level_and_combine_keypoints: level.level={:?}",
221+
level.level
222+
);
223+
debug!(
224+
"detect_level_and_combine_keypoints: level.scale={:?}",
225+
level.scale()
226+
);
227+
debug!(
228+
"detect_level_and_combine_keypoints: existing_keypoints.len()={:?}",
229+
existing_keypoints.len()
230+
);
231+
debug!(
232+
"detect_level_and_combine_keypoints: existing_keypoints={:?}",
233+
existing_keypoints
234+
);
235+
debug!(
236+
"detect_level_and_combine_keypoints: current_level={:?}",
237+
current_level
238+
);
239+
240+
let level_keypoints = detect_level_keypoints(
241+
&level.times,
242+
&level.values,
243+
&level.velocity,
244+
&level.acceleration,
245+
&level.curvature,
246+
current_level,
247+
);
248+
249+
let mut keypoints = Vec::new();
250+
for keypoint in level_keypoints {
251+
if !is_near_existing_keypoint(
252+
keypoint.time,
253+
level.scale(),
254+
existing_keypoints,
255+
) {
256+
keypoints.push(keypoint);
257+
}
258+
}
259+
260+
debug!(
261+
"detect_level_and_combine_keypoints: keypoints.len()={:?}",
262+
keypoints.len()
263+
);
264+
for keypoint in &keypoints {
265+
debug!(
266+
"detect_level_and_combine_keypoints: keypoint={:?}",
267+
keypoint
268+
);
269+
}
270+
271+
keypoints
272+
}
273+
225274
/// Check if point is near any existing keypoint.
226275
fn is_near_existing_keypoint(
227276
time: Real,
@@ -308,8 +357,11 @@ fn process_pyramid_levels(
308357
// Process levels from coarse to fine.
309358
let mut max_level = 0;
310359
for pyramid in pyramids.iter().rev() {
311-
let pyramid_keypoints =
312-
detect_level_keypoints(pyramid, &all_keypoints, pyramid.level);
360+
let pyramid_keypoints = detect_level_and_combine_keypoints(
361+
pyramid,
362+
&all_keypoints,
363+
pyramid.level,
364+
);
313365

314366
for keypoint in pyramid_keypoints {
315367
all_keypoints.push(keypoint);
@@ -328,7 +380,7 @@ fn process_pyramid_levels(
328380
Ok(selected)
329381
}
330382

331-
fn filter_keypoints_by_type_and_level(
383+
pub fn filter_keypoints_by_type_and_level(
332384
only_keypoint_type: KeypointType,
333385
only_level_detected: usize,
334386
min_spacing: Real,

lib/rust/mmscenegraph/src/curve/detect/pops.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use anyhow::Result;
2323
use log::debug;
2424
use std::fmt;
2525

26+
use crate::constant::Real;
2627
use crate::curve::derivatives::allocate_derivatives_order_2;
2728
use crate::curve::derivatives::calculate_derivatives_order_2;
2829
use crate::math::statistics::calc_median_absolute_deviation_sigma;
@@ -34,9 +35,9 @@ use crate::math::statistics::SortedDataSliceOps;
3435
/// Represents a point that was classified as a pop
3536
#[derive(Debug)]
3637
pub struct PopPoint {
37-
pub time: f64,
38-
pub value: f64,
39-
pub score: f64,
38+
pub time: Real,
39+
pub value: Real,
40+
pub score: Real,
4041
}
4142

4243
impl fmt::Display for PopPoint {
@@ -50,11 +51,11 @@ impl fmt::Display for PopPoint {
5051
}
5152

5253
fn calculate_per_frame_pop_score(
53-
times: &[f64],
54-
values: &[f64],
55-
out_velocity: &mut [f64],
56-
out_acceleration: &mut [f64],
57-
out_scores: &mut [f64],
54+
times: &[Real],
55+
values: &[Real],
56+
out_velocity: &mut [Real],
57+
out_acceleration: &mut [Real],
58+
out_scores: &mut [Real],
5859
) -> Result<()> {
5960
if (times.len() != values.len()) && (times.len() != out_scores.len()) {
6061
bail!("Times, values and output arrays must have the same length.");
@@ -105,9 +106,9 @@ fn calculate_per_frame_pop_score(
105106

106107
/// Find pops in the data.
107108
pub fn detect_curve_pops(
108-
times: &[f64],
109-
values: &[f64],
110-
threshold: f64,
109+
times: &[Real],
110+
values: &[Real],
111+
threshold: Real,
111112
) -> Result<Vec<PopPoint>> {
112113
if times.len() != values.len() {
113114
bail!("Times and values must have the same length.");
@@ -176,10 +177,10 @@ pub fn detect_curve_pops(
176177
}
177178

178179
pub fn filter_curve_pops(
179-
times: &[f64],
180-
values: &[f64],
181-
threshold: f64,
182-
) -> Result<Vec<(f64, f64)>> {
180+
times: &[Real],
181+
values: &[Real],
182+
threshold: Real,
183+
) -> Result<Vec<(Real, Real)>> {
183184
if times.len() != values.len() {
184185
bail!("Times and values must have the same length.");
185186
}

0 commit comments

Comments
 (0)