MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches

◆ dtw_cost()

template<typename T >
float MayaFlux::Kinesis::dtw_cost ( std::span< const T >  a,
std::span< const T >  b,
const std::function< float(const T &, const T &)> &  distance,
size_t  band = 0 
)
inline

Dynamic time warping cost between two sequences.

Template Parameters
TElement type
Parameters
aLeft sequence
bRight sequence
distancePointwise cost between one element of each
bandSakoe-Chiba radius: the furthest an alignment may stray from the diagonal, in elements. Zero means unconstrained
Returns
Accumulated cost of the cheapest monotone alignment, or infinity if either sequence is empty or the band admits no complete alignment

Resampling by arc length removes speed variation from a path by discarding time entirely, which is right when only shape matters and wrong when the quantity being compared is not positional. This instead keeps both sequences and finds the cheapest correspondence between them, allowing one to stretch against the other, so two recordings of the same thing performed at different tempos align rather than disagree at every step.

The band is the difference between a bounded cost and a quadratic one, and it also encodes an assumption: a nonzero band asserts that the two sequences are roughly in step and only locally out of it. A band narrower than the genuine offset between two sequences reports infinity rather than a poor alignment, which is the honest answer given the constraint it was handed.

Definition at line 361 of file PathShape.hpp.

366{
367 if (a.empty() || b.empty())
368 return std::numeric_limits<float>::infinity();
369
370 const size_t n = a.size();
371 const size_t m = b.size();
372 constexpr float inf = std::numeric_limits<float>::infinity();
373
374 std::vector<float> prev(m + 1, inf);
375 std::vector<float> curr(m + 1, inf);
376 prev[0] = 0.0F;
377
378 for (size_t i = 1; i <= n; ++i) {
379 std::ranges::fill(curr, inf);
380
381 size_t lo = 1;
382 size_t hi = m;
383 if (band > 0) {
384 const auto centre = static_cast<size_t>(
385 (static_cast<double>(i) * static_cast<double>(m)) / static_cast<double>(n));
386 lo = (centre > band) ? (centre - band) : 1;
387 hi = std::min(m, centre + band);
388 if (lo > hi)
389 return inf;
390 }
391
392 for (size_t j = lo; j <= hi; ++j) {
393 const float cost = distance(a[i - 1], b[j - 1]);
394 const float best = std::min({ prev[j], curr[j - 1], prev[j - 1] });
395 curr[j] = (best == inf) ? inf : (cost + best);
396 }
397 std::swap(prev, curr);
398 }
399
400 return prev[m];
401}
size_t a
size_t b
float lo
float hi

References a, b, distance(), hi, and lo.

+ Here is the call graph for this function: