第一章 数据预处理:噪声来源分析、低通滤波原理、移动平均滤波实现
各位同学好,我是你们的嵌入式系统讲师。今天咱们来聊聊计步算法里最基础、也最容易被忽视的一环——数据预处理。
说实话,我刚开始做计步算法时,踩过最大的坑就是「数据没洗干净」。你想想看,手环戴在手腕上,走路、甩手、甚至打字都会产生加速度信号。如果不做预处理,算法会把「甩手」误判成「走路」。嗯,这问题我当年在项目里可没少头疼。
1.1 噪声来源分析
先说说噪声从哪来。我习惯把噪声分成三类:
- 人体运动噪声:走路时手臂自然摆动,但你可能在接电话、挠头、或者挥手。这些动作都会叠加到步态信号上。
- 传感器自身噪声:加速度计芯片本身有热噪声、量化噪声。说白了,就是芯片内部电路产生的随机波动。
- 环境振动噪声:坐车、电梯、甚至旁边有人跺脚,都会通过手腕传递到手环上。
我记得有一次,测试人员戴着我的手环去坐地铁。结果计步数直接翻了三倍。后来一查,原来是地铁启动时的低频振动被误判成了步数。从那以后,我对噪声分析就格外上心。
核心观点:计步算法的第一步,不是「怎么算步数」,而是「怎么把不是步数的信号去掉」。
1.2 低通滤波原理
好,噪声知道了,怎么去掉?最常用的手段就是低通滤波。
低通滤波,说白了就是「让慢的信号通过,把快的信号拦住」。人的正常步行频率是多少?大概1-3Hz。而甩手、抖动这些噪声,频率往往在5Hz以上。所以,我们只需要保留3Hz以下的信号,就能把大部分噪声滤掉。
从数学上讲,低通滤波可以用一个简单的一阶RC电路来理解。但咱们做嵌入式,不用纠结太多公式。你只需要记住:
- 截止频率:信号衰减到原来0.707倍时的频率
- 对于计步,我一般把截止频率设在3-5Hz之间
- 频率越高,保留的细节越多,但噪声也越多
个人经验:我在项目中试过2Hz、3Hz、5Hz三个截止频率。最后发现3Hz最适合日常步行。如果是跑步场景,可以适当提高到5Hz。这个值不是固定的,建议你拿到真实数据后自己调一调。
1.3 移动平均滤波实现
理论讲完了,咱们来点实际的。移动平均滤波是最简单、最常用的低通滤波方法。它的原理特别直观:
取最近N个采样点的平均值,作为当前输出值。窗口越大,滤波效果越强,但信号延迟也越大。
我曾经犯过一个错误:为了追求滤波效果,把窗口设到了20个点。结果走路时信号延迟了将近0.5秒,计步数明显滞后。后来我改成10个点,效果就好多了。
下面是我常用的移动平均滤波代码,用Python实现:
def moving_average(data, window_size=10):
"""
移动平均滤波
:param data: 原始加速度数据列表
:param window_size: 滑动窗口大小,默认10
:return: 滤波后的数据列表
"""
filtered = []
for i in range(len(data)):
if i < window_size - 1:
# 窗口未满时,取已有数据的平均值
filtered.append(sum(data[:i+1]) / (i+1))
else:
# 窗口满后,取最近window_size个点的平均值
filtered.append(sum(data[i-window_size+1:i+1]) / window_size)
return filtered
# 使用示例
raw_data = [1.2, 1.5, 1.3, 1.8, 2.1, 1.9, 1.6, 1.4, 1.7, 2.0]
filtered_data = moving_average(raw_data, window_size=5)
print("原始数据:", raw_data)
print("滤波后数据:", filtered_data)
避坑指南:我曾经在STM32上实现这个算法时,忘记处理窗口未满的情况。结果前几个点输出全是0,导致计步算法一开始就误判。记住:窗口未满时,要取已有数据的平均值,而不是补0。
1.4 滤波效果对比
为了让你更直观地理解,我整理了一个对比表格。假设原始信号是1Hz的正弦波,叠加了10Hz的噪声:
| 窗口大小 | 滤波后噪声幅度 | 信号延迟 | 适用场景 |
|---|---|---|---|
| 3 | 降低约30% | 约0.03秒 | 跑步、快速运动 |
| 5 | 降低约50% | 约0.05秒 | 日常步行 |
| 10 | 降低约70% | 约0.1秒 | 慢走、静止检测 |
| 20 | 降低约85% | 约0.2秒 | 不推荐用于计步 |
从表格能看出来,窗口越大,噪声压得越低,但延迟也越大。我个人习惯在计步场景下用5-10的窗口。你想想看,如果延迟超过0.1秒,人走路时手环的反应就会「慢半拍」,体验很不好。
1.5 小结
这一章咱们聊了三个重点:
- 噪声来源:人体运动、传感器自身、环境振动
- 低通滤波原理:保留低频步态信号,滤除高频噪声
- 移动平均滤波实现:简单、高效、适合嵌入式
下一章,咱们会讲步态检测的另一个关键步骤——峰值检测。到时候我会分享一个我踩过的坑:怎么区分「真正的步数峰值」和「手臂抖动产生的假峰值」。嗯,那个坑可让我熬了好几个通宵。
今天就到这儿。代码你可以直接拿去用,但建议根据你的传感器采样率调整窗口大小。采样率100Hz时,窗口10对应0.1秒的延迟,效果不错。采样率50Hz时,窗口可以缩到5。记住:没有万能参数,只有不断调试出来的最佳值。
一句话总结:数据预处理做得好,计步算法成功一半。别急着写步数检测逻辑,先把噪声滤干净。