1. 声呐信号时频分析导论

声呐系统通过水声信道获取目标信息,接收到的信号既包含目标回波,也混杂着海洋环境噪声、混响和干扰。要从中提取有用信息,首先必须理解声呐信号在时间与频率两个维度上的分布规律。本章作为全课程的起点,先建立声呐信号类型与特性的基本认识,说明时频分析在声呐系统中的实际作用,并完成Python分析环境的搭建,为后续各章的算法实现打下基础。

一、声呐信号的基本类型与特性

从波形设计角度看,声呐发射信号主要分为两大类:连续波信号(CW)和调频信号(FM)。CW信号在脉冲持续时间内频率恒定,其数学形式可写为 $s(t)=A\cos(2\pi f_0 t)$,$0\le t\le T$。它的优点是产生简单、多普勒容限较好,但距离分辨率受脉宽限制,存在明显的距离—速度模糊。FM信号(最典型的是线性调频LFM)频率随时间线性变化,瞬时频率 $f(t)=f_0+kt$,其中调频率 $k=B/T$,$B$ 为带宽。LFM通过大带宽获得高的距离分辨率,同时保持较长脉宽以积累能量,是主动声呐中应用最广的波形之一。

除波形外,声呐信号还有几个关键特性需要关注。载频决定了信号在水中的传播衰减程度,低频传播远但分辨率低,高频分辨率高但衰减快。带宽直接决定距离分辨率 $\Delta R=c/(2B)$,$c\approx1500\,\text{m/s}$ 为水中声速。脉宽影响能量积累与盲区。多普勒频移 $f_d=2v f_0/c$ 反映目标径向速度,是区分动目标与静止混响的重要依据。此外,实际接收信号还叠加了信道扩展、多途干涉和噪声,这些因素都会在时频平面上留下可辨识的痕迹。

二、时频分析在声呐系统中的作用

传统傅里叶变换给出的是信号在整个时间轴上的全局频谱,无法反映频率成分随时间的变化。而声呐信号恰恰是非平稳的:LFM的频率在脉冲内持续变化,目标回波的出现时刻携带距离信息,多普勒偏移携带速度信息。若只做频谱分析,这些时间定位信息会丢失。时频分析把一维时间信号映射到“时间—频率”二维平面,使信号的瞬时频率轨迹、到达时刻、能量分布同时可见。

在声呐工程中,时频分析主要承担四类任务:其一,信号检测与参数估计,在时频图上识别LFM的斜线轨迹或CW的水平亮线,估计起止频率与脉宽;其二,目标特征提取,不同目标、不同工况的回波在时频域呈现不同的调制样式,可作为分类依据;其三,混响与干扰抑制,利用目标回波与混响在时频域分布差异进行滤波;其四,多普勒与距离联合分析,通过时频脊线斜率与偏移量反演目标运动参数。可以说,时频分析是连接原始采样数据与声呐决策信息的关键桥梁。

声呐信号时频处理链路 发射波形 CW / LFM f₀, B, T 水声信道 多途 / 扩展 噪声 / 混响 接收信号 回波 + 干扰 多普勒 f_d 时频分析 STFT / 小波 / WVD 时间—频率二维图 时频平面示意 时间 t 频率 f LFM 脊线 CW 亮线 背景噪声与混响 信息提取与决策 检测:脊线是否存在 测距:到达时刻 → ΔR = c·t/2 测速:多普勒偏移 → v = c·f_d/(2f₀)

三、Python环境搭建与常用库

本课程全部算法基于Python实现,推荐使用Python 3.10及以上版本,通过Anaconda或venv创建独立虚拟环境,避免依赖冲突。核心依赖只有三个:NumPy负责数组运算与信号采样,SciPy提供滤波、卷积、窗函数和频谱计算,Matplotlib负责时频图与波形可视化。安装命令如下:

python -m venv sonar_env
source sonar_env/bin/activate      # Windows 使用 sonar_env\Scripts\activate
pip install numpy scipy matplotlib

三个库的分工需要明确。NumPy的np.arange、np.sin用于生成采样信号,np.fft提供快速傅里叶变换;SciPy的scipy.signal模块包含stft、spectrogram、hilbert、butter等函数,是时频分析的主力工具;Matplotlib的imshow、pcolormesh用于绘制时频图,specgram可快速出图。下面是一段可直接运行的最小示例,生成一段LFM信号并观察其波形与频谱:

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

fs = 48000          # 采样率 48 kHz
T = 0.05            # 脉宽 50 ms
f0, B = 8000, 4000  # 起始频率 8 kHz,带宽 4 kHz
t = np.arange(0, T, 1/fs)
k = B / T
s = np.cos(2*np.pi*(f0*t + 0.5*k*t**2))   # LFM 信号

f, Pxx = signal.welch(s, fs, nperseg=1024)
plt.subplot(2,1,1); plt.plot(t*1000, s); plt.xlabel('时间/ms')
plt.subplot(2,1,2); plt.plot(f, 10*np.log10(Pxx)); plt.xlabel('频率/Hz')
plt.tight_layout(); plt.show()

运行后应看到:上图为频率逐渐升高的振荡波形,下图功率谱在8~12 kHz区间较为平坦,这正是LFM带宽的体现。若频谱明显偏离该区间,应首先检查采样率是否满足奈奎斯特条件($f_s>2(f_0+B)$),以及时间向量与频率参数是否匹配。建议在正式分析前,先用这段代码验证环境与参数理解是否正确,再进入后续章节的时频算法实现。

学习建议:每章代码都应在同一虚拟环境中运行,并固定随机种子(np.random.seed(0))以便复现噪声条件下的结果。时频图建议统一使用对数幅度(dB)显示,动态范围取60~80 dB,更接近声呐实际观察习惯。