我编写了这段代码来平滑曲线。
它需要一个点旁边的 5 个点并将它们相加并求平均值。
/* Smoothing */
void smoothing(vector<Point2D> &a)
{
//How many neighbours to smooth
int NO_OF_NEIGHBOURS=10;
vector<Point2D> tmp=a;
for(int i=0;i<a.size();i++)
{
if(i+NO_OF_NEIGHBOURS+1<a.size())
{
for(int j=1;j<NO_OF_NEIGHBOURS;j++)
{
a.at(i).x+=a.at(i+j).x;
a.at(i).y+=a.at(i+j).y;
}
a.at(i).x/=NO_OF_NEIGHBOURS;
a.at(i).y/=NO_OF_NEIGHBOURS;
}
else
{
for(int j=1;j<NO_OF_NEIGHBOURS;j++)
{
a.at(i).x+=tmp.at(i-j).x;
a.at(i).y+=tmp.at(i-j).y;
}
a.at(i).x/=NO_OF_NEIGHBOURS;
a.at(i).y/=NO_OF_NEIGHBOURS;
}
}
}
但我对每个点都得到非常高的值,而不是与前一点相似的值。形状被最大化了很多,这个算法出了什么问题?
这里看起来像是有限脉冲响应 (FIR) 滤波器的低低音实现,该滤波器实现了棚车窗功能。从DSP的角度思考问题,你需要过滤你的传入vector
with NO_OF_NEIGHBOURS
相等的 FIR 系数,每个系数的值为1/NO_OF_NEIGHBOURS
。通常最好使用已建立的算法,而不是重新发明轮子。
这是一个相当蹩脚的实现,我很快就敲定了过滤器加倍的实现。您可以轻松修改它以过滤您的数据类型。该演示显示了对上升锯齿函数 (0,.25,.5,1) 的几个周期的过滤,仅用于演示目的。它可以编译,所以你可以使用它。
#include <iostream>
#include <vector>
using namespace std;
class boxFIR
{
int numCoeffs; //MUST be > 0
vector<double> b; //Filter coefficients
vector<double> m; //Filter memories
public:
boxFIR(int _numCoeffs) :
numCoeffs(_numCoeffs)
{
if (numCoeffs<1)
numCoeffs = 1; //Must be > 0 or bad stuff happens
double val = 1./numCoeffs;
for (int ii=0; ii<numCoeffs; ++ii) {
b.push_back(val);
m.push_back(0.);
}
}
void filter(vector<double> &a)
{
double output;
for (int nn=0; nn<a.size(); ++nn)
{
//Apply smoothing filter to signal
output = 0;
m[0] = a[nn];
for (int ii=0; ii<numCoeffs; ++ii) {
output+=b[ii]*m[ii];
}
//Reshuffle memories
for (int ii = numCoeffs-1; ii!=0; --ii) {
m[ii] = m[ii-1];
}
a[nn] = output;
}
}
};
int main(int argc, const char * argv[])
{
boxFIR box(1); //If this is 1, then no filtering happens, use bigger ints for more smoothing
//Make a rising saw function for demo
vector<double> a;
a.push_back(0.); a.push_back(0.25); a.push_back(0.5); a.push_back(0.75); a.push_back(1.);
a.push_back(0.); a.push_back(0.25); a.push_back(0.5); a.push_back(0.75); a.push_back(1.);
a.push_back(0.); a.push_back(0.25); a.push_back(0.5); a.push_back(0.75); a.push_back(1.);
a.push_back(0.); a.push_back(0.25); a.push_back(0.5); a.push_back(0.75); a.push_back(1.);
box.filter(a);
for (int nn=0; nn<a.size(); ++nn)
{
cout << a[nn] << endl;
}
}
使用这条线增加滤波器系数的数量可以看到逐渐更加平滑的输出。只有 1 个滤波器系数,没有平滑。
boxFIR box(1);
该代码足够灵活,如果您愿意,您甚至可以更改窗口形状。通过修改构造函数中定义的系数来做到这一点。
注意:这将为您的实现提供略有不同的输出,因为这是一个因果过滤器(仅取决于当前样本和先前样本)。您的实现不是因果关系,因为它会及时查看未来的样本以求平均值,这就是为什么您需要针对接近向量末尾的情况的条件语句。如果您想要输出类似于您尝试使用此算法对过滤器执行的操作,请通过此算法反向运行您的向量(只要窗口函数是对称的,这就可以正常工作)。这样你就可以获得类似的输出,而无需算法中令人讨厌的条件部分。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)