在 0.667 和 3.833 Hz 范围内快速实现 IIR 滤波器



我需要削减 0.667 - 3.833 Hz 范围之外的频率(心率范围:40 到 230 bpm)。我查看了Apple文档,但我只看到了AVFoundation Butterworth过滤器。显然,"值的有效范围是 20 Hz 到 (SampleRate/2)。过滤器来自AVAudioUnitEQ,所以这是可以理解的......我似乎找不到任何在我正在使用的频率范围内工作的滤波器。

我是否必须实现自己的巴特沃兹过滤器,还是缺少什么?

编辑:所以我深入研究了文档,我发现了一个 IIR 过滤器和 FIR 过滤器,但这并不是我真正期望的......IIR滤波器是"级联双二阶IIR滤波器",而不是巴特沃兹滤波器(这是我更喜欢的)。我做了一些阅读,我不知道这个过滤器应该如何工作。如果我使用系数,我可以实现与巴特沃兹滤波器类似的功能吗?如果是这样,我该怎么做?目标是拥有一个没有波纹的平坦通带。

我松散地关注的博客文章:http://www.ignaciomellado.es/blog/Measuring-heart-rate-with-a-smartphone-camera

包含一些双二阶滤波器建议的博客文章:http://www.ignaciomellado.es/blog/Measuring-heart-rate-with-a-smartphone-camera

在任何语言中,IIR滤波器的实现都是非常简单和简单的。 IIR的设计是挑战和有趣的部分。可以进行很多权衡。 Biquad IIR滤波器是相当不错的二阶滤波器(可以用巴特沃兹系数配置),对于许多应用来说,一个就足够了,但是如果需要,您也可以级它们以制作更高阶的滤波器。

第一件事是弄清楚你真正需要什么,这通常意味着你需要了解你想要过滤的噪声在频域中是什么样子的,然后设计一个抑制噪声的滤波器。

周围有很多工具可以让您了解给定一组 IIR 系数的频率响应会是什么样子。

这是来自快速谷歌搜索的众多之一。

一个关键参数是采样数据源的频率(采样率)

一旦你有了系数,实现就非常简单了,它只是当前输入样本和许多先前输入和输出的函数。

你可以在这里找到一些细节,但这里有一个函数。

y[n] = b0* x[n] + b1 * x[n-1] + b2 * x[n-2] - a1 * y[n-1] - a2 * y[n-2]

其中 x[n] 是当前样本,x[n-1] 是之前的样本,依此类推,y[n] 是当前输出值,而 y[n-1]、y[n-2] 是以前的输出。

如果您真的想深入了解过滤器设计的细节,我找到的最好的资源之一就是使用 SciPy,同样也有很多关于如何执行此操作的教程。

我没有看过它,但这里有一个YouTube视频,描述了如何在Python中设计Butterworth过滤器。

正如我之前所说,一旦你有了系数,任何语言的实现都非常简单。例如,这是我在 c++ 中做的一个非常简单的 Biquad,用于过滤 Arduino 项目中的数据。 这可以很容易地转换为 swift 或任何其他语言。

class BiQuad {
public:
BiQuad(double b0, double b1, double b2, double a1, double a2)
: b0_(b0), b1_(b1), b2_(b2), a1_(a1), a2_(a2) {}

double processSample(double xn) {
xn_ = xn;
yn_ = b0_ * xn_ + b1_ * xnm1_ + b2_ * xnm2_ - a1_ * ynm1_ - a2_ * ynm2_;
ynm2_ = ynm1_;
ynm1_ = yn_;
xnm2_ = xnm1_;
xnm1_ = xn_;
return yn_;
}
double getCurrentY() { return yn_; }
void prime(double value) {
xn_ = xnm1_ = xnm2_ = yn_ = ynm1_ = ynm2_ = value;
}
private:
double b0_;
double b1_;
double b2_;
double a1_;
double a2_;
double xn_;
double xnm1_ = 0.0;
double xnm2_ = 0.0;
double yn_ = 0.0;
double ynm1_ = 0.0;
double ynm2_ = 0.0;
};

希望这有帮助。

最新更新