(已开源-ICRA2023) High Resolution Point Clouds from mmWave Radar

news2024/11/19 15:24:37

在这里插入图片描述
本文提出了一种用于生成高分辨率毫米波雷达点云的方法:RadarHD,端到端的神经网络,用于从低分辨率雷达构建类似激光雷达的点云。本文通过在大量原始雷达数据上训练 RadarHD 模型,同时这些雷达数据有对应配对的激光雷达点云数据。本文的实验表明,即使是在未遇见过的场景以及存在严重烟雾遮挡的情况下,RadarHD也能生成丰富的点云数据。同时,这些生成的点云也能应用于现有的激光雷达里程计和建图方法中。

项目链接:https://akarsh-prabhakara.github.io/research/radarhd/

文章目录

  • 1. RadarHD System Design
  • 2. Implementation
  • 3. Results
  • 4. Model Code

1. RadarHD System Design

首先讲一下RadarHD系统设计,RadarHD的核心目标是提高雷达信号的分辨率,使它们类似激光雷达。首先,可以考虑简单地插值方法并对雷达图像进行放大,就像相机图像上的超分辨率。但与相机图像不同,低分辨率雷达图像的邻域缺乏相似性。本文提出的RadarHD方法超越了传统的邻域方法,探索机器学习方法来获得全局图像理解。

ML 设计选择:机器学习方法的选择上,通常可以考虑一个简单的CNN模型,依次使用卷积层并构建输入图像的全局视图。然而,由于本文最终对超分辨率任务感兴趣,需要结合考虑全局图像理解和上采样。因此,RadarHD 建立在基于 U-Net 的编码器-解码器架构之上,该架构通常用于图像分割任务,使用它来解决雷达超分辨率任务。U-Net的编码器可以用来理解各种雷达伪影并获得真实世界目标的语义准确表征,解码器则使用这种表征来执行超分辨率。

设计挑战:本节的剩下章节描述了RadarHD模型的关键设计,帮助U-Net有效地学习。(1) 有效地表示、预处理和输入雷达I/Q数据。(2) 设计 U-Net 网络消除虚假伪影,同时保留场景中真实对象的数据。(3) 设计损失函数以确保保留预期输出中的尖锐线条等特征(如图 2所示)。

在这里插入图片描述
雷达数据表示

  • 本文选择的毫米波雷达装置可以提供原始I/Q数据流,根据需要进行进一步处理。典型的雷达处理包括空间傅立叶变换,输出具有反射雷达信号在距离和方位上的强度热力图。热力图被阈值化为“点云”。CFAR就是常用的阈值检测器,图2展示了CFAR处理后的雷达图像。本文中RadarHD对处理后得到的热力图应用非常低的阈值,以保留主要的反射信号许多伪影信号,将其留给ML模型来学习和过滤伪影。 在图2中,CFAR处理后雷达图像包含110个非零像素,RadarHD处理后包含1606个非零像素。
  • 坐标表示:雷达本质上是径向测量的,为了捕捉这些径向和方位角的变化,需要进行径向/方位角处理。但机器学习中卷积层的主要学习元素是一个滤波器,它在输入的高度和宽度上执行2D卷积运算。为了利用这一点,本文选择了极坐标表示,这样当滤波器分别处理高度和宽度时,它们就会自然地沿着距离和方位角移动。因此,本文处理后的热力图为0-10米的图像,角度为-90°-90°。由于雷达方位分辨率较差,雷达图像大小为 64×256,激光雷达图像大小为 512×256。

神经网络架构

  • 本文选择的网络架构为 U-Net网络 (图 3所示),它的编码器进行去噪处理并获得准确的语义场景理解,解码器部分来执行超分辨率。RadarHD的设计与传统的U-Net有所不同,对于超分辨率任务,U-Net是不对称的(5个下采样和8个上采样)。
  • 为了消除伪影,本文选择历史帧作为输入,同时在当前帧上执行超分辨率。实验发现使用 40 个历史帧(过去2 秒时间)作为输入效果最好,即使在静态情况下,使用历史帧也会保持输出平滑和更少的抖动。
    在这里插入图片描述

