Img2Num C++ (Internal Developer Docs) dev
API Documentation
Loading...
Searching...
No Matches
SavitzkyGolay Class Reference
+ Collaboration diagram for SavitzkyGolay:

Public Member Functions

 SavitzkyGolay (int radius, int poly_order)
 
std::vector< Pointfilter (const std::vector< Point > &data)
 
std::vector< Pointfilter_wrap (const std::vector< Point > &data)
 
std::vector< float > get_coeffs () const
 

Private Member Functions

std::vector< std::vector< float > > invert_matrix (std::vector< std::vector< float > > A)
 
void compute_coefficients ()
 

Private Attributes

int window_size_
 
int window_radius_
 
int poly_order_
 
std::vector< float > coeffs_
 

Detailed Description

Definition at line 10 of file SavitskyGolay.h.

Constructor & Destructor Documentation

◆ SavitzkyGolay()

SavitzkyGolay::SavitzkyGolay ( int  radius,
int  poly_order 
)

Definition at line 8 of file SavitskyGolay.cpp.

9 : window_radius_(radius), window_size_(2 * radius + 1), poly_order_(poly_order) {
10 assert(radius >= 0);
11 assert(window_size_ > poly_order_);
12
13 compute_coefficients();
14}

Member Function Documentation

◆ compute_coefficients()

void SavitzkyGolay::compute_coefficients ( )
private

Definition at line 101 of file SavitskyGolay.cpp.

101 {
102 // 1. Create the matrix J = (A^T * A)
103 // Size is (poly_order + 1) x (poly_order + 1)
104 // Element J[i][j] is the sum of k^(i+j) for k in -m..m
105
106 int rows = poly_order_ + 1;
107 std::vector<std::vector<float>> J(rows, std::vector<float>(rows));
108
109 for (int i = 0; i < rows; ++i) {
110 for (int j = 0; j < rows; ++j) {
111 float sum = 0;
112 for (int k = -window_radius_; k <= window_radius_; ++k) {
113 sum += std::pow(k, i + j);
114 }
115 J[i][j] = sum;
116 }
117 }
118
119 // 2. Invert J to solve the normal equations
120 auto J_inv = invert_matrix(J);
121
122 // 3. Compute the weights
123 // The smoothed value is the coefficient c_0 of the polynomial.
124 // c_0 = sum( weight_k * y_k )
125 // weight_k = sum( J_inv[0][j] * k^j ) for j=0..order
126
127 coeffs_.resize(window_size_);
128 for (int k = -window_radius_; k <= window_radius_; ++k) {
129 float weight = 0.0;
130 for (int j = 0; j < rows; ++j) {
131 weight += J_inv[0][j] * std::pow(k, j);
132 }
133 coeffs_[k + window_radius_] = weight;
134 }
135}

◆ filter()

std::vector< Point > SavitzkyGolay::filter ( const std::vector< Point > &  data)

Definition at line 16 of file SavitskyGolay.cpp.

16 {
17 if (data.size() < window_size_) {
18 return data; // Data too short to filter
19 }
20
21 std::vector<Point> result(data.size());
22
23 // 1. Convolution for the valid range
24 for (size_t i = window_radius_; i < data.size() - window_radius_; ++i) {
25 Point val{0.0, 0.0};
26 for (int j = -window_radius_; j <= window_radius_; ++j) {
27 val += data[i + j] * coeffs_[j + window_radius_];
28 }
29 result[i] = val;
30 }
31
32 // 2. Handle Edges (Simple Repeat/Nearest padding strategy)
33 // For a robust production app, you might calculate asymmetric kernels here.
34 for (int i = 0; i < window_radius_; ++i) result[i] = data[i];
35 for (size_t i = data.size() - window_radius_; i < data.size(); ++i) result[i] = data[i];
36
37 return result;
38}
Definition Point.h:5

◆ filter_wrap()

std::vector< Point > SavitzkyGolay::filter_wrap ( const std::vector< Point > &  data)

Definition at line 40 of file SavitskyGolay.cpp.

40 {
41 // wrap around
42 if (data.size() < window_size_) {
43 return data; // Data too short to filter
44 }
45
46 std::vector<Point> result(data.size());
47 std::copy(data.begin(), data.end(), result.begin());
48
49 for (size_t i = 0; i < data.size(); ++i) {
50 Point val{0.0, 0.0};
51 for (int j = -window_radius_; j <= window_radius_; ++j) {
52 int k = i + j;
53 if (k < 0) {
54 k = data.size() + k;
55 } else if (k >= data.size()) {
56 k = k - data.size();
57 }
58 val = val + data[k] * coeffs_[j + window_radius_];
59 }
60 result[i] = val;
61 }
62
63 return result;
64}

◆ get_coeffs()

std::vector< float > SavitzkyGolay::get_coeffs ( ) const
inline

Definition at line 24 of file SavitskyGolay.h.

24 {
25 return coeffs_;
26 }

◆ invert_matrix()

std::vector< std::vector< float > > SavitzkyGolay::invert_matrix ( std::vector< std::vector< float > >  A)
private

Definition at line 68 of file SavitskyGolay.cpp.

68 {
69 int n = A.size();
70 std::vector<std::vector<float>> inv(n, std::vector<float>(n, 0.0));
71
72 // Initialize inverse as identity
73 for (int i = 0; i < n; ++i) inv[i][i] = 1.0;
74
75 for (int i = 0; i < n; ++i) {
76 // Find pivot
77 float pivot = A[i][i];
78 // (Simple pivot check, typically you'd swap rows for stability)
79 if (std::abs(pivot) < 1e-10) throw std::runtime_error("Matrix singular, cannot invert.");
80
81 // Normalize row
82 for (int j = 0; j < n; ++j) {
83 A[i][j] /= pivot;
84 inv[i][j] /= pivot;
85 }
86
87 // Eliminate other rows
88 for (int k = 0; k < n; ++k) {
89 if (k != i) {
90 float factor = A[k][i];
91 for (int j = 0; j < n; ++j) {
92 A[k][j] -= factor * A[i][j];
93 inv[k][j] -= factor * inv[i][j];
94 }
95 }
96 }
97 }
98 return inv;
99}

Member Data Documentation

◆ coeffs_

std::vector<float> SavitzkyGolay::coeffs_
private

Definition at line 15 of file SavitskyGolay.h.

◆ poly_order_

int SavitzkyGolay::poly_order_
private

Definition at line 14 of file SavitskyGolay.h.

◆ window_radius_

int SavitzkyGolay::window_radius_
private

Definition at line 13 of file SavitskyGolay.h.

◆ window_size_

int SavitzkyGolay::window_size_
private

Definition at line 12 of file SavitskyGolay.h.


The documentation for this class was generated from the following files: