Savitzky–Golay滤波 matlab/C++代码编写

       最近准备把matlab sgolayfilt函数转成opencv + C++代码,网上溜达了一圈,看到有配置GSL库,调用相关函数实现的C代码。GSL编译好了,觉得程序太复杂,决定看一看原理自己写吧。原理什么的参见下面的连接,话不多说,直接上代码。

相关参考连接

1、Savitzky-Golay 滤波器详解及C/matlab语言  https://blog.csdn.net/shenziheng1/article/details/53391422

2、C++编写S-G滤波  https://download.csdn.net/download/mr_wwww/10370036

3、Savitzky-Golay 卷积平滑算法 http://www.doc88.com/p-7788316275187.html

4、Windows下编译64为GSL  https://www.cnblogs.com/Ooman/p/11080694.html

matlab代码

function [test_data_sg] = Maxtrix_sg(test_data, M, N)
% test_data 待滤波数据
% M 滑动窗口大小 = 2 * M + 1
% N 拟合多项式最高阶数 = N - 1
% test_data_sg 滤波后的数据
test_data_sg = test_data;
[~, cols] = size(test_data);

if(cols <= 2 * M + 1)
    msgbox('待滤波数据长度太短', 'Warning:')
end

if(2 * M + 1 <= N)
    msgbox('滑动窗口比拟合多项式还小, 无法求解', 'Warning:')
end

move_box = zeros(2*M+1, N);
for i = -M : M
    for j = 0 : N - 1
        move_box(i+M+1, j+1) = i ^ j;
    end
end
I = ones(1, N);
I = diag(I);
move_box_move = move_box' * move_box;
mox_box_coef = (move_box * (I / move_box_move)) * move_box';

for i = M+1 : cols-M
    
    result = mox_box_coef * test_data(2, i-M : i+M)';
    test_data_sg(2, i) = result(M+1, 1);
    
end

matlab 自编写函数Maxtrix_sg(test_data, 7, 5) 与 sgolayfilt(test_data(2, :), 5, 15) 测试结果对比:

对比结果:自写Maxtrix_sg函数除了首尾端各M个数据没有处理之外,其余处理结果与matlab sgolayfilt处理结果一致。

opencv + C++代码

#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cmath>

using namespace cv;
using namespace std;

// 矩阵X的广义逆
Mat Generalized_inverse(Mat &X)
{
	Mat Xt = X.t();

	Mat Xt_X = Xt * X;

	Mat inverse_Xt_X;
	invert(Xt_X, inverse_Xt_X, DECOMP_LU);		//方阵LU分解,求逆矩阵

	return inverse_Xt_X * Xt;
}

vector<vector<float>> opencv_sg(vector<vector<float>> &test_data, int M, int N)
{
	// SG平滑矩阵算子	
	Mat move_box(2 * M + 1, N, CV_32F);
	for (int i = -M; i <= M; ++i)
	{
		for (int j = 0; j < N; ++j)
		{
			move_box.at<float>(i + M, j) = pow(i, j);
		}
	}
	Mat gen_inv = Generalized_inverse(move_box);	// 矩阵move_box 的广义逆
	
	vector<vector<float>> test_data_clone = test_data;

	if (test_data[0].size() <= 2 * M + 1)
	{
		qDebug() << "the length of the input_data is too short!";
	}

	if (2 * M + 1 <= N)
	{
		qDebug() << "box size is too small!";
	}

	for (int i = M; i < test_data[0].size() - M; ++i)
	{
		Mat y_box_value(2 * M + 1, 1, CV_32F);
		for (int j = -M; j <= M; ++j)
		{
			y_box_value.at<float>(j + M, 0) = test_data[1][i + j];
		}

		Mat ls_sol = gen_inv * y_box_value;					// 最小二乘解
		Mat result = move_box * ls_sol;						// sg滤波值
		test_data_clone[1][i] = result.at<float>(M, 0);
	}

	return test_data_clone;
}

opencv + C++ 代码测试结果:

测试结果与matlab测试结果一致(注:C++下标从0开始,matlab下标从1开始。故这里从349开始截图)

完工~

  • 7
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
SAVITZKY-GOLAY滤波器是一种基于局域多项式最小二乘法拟合的滤波方法,最初由SavitzkyGolay于1964年提出。该滤波器的主要目的是对数据进行平滑和去噪处理,同时保持信号的形状和宽度不变。 在SAVITZKY-GOLAY滤波器中,窗口大小和多项式阶数是两个重要的参数。窗口大小决定了在滤波过程中用于拟合的数据点的数量,而多项式阶数则决定了用于拟合的多项式的次数。这两个参数的选择将直接影响滤波器的效果。 具体来说,SAVITZKY-GOLAY滤波器的原理是通过在每个数据点上进行多项式拟合,然后根据拟合结果来估计该数据点的值。这样可以在滤除噪声的同时保持信号的平滑性。由于拟合过程是基于局域数据进行的,所以该滤波器能够保留信号的细节信息。 总结起来,SAVITZKY-GOLAY滤波器通过基于局域多项式最小二乘法拟合的方式,对数据进行平滑和去噪处理,同时保持信号的形状和宽度不变。它是一种常用的光谱分析预处理方法,可以提高光谱的平滑性并降低噪音的干扰。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【UWB】Savitzky Golay filter SG滤波器原理讲解](https://blog.csdn.net/weixin_36815313/article/details/121238628)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值