如何使用Python从手指按压传感器的时序数据中识别周期?
基于Python的时序信号周期识别解决方案
一、数据预处理建议
如果原始数据噪声较大,建议先恢复未置0的原始数据,再做降噪处理:
- 滑动窗口平均:简单平滑,适合低噪声场景
- Savitzky-Golay滤波:保留信号趋势的同时降噪,适配周期性信号
示例代码(Savitzky-Golay滤波):
import numpy as np from scipy.signal import savgol_filter # raw_data 为原始时序数据 filtered_data = savgol_filter(raw_data, window_length=51, polyorder=3)
若必须使用置0后的数据,先通过掩码剔除连续0段,仅保留有效信号段再开展分析。
二、周期识别核心方法
1. 自相关分析法
周期信号的自相关函数会在周期整数倍的滞后位置出现峰值,找到最大峰值对应的滞后值即可得到周期。
示例代码:
import numpy as np import matplotlib.pyplot as plt def find_period_via_autocorrelation(data): # 计算自相关 autocorr = np.correlate(data, data, mode='full') # 截取正滞后部分 autocorr = autocorr[len(autocorr)//2:] # 定位峰值(跳过滞后为0的初始峰值) peaks = np.where((autocorr[1:-1] > autocorr[:-2]) & (autocorr[1:-1] > autocorr[2:]))[0] + 1 # 返回第一个显著峰值对应的滞后作为周期 return peaks[0] if len(peaks) > 0 else None # filtered_data 为预处理后的信号 period = find_period_via_autocorrelation(filtered_data) print(f"识别到的周期长度:{period}") # 可视化自相关结果 plt.plot(autocorr) plt.scatter(peaks, autocorr[peaks], c='r') plt.show()
2. FFT频域分析法
将信号转换至频域,定位能量最高的频率成分,周期为该频率的倒数。
示例代码:
import numpy as np def find_period_via_fft(data, sampling_rate): # 计算FFT fft_vals = np.fft.fft(data) fft_freqs = np.fft.fftfreq(len(data), 1/sampling_rate) # 筛选正频率部分 positive_freq_mask = fft_freqs > 0 fft_vals_pos = np.abs(fft_vals[positive_freq_mask]) fft_freqs_pos = fft_freqs[positive_freq_mask] # 找到能量最大的主频率 dominant_freq = fft_freqs_pos[np.argmax(fft_vals_pos)] # 计算周期(单位随采样率定义,可为秒或采样点数) period = 1 / dominant_freq return period # sampling_rate 为信号采样率(如每秒采集点数) period = find_period_via_fft(filtered_data, sampling_rate=100) print(f"识别到的周期:{period:.2f} 秒")
3. 峰值间隔统计法
按压信号的每个周期通常带有明显峰值,检测所有峰值位置后,统计最频繁出现的峰值间隔即为周期。
示例代码:
from scipy.signal import find_peaks import numpy as np from collections import Counter def find_period_via_peaks(data): # 检测峰值(需根据信号特征调整height、distance参数) peaks, _ = find_peaks(data, height=np.mean(data)+np.std(data), distance=50) # 计算峰值间隔 peak_intervals = np.diff(peaks) # 统计最常见的间隔 if len(peak_intervals) > 0: counter = Counter(peak_intervals) most_common_interval = counter.most_common(1)[0][0] return most_common_interval return None period = find_period_via_peaks(filtered_data) print(f"识别到的周期长度(采样点数):{period}")
三、注意事项
- 预处理是关键:噪声会严重干扰周期识别,优先使用原始数据完成降噪
- 多方法交叉验证:单一方法结果不稳定时,可结合两种以上方法的结果取共识
- 参数适配:需根据实际信号特征,调整滤波窗口、峰值检测的height/distance等参数
内容的提问来源于stack exchange,提问作者asdzxsad
相关产品推荐
相关产品推荐

