这将是一个很长的答案。
我将首先分析您的文件以及您可以采取哪些措施来改善音频。我还将在我设计用于检测心跳的算法上试用您的文件。在那之后,我将描述设计我的算法的内容以及它是如何工作的。然后,我将对如何开始使用您自己的算法提出一些一般性建议。
现有文件分析
我将您的每个文件加载到Audacity中以收听它们并查看频率内容的样子。通常,您不仅会遇到静态(白)噪声问题。来自您所在地区的交流电源频率(50Hz 和谐波)的持续干扰会给您带来很多麻烦。
从最差到最好:
文件: static_with_beats_doesnt_evaluate.wav
电力线噪声的严重干扰。我可以看到那里有一个心跳信号。但是,它被干扰掩盖了太多,无法检测到。没有什么可以保存这段录音。50Hz 干扰太接近实际信号而无法分离。
文件: in_accurate_with_noise.png 最大的问题还是来自 50Hz 电源线的干扰。在某些时候,信号足够干净,可以识别出心跳。如果我通过一个非常尖锐的 45Hz 低通滤波器运行它,我使用的算法可以挑选出个别的节拍,但即使这样,也有一些心跳是根本听不见的。
文件: accuracy.wav
这个文件没有电源线干扰,可能是在户外录制的。它可以比其他人更好地破译,尽管仍然有一些部分根本没有检测到信号。一个截止频率为 45 Hz 的陡峭低通滤波器从我的算法中得到了几乎完美的结果。有一小段信号太弱,无法从剩余的噪声中挑选出来。
文件: accuracy_72bpm.wav
该文件也缺少电源线干扰。偶尔的干扰会导致一个节拍在这里和那里丢失,但除此之外是非常好的录音。
检测心跳所涉及的问题
检测心跳涉及几个基本问题:
- 什么是心跳?心跳由多种声音组成,其中大部分声音很难与背景噪音和干扰区分开来。您必须选择一个“功能”,而不是从垃圾中可靠地挑选出来。简单地检测声音的音量是行不通的(太多其他的东西也可能很响。)我发现“lub dub”声音是大约 30Hz 到 40Hz 之间的短脉冲频率。这就是我的算法所要寻找的。
- 阈值 - 你什么时候真正检测到你的特征说有心跳?音量不断变化,噪音和干扰的音量也随之变化。因为固定阈值不行。您的阈值必须适应背景和心跳的变化量。心跳的音量随着每次呼吸而变化,并且随着麦克风在胸部周围移动而变化。对于阈值问题,我有一个非常奇怪的解决方案。
- 噪声 - 该算法必须在相当广泛的噪声条件下工作。您寻找的功能应该相当简单,几乎可以从任何噪音中挑选出来。我使用的算法可以达到大约 20dB 的信噪比。它对心跳信号的绝对电平不敏感,但需要相当干净的信号。
- 硬件——如果算法依赖于麦克风的灵敏度和频率响应,那么它对你没有好处。无论您做什么,都需要在任何手机上使用任何麦克风。我使用的算法对硬件几乎完全不敏感。如果有心跳,就会被发现。
第 3 点确实是最重要的。大声不重要,绝对水平不重要。整个事情的生死取决于你的信号有多干净。无论您使用什么算法,干净的信号都是必须的。
- 没有干扰。如果您正在拾取电源线嗡嗡声,请修复它。这通常是电气问题,可以通过适当的接线和接地来解决。
- 减少运动噪音。在我的实验中,我使用松紧带将麦克风固定在胸前。
- 减少背景噪音。我在麦克风和松紧带之间使用了一块塞满棉花的小纸板“饼干”。它由几圈带有塑料覆盖物的硬纸板制成。背面也是硬纸板。面向我胸部的那一面,棉球和麦克风之间只有一层塑料。这大大降低了背景噪音。
我如何检测心跳
我最终想出的方法是建立在对一些(真正)干净的心跳记录的观察之上。我发现,心跳的每一次“砰砰”都有一种“突发”的频率。如果您过滤掉除了突发内容之外的所有内容,那么您将获得一个相当可靠的心跳检测器。我使用 24 到 44 Hz 的带通滤波器。这似乎提供了最好的结果。范围可能取决于人——我没有足够的样本来比较。
在带通之后,我使用希尔伯特变换来连续估计突发频率的响度。希尔伯特函数给出两个彼此旋转 90 度的输出。每个平方,求和的平方根,你就有一个连续的信号,代表“突发”频率的幅度。对其应用低通滤波器以消除疯狂的变化。
获得正确的阈值是真正的问题,我尝试了几种方法。我从手动调整阈值开始,但当然它会随着您的呼吸和移动而改变,因此效果不佳。我尝试了自动校准,这有帮助,但必须在麦克风移动时重复。我尝试了各种自适应阈值,但由于各种原因都失败了。
最终效果很好的东西看起来非常愚蠢。
取幅值信号绝对值的对数。是的,取振幅的对数(无论您使用什么底数对数都没有关系。)将其通过高通滤波器,并将固定阈值应用于输出。该固定阈值并未设置信号的绝对电平。它正在设置信噪比。较低的值意味着“以较低的信噪比工作”,而较高的值意味着“需要更高的信噪比”。最终效果是“如果存在 24Hz 和 44Hz 之间的频率并且它比当前噪音水平响亮某个固定比率,则触发”。
这种设置对输入信号的绝对电平非常不敏感。麦克风和放大器的频率响应几乎无关紧要。当呼吸和麦克风改变位置时,它会自动适应运动。
此图显示了该过程的核心部分:
这是我为开发算法而放在一起 的纯数据补丁的片段。GitHub 上提供了整个内容以及一些示例文件。 如果您想试用它,您将需要Pure Data Extended 0.43才能使用该补丁 - 它依赖于 PD Extended 包含但其他版本不包含的几个外部库。
概括
无论您选择如何实现您的算法,您都必须从查看录音中的可用信号开始。
在时域(示波器视图)和频域 (FFT) 中查看它们。找出您的噪声和干扰的样子。
查看干净的录音,找出与噪音和干扰不同的特征。找到可以用某种过滤器挑选出来的东西。
设计一个可以将特性与噪声分离的滤波器。
设计一种使阈值适应当前噪声水平和信号水平的方法。
当然,我的方法有缺点。最大的问题是,如果没有心跳,它会“想象”它正在听到心跳并开始传递错误的脉冲。独立于绝对电平和硬件变化的代价是必须保证一定的最小信噪比。