第一章 数据预处理:噪声来源分析、低通滤波原理、移动平均滤波实现

各位同学好,我是你们的嵌入式系统讲师。今天咱们来聊聊计步算法里最基础、也最容易被忽视的一环——数据预处理。

说实话,我刚开始做计步算法时,踩过最大的坑就是「数据没洗干净」。你想想看,手环戴在手腕上,走路、甩手、甚至打字都会产生加速度信号。如果不做预处理,算法会把「甩手」误判成「走路」。嗯,这问题我当年在项目里可没少头疼。

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。记住:没有万能参数,只有不断调试出来的最佳值。

一句话总结:数据预处理做得好,计步算法成功一半。别急着写步数检测逻辑,先把噪声滤干净。