如何利用Scipy计算含噪变频率正弦波的平均峰峰值电压?
如何利用Scipy计算含噪变频率正弦波的平均峰峰值电压?
嘿,看起来你已经成功用Scipy的find_peaks定位到了含噪正弦波的峰值,效果还不错!要计算平均峰峰值电压其实并不难,咱们可以基于你现有的代码扩展,或者用一些更鲁棒的方法来适配变频率、带噪声的信号,下面给你详细讲讲:
方法一:基于现有峰值检测逻辑扩展
峰峰值的本质是峰值电压与对应谷值电压的差值,所以你只需要同时检测出谷值,再将峰谷配对计算即可:
- 检测谷值:把原始信号反转后,用同样的
find_peaks方法就能得到谷值的位置——毕竟谷值就是反转信号的峰值。 - 配对峰谷:由于信号频率是变化的,咱们可以按顺序取峰、谷数组中长度较小的那个作为配对基准,避免出现不匹配的情况。
- 计算平均峰峰值:算出每一组峰谷的电压差,再取所有差值的平均值。
给你写了个扩展函数,直接就能用:
from scipy.signal import find_peaks import numpy as np import matplotlib.pyplot as plt def calculate_avg_peak_to_peak(data_mV, sampling_rate, signal_frequency): # 复用你原来的距离参数,保证峰谷检测的一致性 distance = (sampling_rate / signal_frequency) - 100 # 检测峰值 peaks, _ = find_peaks(data_mV, distance=distance) # 检测谷值(反转信号找峰值) valleys, _ = find_peaks(-data_mV, distance=distance) # 按顺序配对峰谷,取两者中较短的长度避免不匹配 min_length = min(len(peaks), len(valleys)) peak_voltages = data_mV[peaks[:min_length]] valley_voltages = data_mV[valleys[:min_length]] # 计算每组峰峰值并求平均 peak_to_peak_values = peak_voltages - valley_voltages avg_peak_to_peak = np.mean(peak_to_peak_values) # 可视化验证(可选) plt.plot(data_mV, label="Original Signal") plt.plot(peaks, peak_voltages, "x", color="orange", label="Peaks") plt.plot(valleys, valley_voltages, "o", color="green", label="Valleys") plt.plot(np.zeros_like(data_mV), "--", color="gray") plt.title(f"Average Peak-to-Peak Voltage: {avg_peak_to_peak:.2f} mV") plt.legend() plt.show() return avg_peak_to_peak
方法二:先滤波降噪,再计算(更鲁棒)
虽然你现在的峰值检测效果不错,但噪声可能会在频率变化时干扰谷值的准确性。可以先给信号做低通滤波,滤除高频噪声后再进行峰谷检测,结果会更可靠:
先实现一个简单的巴特沃斯低通滤波器,再用滤波后的信号计算平均峰峰值:
from scipy.signal import butter, filtfilt def butter_lowpass_filter(data, cutoff_frequency, sampling_rate, order=5): nyquist_freq = 0.5 * sampling_rate normalized_cutoff = cutoff_frequency / nyquist_freq # 构建低通滤波器 b, a = butter(order, normalized_cutoff, btype='low', analog=False) # 双向滤波避免相位偏移 filtered_data = filtfilt(b, a, data) return filtered_data # 示例:用信号频率的1.2倍作为截止频率,滤除高于信号的噪声 filtered_data = butter_lowpass_filter(data_mV, signal_frequency * 1.2, sampling_rate) # 用滤波后的信号计算平均峰峰值 avg_pp_voltage = calculate_avg_peak_to_peak(filtered_data, sampling_rate, signal_frequency)
针对你的问题补充一句:Scipy本身没有专门的“计算平均峰峰值”的内置函数,但它提供了find_peaks、滤波工具这些基础组件,咱们完全可以组合出可靠的计算逻辑,适配你这种含噪、变频率的信号场景。
备注:内容来源于stack exchange,提问作者Lukas Petrikas
相关产品推荐
相关产品推荐

