FIR滤波器在C++中使用MATLAB中的系数设计,滤波器没有给出正确的结果

FIR filter design in C++ using coefficients from MATLAB, Filter not giving correct results

本文关键字:滤波器 结果 C++ MATLAB FIR      更新时间:2023-10-16

我正在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; 
}

我尝试使用下面代码片段中描述的过滤器。filteredTtrajectory是向量的向量,我想在这里存储过滤后的值。YCordinates是包含要滤波的数据的向量的向量。Y坐标系的尺寸为[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的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();
  }
}