神经网络训练方法

  • 损失函数的选择上,主要是保留激光雷达图像中出现的尖锐线条等特征。为了比较两幅图像,一个是真值,一个是网络输出,首先考虑最标准的损失函数——pixel wise loss。本文选择的真值标签是二分类激光雷达图像。将此二值图像与网络sigmoid输出层进行比较。在所有像素上使用平均二元交叉熵 (BCE)损失。这种像素级损失的目标是强制每个像素匹配预期输出,图4展示了使用BCE损失得到的输出结果。
  • 为了促进输出图像中的清晰锐利线条,本文还使用Dice loss: D = 1 − 2 ∑ i = 1 N o i g i ∑ i = 1 N o i 2 + ∑ i = 1 N g i 2 D=1-\frac{2 \sum_{i=1}^{N} o_{i} g_{i}}{\sum_{i=1}^{N} o_{i}^{2}+\sum_{i=1}^{N} g_{i}^{2}} D=1i=1Noi2+i=1Ngi22i=1Noigi,图4分析了 BCE 损失 和 Dice 损失之间不同权重的输出结果。Dice 损失权重越大,反而会导致消除某些重要特征。
    在这里插入图片描述

2. Implementation

下面介绍本文的具体实现:

  • 硬件上,RadarHD是使用TI毫米波雷达AWR1843实现的,一种最先进的单芯片雷达,理论距离分辨率为3.75 cm,方位角分辨率为15°。RadarHD的目标是提高方位角分辨率,使用 AWR1843 和 DCA1000EVM 来收集原始 I/Q 数据流。
  • 本文的试验台由雷达、激光雷达和相机组成,相机用于调试——所有传感器时间上进行了同步。测试平台安装在移动试验台上。整个数据存储库由大约 200k 雷达 I/Q - 激光雷达对组成,在整个 5147平方米区域内收集。
  • 真值设备,使用 Ouster OS 0 - 64 线激光雷达作为真值。激光雷达配置为0.35°方位角分辨率。只使用前置激光雷达点云进行超分辨率任务,还将激光雷达的仰角视场限制在+/-30厘米以内。
  • Baseline上,使用具有不同的阈值(1dB、3dB、5dB、8dB)的CFAR算法作为我们的基线。
  • 训练和测试数据:在包含家具、电子产品、墙壁、会议室和立方体在内的大型办公空间中训练RadarHD模型。在三个环境中进行了测试: (1) 相同环境中的未使用过的数据,在不同的办公空间中收集不同的轨迹,以及 (2) 相似的环境但不同的空间结果,以及 (3) 不同的环境,包括建筑游艇和室外环境。

3. Results

下面介绍本文实验结果,首先是点云比较。为了与激光雷达点云进行比较,首先转换距离-方位输出图像,得到一个点列表及其(x,y)位置。然后使用两个常用的点云相似度度量来比较点云误差:(1) Chamfer距离,找到一个点云中的每个点到另一个点云的最近点,取所有这些距离的平均值,得到每个点云对的误差。(2) Modified Hausdorff 距离,找到最近的点并获得距离中值。

在这里插入图片描述

与CFAR基线的比较:在这里,本文展示了在 19 个不同的轨迹上在不同 CFAR 阈值下的的性能。如图 5 所示,RadarHD获得了0.24m修改后的 Hausdorff 中值误差和 0.36m Chamfer中值误差。另一方面,CFAR 因阈值而异,像 1dB 阈值这样的低阈值创建了比激光雷达更密集的点云(5倍),而像 8dB 这样的高阈值将只有激光雷达捕获的点数的10%。尽管密度不同,但它们都没有与激光雷达点云有任何结构相似性。所以从1dB到8dB,随着阈值的增加和密度的降低,两个点云误差度量累积分布函数向左移动。然而,由于最高阈值生成的点云非常稀疏,并且与地面实况不相似,CDF 不会随着阈值的增加而向左移动更多。事实上超过 8dB,点数少于激光雷达的 1%。生成的点云不仅将 CFAR 提高了 3.5 倍(mod-Hausdorff)和 2.7 倍(Chamfer),而且在结构上更类似于地面实况,如图 8 所示。

在这里插入图片描述


泛化性:图 6 显示了新环境中性能的变化。相似环境的中值误差为 0.75 米 (mod-Hausdorff) 和 0.8 米 (Chamelfer),不同环境的中值误差为 0.94 米 (mod-Hausdorff) 和 1.03 米 (Chamelfer)。可能会感觉这些中位数与图5中一些CFAR CDF的中位数相似。然而,这里想指出RadarHD的点云仍然更好的三个重要原因。首先,CFAR CDF 从 x 轴0.4m处开始;相比之下,即使对于相似和不同的环境,可以看到RadarHD CDF 从 0.08 m 开始。这表明本文提出的系统可以准确地推断出点云中的很大一部分。其次,由于Chamfer距离和修改后的Hausdorff距离都具有最近邻点关联,因此不能完全捕获结构相似性。然而,可以从图8中定性地看出,本文提出的系统确实生成了有意义的点。第三,为了定量地显示提高精度的影响,本文将RadarHD与CFAR在两个关键应用中进行了比较——里程计和建图。


