2. 步态周期检测基础
任务说明
本案例基于单轴加速度计(垂直方向,记为Acc_z)采集的步行数据,通过分析加速度波形中的周期性峰值特征,实现步态周期检测。输入为一段连续采样的加速度序列,输出为检测到的步态周期数量及每个周期的起止时间索引,用于后续步数计数与步态分析。
实现方案
步态周期检测的核心在于识别加速度波形中周期性出现的波峰。正常步行时,垂直加速度在每个步态周期内会出现一个明显的主波峰(脚触地时的冲击响应)。本案例采用以下处理流程:
- 信号预处理:对原始加速度序列进行滑动窗口均值滤波,抑制高频噪声,避免误检;
- 峰值检测:在滤波后的波形中寻找局部极大值点,要求该点值大于相邻采样点,且高于动态阈值(基于信号均值和标准差计算);
- 周期划分:相邻两个有效波峰之间的区间即为一个步态周期,记录起始与结束索引。
代码中内置一组模拟步行加速度数据(采样率50Hz,时长10秒,包含8个完整步态周期),用于演示完整的检测流程。检测结果以周期索引列表形式输出,便于直观验证。
代码实现
import numpy as np
def generate_walk_data(fs=50, duration=10.0, steps=8):
"""生成模拟步行垂直加速度数据(含噪声)"""
t = np.arange(0, duration, 1/fs)
n = len(t)
# 基础步态波形:主峰 + 次峰(近似)
base = np.zeros(n)
step_period = duration / steps
for i in range(steps):
center = int((i + 0.5) * step_period * fs)
# 主峰(高斯形状)
base[center] += 1.2
# 次峰(较小)
if center + int(0.15*fs) < n:
base[center + int(0.15*fs)] += 0.4
# 平滑并添加噪声
from scipy.ndimage import gaussian_filter1d
smooth = gaussian_filter1d(base, sigma=3)
noise = np.random.normal(0, 0.05, n)
acc = smooth + noise + 9.8 # 叠加重力偏置
return t, acc
def moving_average(x, window=5):
"""滑动均值滤波"""
kernel = np.ones(window) / window
return np.convolve(x, kernel, mode='same')
def detect_gait_cycles(acc, fs=50, min_peak_dist=0.3):
"""
步态周期检测
参数:
acc: 垂直加速度序列
fs: 采样率(Hz)
min_peak_dist: 最小峰间距(秒),用于排除伪峰
返回:
cycles: 列表,每个元素为(起始索引, 峰值索引, 结束索引)
"""
# 1. 滤波去噪
filtered = moving_average(acc, window=5)
# 2. 动态阈值
mean_val = np.mean(filtered)
std_val = np.std(filtered)
threshold = mean_val + 0.5 * std_val
# 3. 峰值检测
min_dist_samples = int(min_peak_dist * fs)
peaks = []
n = len(filtered)
for i in range(1, n-1):
if filtered[i] > threshold:
if filtered[i] >= filtered[i-1] and filtered[i] > filtered[i+1]:
# 检查与上一个峰的最小距离
if len(peaks) == 0 or (i - peaks[-1]) >= min_dist_samples:
peaks.append(i)
# 4. 构建周期区间
cycles = []
for j in range(len(peaks)-1):
start = peaks[j]
end = peaks[j+1]
cycles.append((start, peaks[j], end))
return cycles
# ---------- 主程序 ----------
fs = 50 # 采样率 50Hz
t, acc_data = generate_walk_data(fs=fs, duration=10.0, steps=8)
# 执行检测
cycles = detect_gait_cycles(acc_data, fs=fs)
# 输出结果
print(f"采样点数: {len(acc_data)}")
print(f"检测到步态周期数: {len(cycles)}")
print("周期区间(起始索引, 峰值索引, 结束索引):")
for idx, (s, p, e) in enumerate(cycles):
print(f" 周期{idx+1}: ({s}, {p}, {e}) 时长: {(e-s)/fs:.2f}s")
运行与验证
运行方式:将上述代码保存为 gait_cycle_detect.py,在已安装 numpy 和 scipy 的Python环境中执行 python gait_cycle_detect.py。
验证方法:程序输出检测到的周期数量与区间索引。由于内置数据生成时设定了8个步态周期,且峰值检测算法基于波形特征,预期输出周期数为7(相邻峰构成完整周期区间)。若检测结果在6~8之间(受噪声影响可能略有偏差),说明算法正确识别了周期性步态特征。可通过调整 generate_walk_data 中的 steps 参数(如改为5或10)重新运行,观察检测数量是否随之线性变化,以验证算法的鲁棒性。
判定标准:检测到的周期数量与设定步数相差不超过1,且每个周期时长在合理步态范围(0.8s~1.5s)内,即判定检测通过。
检测流程示意
关键说明
本案例聚焦于步态周期检测的核心算法实现。代码中的模拟数据仅用于验证算法逻辑,实际应用时可将 acc_data 替换为真实传感器采集的加速度序列(需保证采样率一致)。检测算法对噪声和幅值变化具有一定的鲁棒性,但若实际信号存在剧烈漂移或异常冲击,建议先进行带通滤波(如0.5~5Hz)预处理,以提升检测稳定性。当前实现未包含该预处理步骤,如需处理复杂真实信号,可在此基础上扩展滤波模块。