用于平滑的算法
Algorithm for smoothing
我写了此代码以平滑曲线。它在一个点旁边需要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)滤波器的低音量,该滤镜实现了实现Boxcar窗口功能的滤波器。考虑到DSP的问题,您需要使用NO_OF_NEIGHBOURS
相等的FIR系数过滤传入的vector
,每个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);
该代码足够灵活,如果愿意,您甚至可以更改窗口形状。通过修改构造函数中定义的系数来执行此操作。
注意:这将使您的实现略有不同,因为这是一个因果过滤器(仅取决于当前样本和以前的样本)。您的实现不是因果关系,因为它会在未来的样本中及时提前保持平均水平,这就是为什么您需要在矢量末尾的情况下需要条件陈述的原因。如果您希望像尝试使用此算法尝试使用过滤器执行的输出,请在反向的情况下通过此算法运行矢量(只要窗口函数是对称的,就可以正常运行该算法。这样,您可以在没有算法的讨厌的条件部分的情况下获得类似的输出。
在以下块中:
for(int j=0;j<NO_OF_NEIGHBOURS;j++)
{
a.at(i).x=a.at(i).x+a.at(i+j).x;
a.at(i).y=a.at(i).y+a.at(i+j).y;
}
对于每个邻居,您分别添加a.at(i)的x和y到邻居值。
我正确理解,应该是这样的。
for(int j=0;j<NO_OF_NEIGHBOURS;j++)
{
a.at(i).x += a.at(i+j+1).x
a.at(i).y += a.at(i+j+1).y
}
过滤非常适合'内存'平滑。这是LearnVST答案的相反通过,以防止阶段失真:
for (int i = a.size(); i > 0; --i)
{
// Apply smoothing filter to signal
output = 0;
m[m.size() - 1] = a[i - 1];
for (int j = numCoeffs; j > 0; --j)
output += b[j - 1] * m[j - 1];
// Reshuffle memories
for (int j = 0; j != numCoeffs; ++j)
m[j] = m[j + 1];
a[i - 1] = output;
}
MATLAB中的零相变形FIR滤波器的更多信息:http://www.mathworks.com/help/signal/ref/ref/filtfilt.html
点的当前值使用两次:一次是因为您使用+=
,并且如果y==0
,则使用一次。因此,您正在构建例如6点的总和,但仅除以5。此问题在IF和其他情况下。另外:您应该检查向量是否足够长,否则您的其他内容将以负索引阅读。
以下本身不是问题,而只是一个想法:您是否考虑使用仅触摸每个点两次的算法?当您访问每个点时,只需添加新点,然后减去最古老的点,如果它比您的NEIGHBOURS
较远。您将此"运行总和"保留为每个点,并将此值存储为新点的NEIGHBOURS
-NUMBER。
当您需要邻居点时,您会增加点本身 - 只需将索引偏移1:
for(int j=0;j<NO_OF_NEIGHBOURS;j++)
{
a.at(i).x += a.at(i+j+1).x
a.at(i).y += a.at(i+j+1).y
}
这对我来说很好:
for (i = 0; i < lenInput; i++)
{
float x = 0;
for (int j = -neighbours; j <= neighbours; j++)
{
x += input[(i + j <= 0) || (i + j >= lenInput) ? i : i + j];
}
output[i] = x / (neighbours * 2 + 1);
}
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 排序算法c++
- 构建可组合有向图(扫描仪生成器的汤普森构造算法)
- 算法问题:查找从堆栈中弹出的所有序列
- 下面是排序算法O(n)吗
- KMP算法和LPS表构造的运行时间
- 为什么我的排序算法会更改数组值
- 求最大元素位置的分治算法
- 具有非整数边容量的最大流量的Dinic算法
- 到连接组件算法的问题(递归)
- STL算法函数在多个一维容器上的使用
- 读取最后一行代码算法 - c++ 时出现问题
- 括号更改 O(n) 算法
- std::unordered_map 搜索算法是如何实现的?
- 用于平滑的算法
- 平滑算法采用整数算法