赞
踩
链接:【雷达抗干扰】Radar-STDA:一种用于FMCW雷达干扰抑制的高性能空时去噪自编码器【附Python代码】
毫米波雷达体积小、成本低、全天候工作,与其他交通传感器相比,它可以精确测量目标的距离、方位角和径向速度。然而,在实际应用中,毫米波雷达受到各种干扰的困扰,导致目标检测精度下降,甚至无法检测到目标。这在自动驾驶车辆和交通监控中是不可取的,因为它可能威胁人类生命并造成财产损失。因此,抑制干扰对毫米波雷达目标检测具有重要意义。目前,深度学习发展迅速,但现有的基于深度学习的干扰抑制模型在模型规模和推理速度方面仍然存在很大的局限性。出于这些原因,我们提出了RadarSTDA,雷达空间时间去噪自动编码器。RadarSTDA是一种高效的纳米级去噪自动编码器,它考虑了距离多普勒地图的空间和时间信息。在其他方法中,它仅用140,000个参数就实现了17.08 dB的最大SINR。它在RTX A4000 GPU上获得207.6 FPS,在NVIDIA Jetson AGXXavier上获得56.8 FPS,分别对三个连续帧的距离多普勒图进行去噪。此外,我们还为这项任务发布了一个名为Ra-inf的合成数据集,其中包括384,769个距离多普勒地图,其中包含来自不感兴趣的物体的各种杂波和现实场景中的接收器噪声。据我们所知,Ra-inf是第一个雷达干扰的合成数据集。FMCW雷达,干扰抑制,距离多普勒图,去噪自动编码器,空间和时间信息融合,轻量级神经网络,合成数据集毫米波雷达是交通领域的重要传感器,其中最常用的调制方式之一是调频连续波(FMCW)。它可以探测目标的距离、方位、速度和雷达散射截面(RCS)。雷达具有很强的穿透灰尘和烟雾的能力。与摄像头和激光雷达相比,雷达在黑暗环境和恶劣天气下更加强大[1],而且成本相对较低。此外,雷达的小尺寸使其易于安装和部署。随着人工智能的快速发展,它可以使自动驾驶汽车和智能交通系统中的传感器更加智能。对于自动驾驶车辆,高检测灵敏度是在各种情况下保证人身和财产安全的必要条件,例如,自适应巡航控制和自动紧急制动。对于智能交通系统,准确感知交通流可以帮助交通管理人员做出更合理的决策。然而,由于汽车雷达传感器数量的迅速增加和有限的带宽,有可能引起相互干扰。因此,干扰会导致传感器在现实中的严重退化以及噪声和杂波。有许多方法可以避免干扰,例如标准化,“感知和避免”和极化。然而,在许多情况下,不可能完全避免相互干扰。在这种情况下,使用定位后进行缓解的方法来减少退化,例如归零[2],自适应阈值迭代方法(IMAT)[3]和斜坡滤波[4]。之后,开发了更复杂的算法,包括计算时间减少的压缩感知[5],具有小波去噪的时域低通滤波器[6][7]和基于CFAR的干扰缓解[8]。然而,通过分析和探索上述方法,我们已经确定了基于信号处理的传统干扰抑制方法的许多缺点和限制。首先,基于信号处理的方法通常是两个阶段,包括干扰检测和干扰去除。干扰检测方法是干扰消除的关键。其次,它们缺乏自适应性,在面对各种干扰时依赖于手动超参数。第三,在某些情况下,基于信号处理的方法去除了部分有用信息,导致目标峰值失真。基于深度学习(DL)的方法不会对噪声和干扰的数据进行事先假设,这可能会导致直接处理数据并保持最有用的信号,在严重干扰条件下优于传统方法。例如,Jiwoo Mun et.al [9]在三层递归神经网络(RNN)中引入了自注意机制,并在时域中恢复了差拍信号。然而,在网络中没有使用频域信息。在[10]中,研究人员进行了离散短时傅立叶变换(STFT)以获得时频频谱图,然后通过完全卷积神经网络进行训练。他们还在[11]中发布了一个大规模的模拟数据集作为开源。Rock和Fuchs [2]提出使用复值卷积神经网络(CVCNN)来解决相位丢失问题。此外,他们提出了一种量化的卷积神经网络,以降低内存占用率和计算复杂度[12],从而实现边缘设备上的实时处理。然而,首先,大多数当前基于DL的方法采用简单的全卷积网络作为去噪自编码器。考虑到卷积的权重共享性质,在去噪结果中仍然保留许多噪声和干扰的特征是没有意义的。其次,距离-多普勒(RD)图的信噪比太低,在某些情况下无法恢复目标峰值。第三,很少的训练数据将导致自动编码器的过拟合,并且恢复的距离-多普勒图将与地面实况显著不同。最后但并非最不重要的是,几乎所有的作品都没有考虑模型在不同设备上的实时性能和实用性。因此,干扰抑制仍然是当今工业和研究的巨大挑战。为了解决这些问题,我们提出了一个有效的去噪自动编码器命名为雷达STDA的距离-多普勒地图的干扰缓解。此外,我们发布了一个名为Ra-inf的合成数据集,用于与RaDICaL相结合的干扰缓解[13]。我们的贡献如下,1)我们发布了一个数据集,称为Ra-inf与现实世界的数据合成的干扰缓解,这是接近现实的测量,从而拥有更好的性能相比,纯粹的模拟数据集的泛化。2)通过仿真分析了FMCW干扰参数对受扰信号的影响。它表明,根据几个参数的相对值可以形成各种图案,例如,扫描持续时间、扫描带宽和载波频率。3)我们提出了一种纳米级但高效的去噪自动编码器,称为Radar-STDA。在Radar-STDA中,我们设计了一个轻量级的编码器(解码器)架构,称为移动的编码器(解码器)。Radar-STDA算法自适应地融合了空间信息和时间信息,并得到了17.08 dB的信干噪比(SINR)。它优于其他基于信号处理的模型和基于DL的正常模型。4)Radar-STDA只有14万个参数,远远少于任何其他去噪自动编码器,并且易于部署。在RTX A4000 GPU上获得207.6 FPS,在NVIDIA Jetson AGX上获得56.8 FPS Xavier在对三个连续帧的距离-多普勒图进行去噪时。
随着深度学习技术的快速发展,去噪自动编码器被应用于汽车雷达的干扰抑制。[14]采用常规卷积神经网络对距离-多普勒图进行去噪处理。[15]采用常规的卷积神经网络对距离像图和距离多普勒图进行去噪。[16]提出了CAE算法,同时引入空间和时间信息进行降噪,可以取代恒虚警和峰值检测运算。[17]设计了一个基于UNet [18]的神经网络,用于基于生成对抗网络的微多普勒图的去噪和重建。此外,边缘设备上的快速推断在许多流量场景中是重要的。满足要求的神经网络(NN)通常只有很少的参数。MobileNet V1 [19]采用了依赖可分离卷积来显著减少参数数量。MobileNet V2 [20]使用具有线性激活的反转残差块。MobileNet V3 [21]将神经架构搜索引入到网络中,并引入了一个轻量级的注意力模块,称为挤压和激励(SE)。ShuffleNet [22]采用逐点组卷积和通道混洗,可以在保持准确性的同时大大减少神经网络的计算负担。
快速线性调频FMCW调制作为经典FMCW调制的一种变体,由于其简单的信号去线性调频过程和相对较低的模数转换器(ADC)要求,常用于商用汽车雷达系统中。随着装备毫米波雷达的车辆数量的增加,相互干扰也随之发生。在雷达信号处理中,通常通过计算距离-多普勒响应来进行目标检测和频域运算。不可忽视的是,与相同条件下的对象相比,更强的干扰可能会导致较大的影响,例如虚警或漏检。因此,干扰抑制已成为一项重要的任务。
在典型的快速线性调频FMCW雷达系统[23]中,雷达传感器发射线性频率啁啾序列,也称为斜坡。线性调频脉冲的频率遵循一种双线性模式,如图1所示。具有载波频率fc、扫描带宽BSW和扫描持续时间Tc的每个线性调频信号的频率表示为:
其中,0 ≤ t < Tc表示快时间维度中的时间变量,BSW Tc可以写为啁啾率α。具有M个重复线性调频脉冲的对应发射信号可以写为
图1.FMCW雷达原理图
其中Δ T是发射信号的幅度,0 ≤ m ≤ M表示慢时间维度中的啁啾指数,Δ T是信号的初始相位。由于在接收器处的往返时间延迟τ是由目标反射引起的,因此单个目标的第m个接收到的线性调频信号为:
其中AR表示接收幅度,τ = 2(D + Vt)/c。这里,D和v分别表示目标和传感器之间的距离和相对径向速度,c是光速。随后,通过将xR(t,m)的共轭与发射信号xT(t,m)混频来获得中频(IF)处的拍频信号,计算如下:
在低通滤波器(LPS)和采样频率为1/Ts且每个线性调频脉冲有N个样本的ADC之后,离散差拍信号可以近似为[24]
其中,0 ≤ n ≤ N,并且2v/c fC可以表示为由目标运动引起的多普勒频移fD。考虑到相互干扰信号线性叠加在多次反射上,
其中NO和NI分别对应于目标的数量和干扰传感器的数量,并且v(n,m)是由复值高斯白色噪声近似的接收器热噪声。从第i个干扰信号sI,t(t)采样sI,i(n,m),其被定义为
其中xInt,i(t-t τi)是具有时间延迟τi的第i个干扰信号。
再次考虑(5)中的IF信号s(n,m)。{s(n,m),0 ≤ n < N,0 ≤ m < M}的集合构成一个N×M的数据矩阵。因此,可以首先在快时间维度上对矩阵执行二维快速傅里叶变换(2DFFT),然后在慢时间维度上执行行式傅里叶变换。结果被称为距离多普勒(RD)图,如下所示,
这里,0 ≤ p < P且0 ≤ q < Q。P和Q是列傅立叶变换中的点数和水平变换中的点数。根据(7),我们可以在(4)中的2BSWD/ cTc的频率处检测到峰值,这意味着目标与雷达传感器之间的径向距离。在如(8)中所计算的跨慢时间维度应用傅立叶变换之后,可以在频率2fc/v c处获得说明相对径向速度的峰值。因此,我们可以同时估计RD地图上每个目标的距离和速度[25]。
通常,干扰功率比从目标反射的期望信号强得多,因为干扰波是单向传播的,而反射波是双向传播的。Friis自由空间中的接收干扰功率和雷达方程为:
其中r是目标和被攻击雷达之间的距离,d是目标和雷达之间的距离,PT是发射功率,Gtrx是发射和接收天线的组合增益,σ是目标的RCS [26]。因此,当r和d相似时,干扰功率超过具有典型RCS值的信号功率,也就是Pint_rtp。此外,干扰的影响取决于干扰样本的总功率以及受害者和攻击者雷达之间的相干程度[27]。
表1 模拟受害者和攻击者的通用雷达系统参数
表2 七种典型情景的定量干扰分析
这里我们只考虑FMCW雷达对FMCW雷达的干扰。为了验证我们的分析,我们在表I中显示了基于雷达系统参数的各种仿真结果。利用MATLAB雷达仿真软件生成受害信号和干扰信号。对于FMCW雷达,根据表II调整扫描带宽、扫描持续时间和载波频率,其中中间两行中的数字表示干扰雷达和受害雷达的斜坡之间的比率。例如,1.1 = BSWint/BSWvic。最后一列中的数字表示干扰斜坡和受干扰斜坡的载波频率之差。图2示出了用于典型干扰场景的RD图。在模拟中,没有干扰的原始RD地图由左侧的一个目标组成。从场景(1)和场景(7)可以看出,当参数相同或整数倍时,干扰表现为目标,称为重影。场景(5)解释了调整干扰的载波频率很少影响接收信号。由于干扰的扫描持续时间在(2)和(6)中略有不同,因此干扰功率分布在整个频谱上,导致噪声基底增加。在场景(3)中,由于扫描持续时间的整数倍,RD图上存在“脊”。当如(4)中给出的那样调整扫描带宽时,出现类似的现象。因此,在上述情况下,可能会出现目标丢失或虚警,抑制干扰是必不可少的。
Radar-STDA是一种高效的轻量级去噪自编码器,用于雷达干扰抑制,全称为Radar-Spatial Temporal Denoising Autoencoder。它是用于干扰减轻和受害雷达的距离-多普勒图恢复。Radar-STDA的特点和优点如下:1)该算法在在线模式下融合距离-多普勒图的空间和时间信息,以抑制距离-多普勒图的干扰。2)采用有效的信道注意(ECA)策略,自适应地抑制干扰。3)它是一个具有快速推理速度的纳米级去噪自动编码器,易于部署并在边缘设备上运行。
图2.变化干涉现象的距离多普勒图
如图3所示,Radar-STDA中有四个模块,分别是输入、编码器、解码器和输出。Radar-STDA采用三个相邻帧的三个距离多普勒图作为编码器h(·)的输入,其在等式1中示出。11.
其中y是编码器h(·)的输出。{xt,xt-1,xt-2}是编码器h(·)的输入,其是在帧t、t-1和t-2处具有干扰的距离-多普勒图。编码器将特征图从低维空间变换到高维空间。解码器f(·)用于去除干扰并尽可能地恢复帧t处的原始距离-多普勒图。整个过程在Eq.12.
图3.雷达-STDA的体系结构。实验中得到的距离-多普勒图的形状均为1 × 128 × 64。
除了传统的去噪自动编码器之外,我们的Radar-STDA将三个时间相邻帧的距离-多普勒图作为输入,其中包括当前帧和前两帧的距离-多普勒图。这是一个在线去噪模式,雷达STDA可以运行在真实的时间。如图4所示,在某些情况下,距离多普勒的信号干扰噪声比(SINR)较低。直觉上,在帧t处的距离-多普勒图中的目标不能被识别。因此,我们需要先前帧处的距离-多普勒图来辅助帧t处的图的恢复。更确切地说,雷达-STDA从通道的维度连接三个距离-多普勒图。假设输入映射是xt,xt−1,xt−2 ∈ Rc×h×w,则级联操作如等式所示。13.
从另一个角度来看,多帧信息意味着距离多普勒图的特征中存在各种干扰,因为不同的帧中可能存在不同的干扰。因此,在训练过程中,RadarSTDA需要尽可能地去除各种干扰,这间接增强了RadarSTDA的干扰抑制和地图恢复能力。
图4.一批三个距离-多普勒图,在三个时间相邻帧处具有干扰。帧t gt是帧t处的距离-多普勒图的地面实况,其是没有干扰的原始距离-多普勒图。
卷积自动编码器(CAE)[16]和其他基于卷积的去噪自动编码器[14][15]都采用正常卷积(去卷积)和最大池的组合。从我们的角度来看,这种组合有两个缺点。第一,正常卷积(去卷积)具有许多冗余参数,这些冗余参数可能代表噪声信号。其次,最大池算法会导致严重的信息丢失。在此基础上,我们设计了一种新颖有效的Radar-STDA编解码器模块组合,即移动的编(解码)器模块和高效信道注意(ECA)模块。受MobileOne [28]的启发,我们设计了一个低成本和高性能的编码器块,称为移动编码器块。在移动的编码器块中,特征图Xi ∈ Rc×h×w将首先由三个不同的分支处理。第一个分支x i 1是具有1 × 1核大小(Conv 1 ×1)和批归一化操作(BN)的卷积。第二个分支x i 2是具有3 × 3核大小(Conv3×3)和批归一化操作的卷积。第三个分支函数Xi 3是一个批量归一化运算,它可以被看作是一个短的剩余边。之后,这三个分支的输出将按元素相加。之后,ReLU将激活特征图Xi+1 [29]。整个过程在Eq14.中显示。
图5.CAE和雷达-STDA单元的比较。
之后,特征图Xi+1将通过3 × 3核大小和步长为2的卷积运算(Conv3×3−2),扩展特征维度并扩大感受野。然后,接下来是批量归一化操作(BN)和ReLU [29]。最后,将在原始特征图Xi的长残差侧添加具有3×3核大小和步长为2(Conv 3 ×3−2)的卷积运算的特征图。长残差可以有效地缓解梯度爆炸和消失。整个过程在Eq中显示。15.
图6.移动的编码器块和移动的解码器块的结构。
其中Xi+2 ∈ R2c×h 2 ×w 2是移动的编码器块的最终输出。移动的解码器块具有与移动的编码器块相同的架构。唯一的区别是所有的卷积操作都被去卷积操作(DeConv)所取代。假设移动的解码器块的输入特征图是xj ∈ R2c×h 2 ×w 2。移动的解码器块也可以被划分为2个级,其在等式(1)中示出。16、Eq.17.
然而,由于卷积核的权值共享,目标和干扰共享公共卷积核,这是不合理的。对于去噪自动编码器,只有移动的编码器(解码器)块是不够的,因为在前向传播中有许多包含噪声的特征图。因此,自动编码器必须有选择地重视具有目标信息的特征图,而尽可能地忽略具有干扰的特征图。在此基础上,我们巧妙地采用有效的通道注意(ECA),以帮助编码和解码的特征映射自适应。如图7所示,包含目标和干扰的特征图m ∈ Rc×h×w将首先通过全局平均池化操作(GAP)进行处理,其结果是m ∈ R1×1×C。然后将m ∈ R1×1×C用一个sigmoid函数进行一维卷积处理,计算m ∈ Rc×h×w中每个通道的权重,我们称加权通道矩阵为Wm ∈ R1×1×C。最后,特征图m ∈ Rc×h×w和加权信道矩阵Wm以逐元素乘积的格式相乘。其结果是加权通道特征映射图m ∈ Rc×h×w。整个过程在Eq18.中显示。
其中σ表示sigmoid函数
图7.有效的信道注意(ECA)块,以消除距离-多普勒地图上的干扰自适应。
在编码器和解码器的模块之间,有两个跳过连接,其中解码器模块中的特征图将被编码器模块中相同大小的特征图添加。跳跃连接首先可以有效地缓解模型训练过程中的梯度消失现象;其次,跳跃连接可以将联合收割机中的多尺度特征融合到模型中。它可以使解码器在解码过程中在编码器的辅助下找到正确的优化方向。
由于在实际中,特别是对于动态场景,难以获取受干扰的雷达回波和相关参考文献,因此没有可用的真实世界数据集用于干扰抑制任务。然而,由于现实环境中缺乏杂波和背景噪声,用模拟数据集训练的模型在实际应用中可能表现不佳。在本文中,我们决定合成真实世界的数据与模拟干扰信号的建议的神经网络训练,然后采用合成和测量数据进行测试。
对于数据生成,我们考虑RaDICaL[13]的子集作为受害者信号,这给出了表III中描述的雷达配置参数的全面列表。该子集是从驾驶汽车内的毫米波雷达收集的,该汽车是来自Texas Instrument的AWR 1843 BOOST型号。驾驶的道路是无数的社区,郊区,高速公路和城市道路。这些视图显示了迎面而来的交通,进入的障碍物,街道标志,护栏(如果存在),以及来自汽车发动机和引擎盖的反射,如图8所示。
图8.三个示例图像对应于来自RaDICaL数据集的雷达信号。
表3 从自由基开放源代码收集的受害者雷达参数
表4 用于产生干扰信号的干扰雷达的参数
为了模拟单一干扰源的各种场景,通过蒙特-卡罗仿真从均匀分布的间隔中选择一些参数,例如扫描带宽和干扰距离。干扰信号的每个参数的详细区间见表IV。此外,干扰幅度由信号干扰噪声比(SINR)以5dB的固定步长从-5dB缩放到25 dB。然后,FMCW传感器通过MATLAB R2021 b雷达收发器发送模拟干扰信号,并根据5叠加到受害者信号。在时域数据合成后,通过64 × 128维的2D-FFT计算干扰信号的RD图。类似地,在原始信号上实现2D-FFT,从而得到相关联的参考的RD图。由于来自汽车发动机和引擎盖的强杂波在零距离和速度轴附近的RD图中表现为重影,我们通过阈值来过滤它们。在子集中总共有六个序列,包括54,967帧。然后基于上述SINR的各种值将每个帧与七个干扰幅度组合。增强数据集包含384,769帧,这些帧是标准化和归一化的。要通过我们的Radar-STDA进行训练,三个连续的帧构成一个样本。最后,我们有一个包含128,247个样本的数据集,并将其随机分为三个分区,分别用于训练(60%),验证(20%)和测试(20%)。与纯模拟数据集相比,合成数据集涵盖了复杂的环境,例如来自静态建筑物和雷达传感器本身的杂波。另一方面,没有干扰的测量信号可以被视为参考,通过标记受干扰的测量几乎无法访问。
对于绩效评估,我们用定量和定性指标来检查结果。这些定量度量之一是SINR,其由以下比率定义:目标处的平均功率达到噪声基底的峰值[30]。在2维RD映射中,SINR被计算为
其中n和m是RD矩阵的行和列索引,O是目标峰值的集合,N是噪声单元的集合。误差矢量幅度(EVM)是另一个定量指标,定义为干净RD图SRD,clean和噪声降级RD图S_RD之间的误差矢量的幅度[30]:
表5 雷达-STDA的训练设置
虽然SINR给出了关于检测概率的信息,但EVM测量检测到的对象属性中的失真,即对象峰值的幅度和相位。因此,干扰抑制的目标是最大化SINR和最小化EVM。第三,由于单元平均恒定虚警率(CA-CFAR)[31]被用作去噪RD图上的峰值检测器,因此我们使用平均精度(AP)来测量正确检测到的对象与峰值总数的比率。在数学上,AP可以定义为
其中Ncd是正确检测到的峰的数量,N是参比品中的总峰的数量。此外,RD图的目视检查。此外,通过观察目标峰值和噪声本底强度以及目标分辨率和峰值失真,将RD图的目视检查视为定性测量方法。
如表V所示,我们在两个RTX A4000 GPU上训练Radar-STDA,批量大小为16。它被训练了100个epoch,初始学习率为0.01。我们使用AdamW [32]作为优化器,权重衰减为5e-4,步进退火作为调度器。
为了比较分析所提出的基于自动编码器的架构,选择了两种经典的方法:归零和IMAT。此外,我们认为多层感知(MLP)和卷积自动编码器(CAE)作为基于DL的比较方法。
表VI指示了不同方法的每个度量的值,其中标记是没有干扰的原始信号。可以看出,我们的雷达STDA显示出更好的性能相比,其他方法。对于传统的方法,我们的网络的信干噪比是7.34%和5.01%,分别高于归零和IMAT。此外,我们的雷达STDA优于两个基于DL的方法的4.14%和1.36%的信干噪比。
表6 与干扰缓解最新技术水平研究的性能比较
由于EVM测量了两个对象在基础事实和推理中的相似性,因此较低的值意味着更小的差异。表VI中的EVM值表明,由于注意机制和时间信息对任务的出色影响,我们的方法获得了最好的结果,为0.1792,其次是两种基于DL的方法。对于AP计算,CA-CFAR用于检测RD图中的峰值,然后通过DBSCAN对这些峰值进行聚类[33]。此外,RD标测图中的目标由注释生成器标记[34]。Radar-STDA的平均精度为87.15%,达到了所有方法中最好的结果。总之,Radar-STDA在干扰抑制方面超过了最先进的算法。
图9显示了地面实况、干扰和五种去噪方法的距离-多普勒图。对于基于信号处理的方法,IMAT优于调零,这使得目标峰值更明显。对于基于DL的方法,我们可以看到每个模型都可以去除噪声,使距离-多普勒图平面平坦和光滑。然而,AECNet(MLP)和CAE [15]错误地将目标峰沿着移除干扰。相比之下,Radar-STDA成功地保持了所有目标峰值。
图9.五种不同去噪方法的去噪结果。
图10示出了RadarSTDA的干扰减轻结果。如我们所看到的,帧T(第一列)处的距离-多普勒图具有低SINR,并且无法识别目标峰值。通过融合帧T-1和T-2(第二列和第三列)的距离-多普勒图,可以恢复并容易地识别雷达-STDA降噪距离-多普勒图中的目标峰值(最后一列)。此外,不同帧的特征融合使得Radar-STDA在训练时需要处理三帧的干扰和噪声,这比帧T的干扰和噪声要多得多。它间接地增强了雷达-STDA抑制干扰和原始噪声的能力。
图10.Radar-STDA去噪结果。可视化是通过OpenCV的imshow()函数实现的。第一列、第二列和第三列列出了在帧T、T-1和T-2处具有干扰的距离-多普勒图。第四列列出了无干扰情况下的距离-多普勒图的地面真值。最后一列列出了雷达-STDA的去噪距离-多普勒图。
如表VII所示,与CAE [15]和AECNet(MLP)相比,我们的Radar-STDA只有14万个参数,在干扰期间占用很少的内存。Radar-STDA在一个RTX A4000 GPU上达到207.57 FPS,以消除一个距离多普勒地图的噪声,速度较慢比CAE(238.42 FPS)和AECNet(MLP)(1715.11 FPS),因为雷达-STDA采用三个距离-多普勒地图作为并行输入。相比之下,CAE [15]和AECNet(MLP)仅采用一个距离多普勒地图作为输入,这在高性能GPU设备上会更快。由于Radar-STDA采用了完全独立的可分离卷积运算,因此在硬件设备的哈希率有限的情况下,它可以比普通卷积模型运行得更快。因此,可以观察到Radar-STDA在一个i7-12700 CPU和NVIDIA Jetson AGX Xavier(边缘设备)上的运行速度比CAE [15]更快。Radar-STDA在一个i7-12700 CPU和NVIDIA Jetson AGX Xavier上分别获得31.67和56.82 FPS。相比之下,CAE [15]在两个设备上实现了24.19和48.63 FPS。此外,AECNet作为一个完整的MLP架构模型,在三种不同的设备上具有最快的推理速度。然而,AECNet(MLP)在干扰缓解方面的性能比CAE [15]和Radar-STDA(表VI)差。总而言之,Radar-STDA具有纳米级的参数大小,可以在不同的设备上实时推断。
表7 不同器械上基于DL的模型的列表
在本文中,我们研究的影响FMCW雷达传感器之间的干扰,“脊”,“鬼目标”和“增加噪声地板”可能是由于不同的啁啾配置。在任务研究中,为了获得更接近现实的环境,发布了称为Ra-inf的合成数据集。此外,我们提出了一个基于DL的去噪自动编码器称为雷达STDA。它利用注意力机制和时空信息的融合,优于最先进的方法,如调零,IMAT和CAE的干扰减轻和去噪。我们的网络的SINR达到17.08 dB,这意味着它可以非常接近地面真实情况进行恢复。同时,我们的模型获得了所有方法中最小的失真,EVM为0.1792。干扰抑制后的目标检测准确率为87.15%,也是所有方法中最好的。更重要的是,Radar-STDA具有纳米级的尺寸,允许在主机和边缘设备上对距离多普勒地图进行实时降噪。总之,与众所周知的传统和基于DL的技术相比,所提出的方法在各种指标上实现了最先进的性能。在未来的工作中,我们的目标是设计一个集成的神经网络的干扰抑制,同时检测,这可以大大降低计算成本。
- import numpy as np
- import pandas as pd
- import torch
- import torch.backends.cudnn as cudnn
- import torch.nn as nn
- import torch.optim as optim
- from torch.utils.data import DataLoader
- from tqdm import tqdm
- from tqdm import trange
- from utils.dataloader import get_dataloader
- from nets.nano_sta_decoder import nano_sta
- from torch.utils.tensorboard import SummaryWriter
- from utils.callbacks import loss_save
- import datetime
- import time
- import matplotlib.pyplot as plt
- import random
- import os
- from thop import profile
- from thop import clever_format
-
-
- def get_fps(input, model, test_times=100):
- t1 = time.time()
-
- for _ in range(test_times):
- output = model(input)
-
- t2 = time.time()
-
- return ((t2 - t1) / test_times), 1 / ((t2 - t1) / test_times)
-
-
-
-
-
-
- if __name__ == '__main__':
- device = 'cuda'
- input = torch.randn(3, 1, 1, 128, 64).to(device)
-
-
- nano_sta_model = nano_sta(encoder_in_channels=1, encoder_out_channels=128, decoder_out_channels=1).to(device)
- macs, params = profile(nano_sta_model, inputs=(input,))
- macs, params = clever_format([macs, params], "%.3f")
- print("========== clever mode ==========")
- print("macs:", macs)
- print("params:", params)
- latency, fps = get_fps(input=input, model=nano_sta_model, test_times=500)
- print("FPS:", fps)
- print("latency:", latency * 1000, " ms")
-
-
- import numpy as np
- import pandas as pd
- import torch
- import torch.backends.cudnn as cudnn
- import torch.nn as nn
- import torch.optim as optim
- from torch.utils.data import DataLoader
- from tqdm import tqdm
- from tqdm import trange
- from utils.dataloader import get_dataloader
- from nets.nano_sta_decoder import nano_sta
- from torch.utils.tensorboard import SummaryWriter
- from utils.callbacks import loss_save
- import datetime
- import matplotlib
- matplotlib.use('TkAgg')
- import matplotlib.pyplot as plt
- import random
- import os
-
- def plot_denoised_rd_maps(denoised_rd_maps):
- fig, ax = plt.subplots(3, 7, figsize=(15, 12))
- row_index = 0
- data_index = 1
-
- for index in range(denoised_rd_maps.shape[0]):
- rd_map_noise = denoised_rd_maps[index]
- ax[row_index, index % 7].imshow(rd_map_noise)
- ax[row_index, index % 7].set_title("Frame {},Noise {}".format(row_index + data_index, index % 7))
-
- if (index + 1) % 7 == 0 and index != 0:
- row_index += 1
-
- if row_index == 3:
- break
-
- plt.show()
-
-
-
- def export_rd_map():
- model_path = "models/radar_stda.pth"
- device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
- model = nano_sta(encoder_in_channels=1, encoder_out_channels=128, decoder_out_channels=1).to('cpu')
- model.load_state_dict(torch.load(model_path))
- model.eval()
- final_results = []
- gts = []
- mapts = []
-
- train_data_read = pd.read_pickle(
- "E:/Big_Datasets/RaDICaL_Denoising/RD_map_log/RD_map_log/temporal_spatial_data.pkl")
- print("======== start export ==========")
- for i in trange(14, 35):
- example_data = train_data_read.loc[i]
- map_t, map_t_1, map_t_2, gt = example_data['t'], example_data['t-1'], example_data['t-2'], \
- example_data['gt']
-
- input_map = torch.from_numpy(np.array(map_t)).unsqueeze(1).unsqueeze(2).type(
- torch.FloatTensor)
-
- output_map = model(input_map).squeeze(0).squeeze(0)
- final_results.append(output_map.detach().numpy())
- gts.append(gt)
- mapts.append(map_t)
-
- final_results = np.array(final_results)
- final_results = final_results.reshape(final_results.shape[0], final_results.shape[1]*final_results.shape[2], -1)
- gts = np.array(gts)
- mapts = np.array(mapts)
- print(final_results.shape)
- print(gts.shape)
- print(mapts.shape)
- np.save("cae.npy", final_results)
- np.save("gt_maps.npy", gts)
- np.save("mapts.npy", mapts)
-
- plot_denoised_rd_maps(final_results)
- print("======== end export ==========")
-
-
-
-
-
- if __name__ == '__main__':
-
- model_path = "models/nano_sta.pth"
- device = 'cuda:0' if torch.cuda.is_available() else 'cpu'
-
- nano_sta_model = nano_sta(encoder_in_channels=1, encoder_out_channels=128, decoder_out_channels=1).to(device)
- nano_sta_model.load_state_dict(torch.load(model_path))
- nano_sta_model.eval()
-
- train_data_read = pd.read_pickle(
- "E:/Big_Datasets/RaDICaL_Denoising/RD_map_log/RD_map_log/temporal_spatial_data.pkl")
- random_index = random.randint(20000, 23966)
- print("random index:", 0)
- example_data = train_data_read.loc[random_index]
- map_t, map_t_1, map_t_2, gt = example_data['t'], example_data['t-1'], example_data['t-2'], \
- example_data['gt']
-
- np.save("qualitive_rd_map_example.npy", map_t)
-
- input_map = torch.from_numpy(np.array([map_t, map_t_1, map_t_2])).unsqueeze(1).unsqueeze(2).type(torch.cuda.FloatTensor)
- print(input_map.shape)
-
- output_map = nano_sta_model(input_map)
-
- output_map = output_map.squeeze(0).squeeze(0)
- print(output_map.shape)
- output_map = output_map.detach().to('cpu').numpy()
-
-
- fig, ax = plt.subplots(1, 5, figsize=(15, 7))
- ax[0].imshow(map_t)
- ax[0].set_title("Frame t interference")
-
- ax[1].imshow(map_t_1)
- ax[1].set_title("Frame t-1 interference")
-
- ax[2].imshow(map_t_2)
- ax[2].set_title("Frame t-2 interference")
-
- ax[3].imshow(gt)
- ax[3].set_title("Frame t gt")
-
- ax[4].imshow(output_map)
- ax[4].set_title("Frame t decouple")
-
- plt.imshow(output_map)
- now = datetime.datetime.now()
- plt.savefig(f"images/test_{random_index}_{now.year}{now.month}{now.day}{now.hour}{now.minute}{now.second}.png")
- plt.show()
-
- export_rd_map()
-
- import numpy as np
- import torch
- import torch.backends.cudnn as cudnn
- import torch.nn as nn
- import torch.optim as optim
- from torch.utils.data import DataLoader
- from tqdm import tqdm
- from tqdm import trange
- from utils.dataloader import get_dataloader
- from nets.nano_sta_decoder import nano_sta
- from torch.utils.tensorboard import SummaryWriter
- from utils.callbacks import loss_save
- import datetime
- import random
- import os
-
-
-
-
- if __name__ == '__main__':
-
- # -------------------------------- 超参数 -------------------------------- #
- data_path = "E:/Big_Datasets/RaDICaL_Denoising/RD_map_log/RD_map_log/temporal_spatial_data.pkl"
- batch_size = 16
- train_ratio = 0.92
- cuda = True
- optimizer_name = 'adam'
- scheduler_name = 'step'
- learning_rate = 0.001
- weight_decay = 5e-4
- epochs = 100
- criterion = nn.MSELoss()
- # ------------------------------------------------------------------------ #
-
- # ------------------------------- 训练设备 --------------------------------- #
- device = 'cuda' if torch.cuda.is_available() else 'cpu'
- # -------------------------------------------------------------------------- #
-
- # --------------------------------- SEED ------------------------------------- #
- def setup_seed(seed):
- torch.manual_seed(seed)
- torch.cuda.manual_seed_all(seed)
- np.random.seed(seed)
- random.seed(seed)
- torch.backends.cudnn.deterministic = True
-
-
- setup_seed(777)
- # ---------------------------------------------------------------------------- #
-
- # ================================================== 开始训练 ==================================================#
-
- # ------------------------------- 模型定义 --------------------------------- #
- nano_sta_model = nano_sta(encoder_in_channels=1, encoder_out_channels=128, decoder_out_channels=1).to(device)
- nano_sta_model._initialize_weights()
- # -------------------------------------------------------------------------- #
-
- # ------------------------------- 数据集加载 ------------------------------- #
- trainloader, testloader, validloader = get_dataloader(data_path=data_path, batch_size=batch_size,
- train_ratio=train_ratio)
- # -------------------------------------------------------------------------- #
-
- # -------------------------------------------------------------------------- #
- # writer = SummaryWriter("logs")
- # time_str = datetime.datetime.strftime(datetime.datetime.now(), '%Y_%m_%d_%H_%M_%S')
- # log_dir = os.path.join("logs", "loss_" + str(time_str) + '.txt')
- # log_history = open(log_dir, encoding='utf8', mode='w')
- # -------------------------------------------------------------------------- #
-
- # ------------------------------ Optimizer --------------------------------- #
- if optimizer_name == 'adam':
- optimizer = optim.AdamW(lr=learning_rate, params=nano_sta_model.parameters(), weight_decay=weight_decay)
- elif optimizer_name == 'sgd':
- optimizer = optim.SGD(lr=learning_rate, params=nano_sta_model.parameters(), momentum=0.937)
- # -------------------------------------------------------------------------- #
-
- # ------------------------------ Scheduler --------------------------------- #
- if scheduler_name == "cosine":
- scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer=optimizer, eta_min=learning_rate * 0.01, T_max=epochs/10)
- elif scheduler_name == "step":
- scheduler = optim.lr_scheduler.StepLR(optimizer=optimizer, gamma=0.9, step_size=1)
- # -------------------------------------------------------------------------- #
-
- # ------------------------------ Start Training ---------------------------- #
- print()
- print("================= Training Configuration ===================")
- print("trainloader size:", len(trainloader) * batch_size)
- print("validloader size:", len(validloader) * batch_size)
- print("testloader size:", len(testloader) * batch_size)
- print("epoch:", epochs)
- print("batch size:", batch_size)
- print("optimizer:", optimizer_name)
- print("scheduler:", scheduler_name)
- print("initial learning rate:", learning_rate)
- print("weight decay:", weight_decay)
- print("=============================================================")
- mse_loss_min = 1000000
- train_loss_array = []
- valid_loss_array = []
- best_model = None
- best_model_name = None
- for epoch in range(epochs):
- train_loss = 0
- train_loop = tqdm(enumerate(trainloader), total=len(trainloader))
- nano_sta_model.train()
- for i, (maps, labels) in train_loop:
- inputs = maps.to(device)
- gts = labels.to(device)
- predictions = nano_sta_model(inputs).to(device)
- loss = criterion(predictions, gts)
- train_loss += loss.item()
-
- # ------------------ 清空梯度,反向传播 ----------------- #
- optimizer.zero_grad()
- loss.backward()
- optimizer.step()
- # ----------------------------------------------------- #
- train_loop.set_description(f'Epoch [{epoch}/{epochs}]')
- train_loop.set_postfix(MSE_Loss=loss.item(), learning_rate=optimizer.param_groups[0]['lr'])
- train_loss_array.append(train_loss)
-
- # log_history.write(str(loss.item()) + '\n')
-
- # loss_history = LossHistory(log_dir="logs", model=nano_sta_model, input_shape=[128, 64])
-
- # ------------------------------- Validation --------------------------------- #
- validation_loop = tqdm(enumerate(validloader), total=len(validloader))
-
- print()
- print("########################## start validation #############################")
- nano_sta_model.eval()
- with torch.no_grad():
- validation_loss = 0
- for i, (maps, labels) in validation_loop:
- inputs = maps.to(device)
- gts = labels.to(device)
- valid_prediction = nano_sta_model(inputs)
- loss = criterion(valid_prediction, gts)
- validation_loss += loss.item()
- validation_loop.set_postfix(loss_real_time=loss.item(), Validation_MSE_Loss_Per_Map=
- validation_loss / (len(validloader) * batch_size))
- if validation_loss < mse_loss_min:
- best_model = nano_sta_model
- best_model_name = "val_loss_" + str(validation_loss) + '.pth'
- print("best model now:", best_model_name)
- torch.save(best_model.state_dict(), best_model_name)
- mse_loss_min = validation_loss
- # writer.add_scalar("MSE - Validation", validation_loss / (len(validloader) * batch_size), epoch)
- # if validation_loss / (len(validloader) * batch_size) <= mse_loss_min:
- # torch.save(nano_sta_model.state_dict(), "logs/validation " +
- # str(validation_loss / (len(validloader) * batch_size)) + ".pth")
- valid_loss_array.append(validation_loss)
-
- print()
- print("########################## end validation #############################")
- # ---------------------------------------------------------------------------- #
-
- scheduler.step()
-
- loss_save(train_loss_array, mode='train')
- loss_save(valid_loss_array, mode='valid', model=best_model, model_name=best_model_name)
- print()
- print("============================== end training =================================")
-
-
-
-
-
-
-
-
-
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。