【问题标题】:FIR filter design in C++ using coefficients from MATLAB, Filter not giving correct results使用 MATLAB 中的系数在 C++ 中设计 FIR 滤波器,滤波器没有给出正确的结果
【发布时间】:2016-07-27 09:28:08
【问题描述】:

我正在开发 OpenCV 的一个项目,因为我是这个领域的新手,我面临着一些问题。我必须设计一个 128 阶 FIR 带通滤波器,为此我使用了通过 MATLAB 计算的系数。我在网上找到了以下代码。

const int taps = 129;
double buffer[129] = {0.0};
int offset = 0;
double input;

double coefficients[] =

{
    0.0005,0.0004,0.0002,0.0000,-0.0001,-0.0000,0.0001,0.0004,0.0007,0.0011,
    0.0015,0.0017,0.0018,0.0016,0.0011,0.0006,0.0001,-0.0003,-0.0002,0.0003,
    0.0011,0.0022,0.0032,0.0038,0.0038,0.0031,0.0015,-0.0005,-0.0026,-0.0044,
    -0.0053,-0.0050,-0.0037,-0.0016,0.0007,0.0023,0.0027,0.0012,-0.0022,-0.0072,
    -0.0127,-0.0178,-0.0212,-0.0220,-0.0199,-0.0153,-0.0093,-0.0036,-0.0001,-0.0003,
    -0.0053,-0.0147,-0.0274,-0.0408,-0.0519,-0.0573,-0.0545,-0.0419,-0.0197,0.0102,
    0.0442,0.0779,0.1064,0.1254,0.1321,0.1254,0.1064,0.0779,0.0442,0.0102,-0.0197,
    -0.0419,-0.0545,-0.0573,-0.0519,-0.0408,-0.0274,-0.0147,-0.0053,-0.0003,-0.0001,-0.0036,
    -0.0093,-0.0153,-0.0199,-0.0220,-0.0212,-0.0178,-0.0127,-0.0072,-0.0022,0.0012,0.0027,
    0.0023,0.0007,-0.0016,-0.0037,-0.0050,-0.0053,-0.0044,-0.0026,-0.0005,0.0015,0.0031,
    0.0038,0.0038,0.0032,0.0022,0.0011,0.0003,-0.0002,-0.0003,0.0001,0.0006,0.0011,
    0.0016,0.0018,0.0017,0.0015,0.0011,0.0007, 0.0004,0.0001,-0.0000,-0.0001,0.0000,
    0.0002,0.0004,0.0005
};


double filter( double input)

{
    double output = 0;


    for(int i= taps-1; i>0 ; i-- )
    {
       buffer[i] = buffer[i-1];
    }

       buffer[0] = input;


    for(int j = 0; j<taps; j++ )
    {

        output += (coefficients[j]*buffer[j]);

    }
    return output; 
}

我尝试使用下面代码 sn-p 中描述的过滤器。 filtersTrajectory 是向量的向量,我想在其中存储过滤后的值。 YCoordinates 是包含要过滤的数据的向量的向量。 YCoordinates的尺寸是[1000x266]

// Calling FIR filter function filter
// filtering all 266 values across 1000 frames.

const int numFrames = 1000;

//featuresPrevious.size() = 266 (predefined fixed value)

vector<vector<double>> filteredTrajectory;
filteredTrajectory.resize(numFrames-1);

   for (int i = 0; i<numFrames-1; i++)

    {

       filteredTrajectory[i].resize(featuresPrevious.size());

       for (int j = 0; j<featuresPrevious.size(); j++)

        {

            filteredTrajectory[i][j] = filter (Ycoordinates[i][j]); 

     }

    }

当我运行此代码时,过滤后的值与 MATLAB 的值不匹配。但是,如果我在所有 1000 帧中只过滤一个值,我会得到与 MATLAB 匹配的结果(参见下面的代码)。

// Filtering value at index Ycoordinates[i][0] across all frames 

filteredTrajectory.resize(numFrames-1);

   for (int i = 0; i<numFrames-1; i++)

    {

     filteredTrajectory[i].resize(1);

     filteredTrajectory[i][0] = filter (Ycoordinates[i][0]);

} 

代码中可能存在哪些缺陷,在过滤循环内的所有轨迹时提供错误结果,但在单独过滤时匹配结果。

【问题讨论】:

  • 请同时提供 Matlab 代码...移植它可能比更正你的代码更容易;D
  • 我已经编辑了帖子,我已经复制了系数。滤波器规格如下 FIR 滤波器 带通 128 阶汉明窗 Fs = 50 Hz Fc1 = 0.7 Hz Fc2 = 4 Hz 我在 MATLAB 中使用 fdatool 设计滤波器,然后生成系数。

标签: c++ opencv signal-processing digital-filter


【解决方案1】:

Matlab 的filter 是一维滤波器。当提供一个二维矩阵的输入时,它会独立过滤每一列(如果 dim 参数未设置或设置为 1,则为默认值;将 dim 设置为 2 将执行相同的操作,但在每一行上),本质上是在每个处理的列(或行)之间重置 FIR 状态。

因此,为了获得正确的结果,您还必须通过将缓冲区重置为零来重置您存储在buffer 中的每组要过滤的值之间的过滤器状态:

void reset_buffer()
{
  for(int i=0; i<taps ; i++ )
  {
    buffer[i] = 0.0;
  }
}

此外,过滤器必须按顺序查看属于同一集合的每个值(即不要将值交错到过滤函数),因此循环的顺序很重要。根据您是要沿数据的列维度还是行维度进行过滤,您可以使用以下任一函数:

// Filter along columns, similar to Matlab's filter(coefficients, 1, data, [], 1)
void filterDim1()
{
  for (int i = 0; i<numFrames-1; i++)
  {
    filteredTrajectory[i].resize(featuresPrevious.size());
  }
  for (int j = 0; j<featuresPrevious.size(); j++)
  {
    for (int i = 0; i<numFrames-1; i++)
    {
      filteredTrajectory[i][j] = filter (Ycoordinates[i][j]); 
    }
    reset_buffer();
  }
}
// Filter along rows, similar to Matlab's filter(coefficients, 1, data, [], 2)
void filterDim2()
{
  for (int i = 0; i<numFrames-1; i++)
  {
    filteredTrajectory[i].resize(featuresPrevious.size());
    for (int j = 0; j<featuresPrevious.size(); j++)
    {
      filteredTrajectory[i][j] = filter (Ycoordinates[i][j]); 
    }
    reset_buffer();
  }
}

【讨论】:

  • 非常感谢 SleuthEye,您的代码工作得非常好。但是滤波后的信号有群延迟,有什么办法可以去掉它...?
  • 任何因果系统(除了微不足道的缩放)都会有一些延迟。如果您的应用程序可以支持非因果实现(例如,您没有实时处理样本),那么“消除”延迟的一种方法是使用“向前-向后”过滤。看看filtfilt
  • 非常感谢您的帮助 :) @SleuthEye,我将查看 filtfilt 文档并尝试在 C++ 中实现相同的功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
  • 1970-01-01
相关资源
最近更新 更多