C语言实现完整Savitzky - Golay滤波器算法:代码详解与使用注意
# Savitzky-Golay Filter in C Below is a complete implementation of the Savitzky-Golay filter in C. This implementation includes functions for calculating the filter coefficients and applying the filter to a data set. ```c #include <stdio.h> #include <stdlib.h> #include <math.h> // Function to calculate the Savitzky-Golay coefficients void savitzky_golay_coeff(int window_size, int poly_order, double* coeff) { int half_window = window_size / 2; double A[(2*poly_order+1) * window_size]; double AtA[(2*poly_order+1) * (2*poly_order+1)]; double invAtA[(2*poly_order+1) * (2*poly_order+1)]; // Construct the design matrix A for (int i = -half_window; i <= half_window; i++) { for (int j = 0; j <= poly_order; j++) { A[(i + half_window) * (poly_order + 1) + j] = pow(i, j); } } // Compute A^T * A for (int i = 0; i <= poly_order; i++) { for (int j = 0; j <= poly_order; j++) { AtA[i * (poly_order + 1) + j] = 0.0; for (int k = 0; k < window_size; k++) { AtA[i * (poly_order + 1) + j] += A[k * (poly_order + 1) + i] * A[k * (poly_order + 1) + j]; } } } // Compute inverse of A^T * A (using simple inversion for small matrices) double det = 0.0; if (poly_order == 2) { // For quadratic polynomial det = AtA[0]*(AtA[4]*AtA[8]-AtA[5]*AtA[7]) - AtA[1]*(AtA[3]*AtA[8]-AtA[5]*AtA[6]) + AtA[2]*(AtA[3]*AtA[7]-AtA[4]*AtA[6]); invAtA[0] = (AtA[4]*AtA[8] - AtA[5]*AtA[7]) / det; invAtA[1] = (AtA[2]*AtA[7] - AtA[1]*AtA[8]) / det; invAtA[2] = (AtA[1]*AtA[5] - AtA[2]*AtA[4]) / det; invAtA[3] = (AtA[5]*AtA[6] - AtA[3]*AtA[8]) / det; invAtA[4] = (AtA[0]*AtA[8] - AtA[2]*AtA[6]) / det; invAtA[5] = (AtA[2]*AtA[3] - AtA[0]*AtA[5]) / det; invAtA[6] = (AtA[3]*AtA[7] - AtA[4]*AtA[6]) / det; invAtA[7] = (AtA[1]*AtA[6] - AtA[0]*AtA[7]) / det; invAtA[8] = (AtA[0]*AtA[4] - AtA[1]*AtA[3]) / det; } else { // For linear polynomial (simpler case) det = AtA[0]*AtA[3] - AtA[1]*AtA[1]; invAtA[0] = AtA[3] / det; invAtA[1] = -AtA[1] / det; invAtA[2] = -AtA[1] / det; invAtA[3] = AtA[0] / det; } // Compute the coefficients for the middle point (smoothing) for (int i = 0; i < window_size; i++) { coeff[i] = 0.0; for (int j = 0; j <= poly_order; j++) { for (int k = 0; k <= poly_order; k++) { coeff[i] += A[i * (poly_order + 1) + k] * invAtA[k * (poly_order + 1) + j] * A[half_window * (poly_order + 1) + j]; } } } } // Function to apply Savitzky-Golay filter to data void apply_savitzky_golay(double* input, double* output, int data_size, int window_size, int poly_order) { double* coeff = (double*)malloc(window_size * sizeof(double)); savitzky_golay_coeff(window_size, poly_order, coeff); int half_window = window_size / 2; // Handle boundaries by simple copying (could be improved) for (int i = 0; i < half_window; i++) { output[i] = input[i]; output[data_size - 1 - i] = input[data_size - 1 - i]; } // Apply filter to middle points for (int i = half_window; i < data_size - half_window; i++) { output[i] = 0.0; for (int j = -half_window; j <= half_window; j++) { output[i] += coeff[j + half_window] * input[i + j]; } } free(coeff); } int main() { // Example usage const int data_size = 20; double input[data_size] = {1.2, 1.5, 1.7, 1.4, 1.6, 1.8, 2.0, 2.1, 2.3, 2.2, 2.0, 1.9, 1.7, 1.6, 1.5, 1.4, 1.3, 1.2, 1.1, 1.0}; double output[data_size]; int window_size = 5; // Must be odd int poly_order = 2; // Typically 2 (quadratic) or 3 (cubic) apply_savitzky_golay(input, output, data_size, window_size, poly_order); printf("Original Data\tSmoothed Data\n"); for (int i = 0; i < data_size; i++) { printf("%.2f\t\t%.2f\n", input[i], output[i]); } return 0; } ``` ## 代码说明 1. `savitzky_golay_coeff`函数计算Savitzky-Golay滤波器的系数矩阵 2. `apply_savitzky_golay`函数将滤波器应用于输入数据 3. 主函数演示了如何使用这些函数处理示例数据 ## 使用注意事项 1. 窗口大小(window_size)必须是奇数 2. 多项式阶数(poly_order)通常选择2(二次)或3(三次) 3. 边界处理采用了简单的复制方法,可以根据需要改进 4. 矩阵求逆部分目前只实现了线性和二次多项式的情况 ## 额外需要注意的逻辑点 1. 窗口大小和多项式阶数的选择会影响滤波效果,窗口越大平滑效果越强但可能丢失细节 2. 边界处理可以改进为使用较小的窗口或镜像数据等方法 3. 对于更高阶多项式,需要实现更通用的矩阵求逆算法 ######[AI写代码神器 | 1730点数解答 | 2025-07-22 17:58:35]
- Verilog 实现 8 位无符号二阶 7 点Savitzky - Golay 光谱曲线平滑滤波及注意要点 (字节豆包 | 404点数解答 | 2025-05-14 16:28:03)166
- 基于 Savitzky - Golay 滤波的光谱曲线处理:计算红边位置、幅值与面积(讯飞星火 | 927点数解答 | 2024-11-13 13:10:27)594
- Python 实现 Savitzky - Golay 滤波的详细过程及注意要点(字节豆包 | 319点数解答 | 2024-12-20 14:16:01)204
- JSP 实现商品展示模块:分页、搜索、交互与美观界面全搞定!(字节豆包 | 19点数解答 | 2024-12-13 15:00:43)349
- Python 实现球类:精准计算半径、表面积与体积,附输入验证与异常处理!(阿里通义 | 261点数解答 | 2024-11-28 21:19:39)362
- 深度揭秘 Oracle Workarea Size Policy:参数调优助力数据库性能飞升(阿里通义 | 372点数解答 | 2024-05-13 10:54:45)245
- 用 JS 中 for 循环实现 1 到 100 相加并输出结果到页面的完整代码 ( | 240点数解答 | 2024-05-20 22:11:29)487
- 用 JS 的 while 循环实现 1 到 100 相加并输出到页面的代码揭秘( | 47点数解答 | 2024-05-20 22:16:48)372
- C++ 实现我的世界基岩版:从简单框架到开发要点揭秘(字节豆包 | 182点数解答 | 2025-02-22 15:53:11)208
- C++ 实现完整斗地主:含洗牌、发牌与手牌展示,可按需扩展!(字节豆包 | 1028点数解答 | 2026-01-10 08:02:37)47
- PyCharm 中用 Selenium 编写自动化测试脚本,轻松登录 eShop 测试平台并点击“我的订单”(字节豆包 | 304点数解答 | 2024-11-06 15:38:30)447
- Verilog 实现二次多项式 Savitzky - Golay 滤波:代码示例、解释与注意要点(字节豆包 | 829点数解答 | 2025-07-29 09:52:39)115