在这里插入图片描述
烟雾:为了研究遮挡的影响,在测试装置周围构建了一个烟雾室。雷达保持静态,在没有烟雾和不同程度的烟雾的情况下捕获相同的场景。由于收集到的雷达信号保持不变,预计性能与没有烟雾相似。图7通过显示RadarHD的性能不会下降来验证这一点,无论是低烟雾密度还是高烟雾密度,雷达性能都没有很大变化。


在这里插入图片描述
里程计和建图比较:里程计中本文使用绝对轨迹误差ATE来进行评估,图10中在所有情况下(包括不同的环境),无论阈值设为何值,RadarHD里程计精度都优于CFAR。定性地说,可以清楚地看到图9中RadarHD和CFAR之间的差异。RadarHD的性能可与Radar+IMU等方法媲美(0.8m)。

通过识别现实世界中相同物理特征的关键点(如房间的角落)对建图性能进行基准测试,然后计算RadarHD和真值之间相应关键点的欧氏距离误差。图9显示了一个轨迹生成的地图的定性比较。很明显,CFAR没有提供任何有意义的特征来提取关键点,而RadarHD与激光雷达相比实现了结构相似的地图。图10显示了不同环境下关键点之间的欧氏距离误差。只有当RadarHD生成无伪影、有意义的点云时,里程计或建图的良好性能才是可能的。

在这里插入图片描述


4. Model Code

U-Net参考代码如下:

