You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何绘制X轴频率准确的信号FFT图?含RTL-SDR信号处理场景

我来帮你搞定这个RTL-SDR信号的频域分析和峰值提取问题!下面是完整的实现方案,从代码补全到峰值提取的细节都给你梳理清楚:

RTL-SDR信号频域分析与峰值提取完整方案

1. 先补全并优化基础采样与PSD绘制代码

你给出的代码片段有小疏漏(比如采样率少了位数),我先把它完善成可直接运行的版本:

import numpy as np
import matplotlib.pyplot as plt
from rtlsdr import RtlSdr

# 初始化RTL-SDR设备
sdr = RtlSdr()

# 配置SDR核心参数
sdr.sample_rate = 2.8e6  # 修正你原来的2.8e,补全为2.8MHz采样率
sdr.center_freq = 434.42e6  # 目标中心频率434.42MHz
sdr.gain = 'auto'  # 自动增益,也可手动设为具体值比如40.0

# 读取采样数据(1M采样点,兼顾速度和精度)
num_samples = 1024 * 1024
samples = sdr.read_samples(num_samples)

# 用完设备记得关闭
sdr.close()

# 绘制PSD(功率谱密度)图
plt.figure(figsize=(10, 6))
# plt.psd会返回4个值:功率谱数组、频率轴数组、绘图线对象、频率范围
psd, freqs, line, _ = plt.psd(
    samples, 
    NFFT=1024,  # FFT点数,决定频率分辨率
    Fs=sdr.sample_rate/1e6,  # 采样率转MHz单位
    Fc=sdr.center_freq/1e6  # 中心频率转MHz单位
)
plt.title('RTL-SDR Received Signal PSD')
plt.xlabel('Frequency (MHz)')
plt.ylabel('Power Spectral Density (dB/Hz)')
plt.grid(True)
plt.show()

2. 核心需求:提取功率高于阈值的峰值坐标

接下来是关键的峰值提取步骤——我们要找到局部最大值且功率超过-20dB/Hz的点,具体实现如下:

代码实现

# 把线性功率谱转换为dB值(plt.psd显示的是dB刻度,但返回的psd是线性值)
psd_dB = 10 * np.log10(psd)

# 定义功率阈值(这里设为你需要的-20dB/Hz)
threshold = -20

# 方法1:用numpy找局部峰值
# np.argrelextrema会返回所有比左右相邻点都大的索引
peak_indices = np.argrelextrema(psd_dB, np.greater)[0]

# 筛选出功率高于阈值的有效峰值
valid_peaks = [
    (freqs[i], psd_dB[i]) 
    for i in peak_indices 
    if psd_dB[i] > threshold
]

# 输出结果
print(f"找到{len(valid_peaks)}个功率高于{threshold}dB/Hz的峰值:")
for freq, power in valid_peaks:
    print(f"频率:{freq:.3f} MHz,功率:{power:.2f} dB/Hz")

# 可选:在PSD图上标记峰值,更直观
plt.figure(figsize=(10, 6))
plt.psd(samples, NFFT=1024, Fs=sdr.sample_rate/1e6, Fc=sdr.center_freq/1e6)
plt.title('PSD with Detected Peaks')
plt.xlabel('Frequency (MHz)')
plt.ylabel('Power Spectral Density (dB/Hz)')
# 画阈值线
plt.axhline(y=threshold, color='r', linestyle='--', label=f'Threshold: {threshold} dB/Hz')
# 标记每个有效峰值
for freq, power in valid_peaks:
    plt.scatter(freq, power, color='red', marker='o', s=50, zorder=5)
plt.legend()
plt.grid(True)
plt.show()

进阶优化:更灵活的峰值检测

如果需要更精准的峰值过滤(比如避免太近的峰值被重复检测),可以用scipy.signal.find_peaks,它支持更多参数:

from scipy.signal import find_peaks

# 设置最小高度(阈值)和最小峰距(避免相邻小峰值)
peaks, properties = find_peaks(psd_dB, height=threshold, distance=20)
valid_peaks_scipy = [(freqs[i], psd_dB[i]) for i in peaks]

# 输出结果
print(f"用scipy找到{len(valid_peaks_scipy)}个有效峰值:")
for freq, power in valid_peaks_scipy:
    print(f"频率:{freq:.3f} MHz,功率:{power:.2f} dB/Hz")

3. 关键细节提醒

  • 采样率与NFFT:NFFT越大,频率分辨率越高,但计算量也会增加,1024是兼顾速度和精度的均衡选择。
  • 增益调整:如果信号太弱,可手动设置增益(比如sdr.gain = 40.0),auto增益适合大多数场景,但手动调整可能获得更干净的信号。
  • 噪声处理:如果PSD图噪声过大,可以增加采样点数(比如num_samples = 2*1024*1024),或者尝试降低增益。

内容的提问来源于stack exchange,提问作者ci7i2en4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:34:52