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

◆ savitzky_golay()

MAYAFLUX_API std::vector< double > MayaFlux::Kinesis::Discrete::savitzky_golay ( size_t  window,
size_t  poly_order,
size_t  derivative = 0 
)

Savitzky-Golay FIR coefficients for smoothing or differentiation.

Fits a polynomial of degree poly_order to a sliding window by least squares and evaluates the requested derivative of that fit at the window centre. With derivative 0 this smooths while preserving peak shape better than a boxcar of the same length; with derivative 1 or 2 it estimates rate of change with far less noise amplification than a raw finite difference, since the differentiation acts on the fitted polynomial rather than on the samples.

This is the block and node form of the kernel that Kinesis::Differential::backward_difference computes per sample on glm types. The streaming form divides by an observed dt and handles irregular timing; this form assumes uniform spacing and returns coefficients in sample units, so a caller needing physical units scales by 1 / dt^derivative.

Returned in FIR tap order: index 0 multiplies the newest sample. Group delay is (window - 1) / 2 samples.

Parameters
windowKernel length, forced odd, must exceed poly_order
poly_orderDegree of the fitted polynomial
derivativeWhich derivative of the fit to evaluate; 0 smooths
Returns
Coefficient vector of length window, or empty if window <= poly_order

Definition at line 216 of file Coefficients.cpp.

217{
218 const size_t n = force_odd(window);
219 if (n <= poly_order || derivative > poly_order)
220 return {};
221
222 const auto rows = static_cast<Eigen::Index>(n);
223 const auto cols = static_cast<Eigen::Index>(poly_order) + 1;
224 const double half = static_cast<double>(n - 1) * 0.5;
225
226 Eigen::MatrixXd vandermonde(rows, cols);
227 for (Eigen::Index i = 0; i < rows; ++i) {
228 const double z = static_cast<double>(i) - half;
229 double p = 1.0;
230 for (Eigen::Index j = 0; j < cols; ++j) {
231 vandermonde(i, j) = p;
232 p *= z;
233 }
234 }
235
236 const Eigen::MatrixXd pseudo = vandermonde
237 .completeOrthogonalDecomposition()
238 .pseudoInverse();
239
240 double factorial = 1.0;
241 for (size_t k = 2; k <= derivative; ++k)
242 factorial *= static_cast<double>(k);
243
244 const Eigen::VectorXd row = pseudo.row(static_cast<Eigen::Index>(derivative)) * factorial;
245
246 std::vector<double> h(n);
247 for (size_t i = 0; i < n; ++i)
248 h[i] = row(static_cast<Eigen::Index>(n - 1 - i));
249
250 return h;
251}
uint32_t h
Definition InkPress.cpp:28
float k

References h, and k.