导言
最近在进行Qt开发,涉及大量的matlab转C的工作,其中包括插值滤波等,这里对matlab的filter函数进行了研究并用C++进行了重写。
经对比,结果与matlab的filter()函数生成的滤波结果一致。
函数需求分析
这里我对工作中调用matlab的filter()函数的实例为例子进行讲解:
- 原matlab程序 :
temp1_i=filter(lbf,1,real(x_d(1:lbn+LEN)));
temp1_q=filter(lbf,1,imag(x_d(1:lbn+LEN)));
-
filter()生成的结果
-
C++版filter()输入输出参数详情:
参数名 | 介绍 |
---|---|
Ti | 已有的点的x坐标的值 |
To | 插入的点的X坐标的值 |
I_Id | 已有的点实部的y坐标的值 |
Q_Id | 已有的点虚部的y坐标的值 |
Y | 插入的点的实部和虚部的Y坐标的值以复数的形式返回 |
comDouble filter(vector<double> b, double a, comDouble x)
/*
注意:该函数仅实现了a为标量且为1时的函数滤波!!!
参数介绍:
b: 滤波器系数
a: 分母系数
x: 复数
x.real: 复数实部
x.imag: 复数虚部
Y: 复数滤波结果
Y.real:复数实部滤波结果
Y.imag:复数虚部滤波结果
公式:(a = 1时)
当 i < 滤波器阶数 时有:
Y[i] = ∑b[j]*x[i-j] (下限j=0, 上限j<i)
当 i > 滤波器阶数 时有:
Y[i] = ∑b[j]*x[i-j] (下限j=0, 上限j<滤波器阶数)
*/
- C++版interp函数生成结果 :结果表明,生成结果与matlab生成结果一致。
源码
那么废话不多说,直接上代码
#include <vector>
#include <iostream>
using namespace std;
const struct comDouble
{
vector<double> real;
vector<double> imag;
double time;
};
comDouble filter(vector<double> b, double a, comDouble x)
{
/*
注意:该函数仅实现了a为标量且为1时的函数滤波!!!
参数介绍:
b: 滤波器系数
a: 分母系数
x: 复数
x.real: 复数实部
x.imag: 复数虚部
Y: 复数滤波结果
Y.real:复数实部滤波结果
Y.imag:复数虚部滤波结果
公式:(a = 1时)
当 i < 滤波器阶数 时有:
Y[i] = ∑b[j]*x[i-j] (下限j=0, 上限j<i)
当 i > 滤波器阶数 时有:
Y[i] = ∑b[j]*x[i-j] (下限j=0, 上限j<滤波器阶数)
*/
comDouble Y;
for (int i = 0; i < b.size(); i++)
{
double real = 0.0;
double imag = 0.0;
for (int j = 0; j <= i; j++) {
real += b[j] * x.real[i - j];
imag += b[j] * x.imag[i - j];
}
Y.real.push_back(real);
Y.imag.push_back(imag);
}
for (int i = b.size(); i < x.real.size(); i++) {
double real = 0.0;
double imag = 0.0;
for (int j = 0; j < b.size(); j++) {
real += b[j] * x.real[i - j];
imag += b[j] * x.imag[i - j];
}
Y.real.push_back(real);
Y.imag.push_back(imag);
}
return Y;
}
追求速度
#include <iostream>
using namespace std;
struct comDoubleC
{
double *real;
double *imag;
double time;
int rsize;
int isize;
comDoubleC(int reallen, int imaglen) {
this->real = new double[reallen];
this->imag = new double[imaglen];
this->time = 0;
this->rsize = 0;
this->isize = 0;
}
};
//fir滤波
comDoubleC filter(
double lbf[],
int lbflen,
double x_dreal[],
double x_dimag[],
int x_dLen,
comDoubleC temp1_iq)
{
/*
注意:该函数仅实现了a为标量且为1时的函数滤波!!!
参数介绍:
lbf: 滤波器系数
x_dreal: 复数实部
x_dimag: 复数虚部
temp1_iq:结果---在函数外管理内存
公式:(a = 1时)
当 i < 滤波器阶数 时有:
Y[i] = ∑b[j]*x[i-j] (下限j=0, 上限j<i)
当 i > 滤波器阶数 时有:
Y[i] = ∑b[j]*x[i-j] (下限j=0, 上限j<滤波器阶数)
*/
double real;
double imag;
for (int i = 0; i < lbflen; i++)
{
real = 0.0;
imag = 0.0;
for (int j = 0; j <= i; j++) {
real += lbf[j] * x_dreal[i - j];
imag += lbf[j] * x_dimag[i - j];
}
temp1_iq.real[i] = real;
temp1_iq.imag[i] = imag;
}
for (int i = lbflen; i < x_dLen; i++) {
real = 0.0;
imag = 0.0;
for (int j = 0; j < lbflen/2; j++) {
real += lbf[j] * x_dreal[i - lbflen + j];
imag += lbf[j] * x_dimag[i - lbflen + j];
}
temp1_iq.real[i] = real;
temp1_iq.imag[i] = imag;
}
return temp1_iq;
}
注意
该文章仅个人学习使用,欢迎大家一起交流学习