class UNet1(nn.Module):
    def __init__(self, n_channels, n_classes, bilinear=True):
        super(UNet1, self).__init__()
        self.n_channels = n_channels
        self.n_classes = n_classes
        self.bilinear = bilinear

        self.inc = DoubleConv(n_channels, 64)
        self.down1 = Down(64, 128)
        self.down2 = Down(128, 256)
        self.down3 = Down(256, 512)
        factor = 2 if bilinear else 1
        self.down4 = Down(512, 1024 // factor)
        self.up1 = Up(1024, 512 // factor, bilinear)
        self.up2 = Up(512, 256 // factor, bilinear)
        self.up3 = Up(256, 128 // factor, bilinear)
        self.up4 = Up(128, 64, bilinear)
        self.up5 = Up_nocat(64, 64, bilinear)
        self.up6 = Up_nocat(64, 64, bilinear)
        self.up7 = Up_nocat(64, 64, bilinear)
        self.outc = OutConv(64, n_classes)
        self.final_sigmoid = nn.Sigmoid()

    def forward(self, x):
        x1 = self.inc(x)
        x2 = self.down1(x1)
        x3 = self.down2(x2)
        x4 = self.down3(x3)
        x5 = self.down4(x4)
        x = self.up1(x5, x4)
        x = self.up2(x, x3)
        x = self.up3(x, x2)
        x = self.up4(x, x1)
        x = self.up5(x)
        x = self.up6(x)
        x = self.up7(x)
        conv_out = self.outc(x)
        logits = self.final_sigmoid(conv_out)

        return logits

U-Net各模块参考代码如下:

# Core components of U-net

# Adapted from: https://github.com/milesial/Pytorch-UNet/blob/master/unet/unet_parts.py

import torch
import torch.nn as nn
import torch.nn.functional as F


class DoubleConv(nn.Module):
    """(convolution => [BN] => ReLU) * 2"""

    def __init__(self, in_channels, out_channels, mid_channels=None):
        super().__init__()
        if not mid_channels:
            mid_channels = out_channels
        self.double_conv = nn.Sequential(
            nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(mid_channels),
            nn.ReLU(inplace=True),
            nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(inplace=True)
        )

    def forward(self, x):
        return self.double_conv(x)


class Down(nn.Module):
    """Downscaling with maxpool then double conv"""

    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.maxpool_conv = nn.Sequential(
            nn.MaxPool2d(2),
            DoubleConv(in_channels, out_channels)
        )

    def forward(self, x):
        return self.maxpool_conv(x)


class Up(nn.Module):
    """Upscaling then double conv"""

    def __init__(self, in_channels, out_channels, bilinear=True):
        super().__init__()

        # if bilinear, use the normal convolutions to reduce the number of channels
        if bilinear:
            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
            self.conv = DoubleConv(in_channels, out_channels, in_channels // 2)
        else:
            self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2)
            self.conv = DoubleConv(in_channels, out_channels)

    def forward(self, x1, x2):
        x1 = self.up(x1)
        # input is CHW
        diffY = x2.size()[2] - x1.size()[2]
        diffX = x2.size()[3] - x1.size()[3]

        x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2,
                        diffY // 2, diffY - diffY // 2])
        # if you have padding issues, see
        # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a
        # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd
        x = torch.cat([x2, x1], dim=1)
        return self.conv(x)

class Up_nocat(nn.Module):
    """Upscaling then double conv"""

    def __init__(self, in_channels, out_channels, bilinear=True):
        super().__init__()

        # if bilinear, use the normal convolutions to reduce the number of channels
        if bilinear:
            self.up = nn.Upsample(scale_factor=(1,2), mode='bilinear', align_corners=True)
            self.conv = DoubleConv(in_channels, out_channels, in_channels)

    def forward(self, x1):
        x1 = self.up(x1)
        return self.conv(x1)

class Up_nocat_sym(nn.Module):
    """Upscaling then double conv"""

    def __init__(self, in_channels, out_channels, bilinear=True):
        super().__init__()

        # if bilinear, use the normal convolutions to reduce the number of channels
        if bilinear:
            self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True)
            self.conv = DoubleConv(in_channels, out_channels, in_channels)

    def forward(self, x1):
        x1 = self.up(x1)
        return self.conv(x1)


class OutConv(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(OutConv, self).__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)

    def forward(self, x):
        return self.conv(x)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1699420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3实战笔记(37)—粒子特效登录页面

文章目录 前言一、粒子特效登录页总结 前言 上头了&#xff0c;再来一个粒子特效登录页面。 一、粒子特效登录页 登录页&#xff1a; <template><div><vue-particles id"tsparticles" particles-loaded"particlesLoaded" :options"…

ML307R OpenCPU GPIO使用

一、GPIO使用流程图 二、函数介绍 三、GPIO 点亮LED 四、代码下载地址 一、GPIO使用流程图 这个图是官网找到的&#xff0c;ML307R GPIO引脚电平默认为1.8V&#xff0c;需注意和外部电路的电平匹配&#xff0c;具体可参考《ML307R_硬件设计手册_OpenCPU版本适用.pdf》中的描…

MLM之CogVLM2:CogVLM2(基于Llama-3-8B-Instruct 模型进行微调)的简介、安装和使用方法、案例应用之详细攻略

MLM之CogVLM2&#xff1a;CogVLM2(基于Llama-3-8B-Instruct 模型进行微调)的简介、安装和使用方法、案例应用之详细攻略 目录 CogVLM2的简介 1、更新日志 2、CogVLM2 系列开源模型的详细信息 3、Benchmark 4、项目结构 5、模型协议 CogVLM2的安装和使用方法 1、模型微调…

智慧社区管理系统:打造便捷、安全、和谐的新型社区生态

项目背景 在信息化、智能化浪潮席卷全球的今天&#xff0c;人们对于生活品质的需求日益提升&#xff0c;期待居住环境能与科技深度融合&#xff0c;实现高效、舒适、安全的生活体验。在此背景下&#xff0c;智慧社区管理系统应运而生&#xff0c;旨在借助现代信息技术手段&…

685. 冗余连接 II

685. 冗余连接 II 问题描述 在本问题中&#xff0c;有根树指满足以下条件的 有向 图。该树只有一个根节点&#xff0c;所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点&#xff0c;而根节点没有父节点。 输入一个有向图&#xff0c;该…

String类为什么设计成不可变的?

目录 缓存 安全性 线程安全 hashCode缓存 性能 其实这个问题我们可以通过缓存、安全性、线程安全和性能几个维度去解析。 缓存 字符串是Java最常用的数据结构&#xff0c;我们都知道字符串大量创建是非常耗费资源的&#xff0c;所以Java中就将String设计为带有缓存的功能…

揭秘Python安装目录:你的编程宝库隐藏了哪些宝藏?

python3.10安装目录结构 Python310/ │ ├── DLLs/ # Python 解释器所需的 DLL 文件 ├── Doc/ # Python 的 官方文档和参考手册 ├── include/ # 头文件和静态库文件 ├── Lib/ # Python 标准库 ├── libs/ …

微信小程序实现计算当前位置到目的地的距离

实现方式&#xff1a;使用腾讯位置服务 微信小程序JavaScript SDK | 腾讯位置服务 1.进腾讯位置服务申请key 2.下载sdk 微信小程序JavaScript SDK | 腾讯位置服务 3.微信公众平台添加授权域名 4.代码实现计算 const qqmap require("../../utils/qqmap-wx-jssdk.min.js…

探索集合python(Set)的神秘面纱:它与字典有何不同?

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、集合&#xff08;Set&#xff09;与字典&#xff08;Dictionary&#xff09;的初识 1. …

历年高校招生计划数据 API 数据接口

历年高校招生计划数据 API 数据接口 基础数据 / 高校招生&#xff0c;各高校历年招生计划数据&#xff0c;高校招生数据 / 历年计划。 1. 产品功能 支持历年高校招生计划数据查询&#xff1b;包含各高校招生计划详细数据&#xff1b;多维度查询条件支持&#xff1b;毫秒级查询…

3款录屏录制软件,打造专业级视频内容

随着技术的不断发展&#xff0c;人们在日常工作和学习中经常会遇到记录电脑屏幕的需求&#xff0c;例如录制游戏过程、制作教程、保存会议记录等。为了解决这一需求&#xff0c;许多录屏录制软件应运而生。本文将介绍三款常见的录屏录制软件&#xff0c;通过分析它们的特点和使…

JAVASE之类和对象(2)

哪怕犯错&#xff0c;也不能什么都不做。 主页&#xff1a;趋早–Step 专栏&#xff1a;JAVASE gitte:https://gitee.com/good-thg 接上部分&#xff0c;我们继续来学习JAVAEE类和对象。 引言&#xff1a; 这篇文章接上一篇&#xff0c;后半部分&#xff0c;结束类和对象 目录 …

C++:STL简介和容器string用法篇

一、STL简介 STL是C中的标准模板库&#xff08;Standard Template Library&#xff09;的缩写。它是C标准库的一部分&#xff0c;提供了一系列的数据结构和算法模板&#xff0c;包括各种容器、算法、迭代器、仿函数等&#xff0c;用于简化和加速C程序的开发过程。STL的设计理念…

[6] CUDA之线程同步

CUDA之线程同步 共享内存&#xff1a;线程时间需要互相交换数据才能完成任务的情况并不少见&#xff0c;因此&#xff0c;必须存在某种能让线程彼此交流的机制当很多线程并行工作并且访问相同的数据或者存储器位置的时候&#xff0c;线程间必须正确的同步线程之间交换数据并不…

Django-auth组件

Django-auth组件 1 表结构 我们从python manage.py migrate为我们创建的auth组件内置的表开始看 auth_user&#xff1a;用户表存储用户信息&#xff08;登录admin后台&#xff09; 里面的字段分两类&#xff1a;用户基本信息&#xff08;用户名&#xff0c;邮箱&#xff0c;密…

音视频开发4-补充 FFmpeg 开发环境搭建 -- 在windows 上重新build ffmpeg

本节的目的是在windows 上 编译 ffmpeg 源码&#xff0c;这样做的目的是&#xff1a;在工作中可以根据工作的实际内容裁剪 ffmpeg&#xff0c;或者改动 ffmpeg 的源码。 第一步 &#xff1a;下载&#xff0c; 安装&#xff0c;配置 &#xff0c;运行 msys64 下载 下载地址&…

字符串的周期:每一期都有那么几位

【题目描述】 如果一个字符串可以由某个长度为k的字符串重复多次得到,则称该串以k为周期。例 如,abcabcabcabc以3为周期(注意,它也以6和12为周期)。 输入一个长度不超过80的字符串(不含空格),输出其最小周期。 输入第一行表示有T组数据,后续是T行字符串。输出的每组…

透视App投放效果,Xinstall助力精准分析,让每一分投入都物超所值!

在移动互联网时代&#xff0c;App的推广与投放成为了每一个开发者和广告主必须面对的问题。然而&#xff0c;如何精准地掌握投放效果&#xff0c;让每一分投入都物超所值&#xff0c;却是一个令人头疼的难题。今天&#xff0c;我们就来谈谈如何通过Xinstall这个专业的App全渠道…

python纯脚本搬砖DNF之深度学习,工作室适用

声明&#xff1a; 本文章仅作学习交流使用,对产生的任何影响&#xff0c;本人概不负责. 转载请注明出处:https://editor.csdn.net/md?articleId103674748 主要功能 脚本已初步完成&#xff0c;可以上机实战了 1.搬砖研究所、海伯伦&#xff08;持续更新中&#xff09; 2.自…

【揭秘!在线ChatGPT神器,体验入口在此!】

&#x1f680;【揭秘&#xff01;在线ChatGPT神器&#xff0c;体验入口在此&#xff01;】&#x1f680; 前言 嘿&#xff0c;大家好&#xff01;今天我要和大家分享一些关于如何使用免费的ChatGPT的技巧。ChatGPT是一项令人兴奋的人工智能技术&#xff0c;它可以成为我们的好…