MMDetection3D/3D目标检测中的边界框和坐标系介绍(含相关函数以及坐标变换的介绍)

2023-10-27

1.准备知识

参考:带你玩转 3D 检测和分割 (二):核心组件分析之坐标系和 Box - 知乎

1.1 坐标系介绍

        激光雷达坐标系通常定义如下左图所示,其中x指向前方,y指向左方,z指向上方。

 

        相机坐标系通常定义如上右图所示,其中x指向右方,y指向下方,z指向前方。

1.2 3D边界框的定义

        一般来说,对于自动驾驶目标检测任务而言,一个3D边界框可以由7个参数决定:位置(x,y,z)、尺寸(\textup{x\_size},\textup{y\_size},\textup{z\_size})以及朝向角/偏航角/旋转角\theta

        一般将与物体朝向平行的棱的长度记为边界框长度l,竖直方向棱的长度记为边界框高度h,余下一组棱的长度记为边界框宽度w,如下左图所示。

        将边界框绕高度轴(对于激光雷达坐标系,高度轴为Z轴;对于相机坐标系,高度轴为Y轴)旋转到朝向与X轴正方向相同时,边界框与x,y,z坐标轴平行的3组棱对应的长度分别记为(\textup{x\_size},\textup{y\_size},\textup{z\_size})

        对于激光雷达坐标系下的边界框,其(\textup{x\_size},\textup{y\_size},\textup{z\_size})即为(l,w,h)(如上中图所示);则对于相机坐标系下的边界框,其(\textup{x\_size},\textup{y\_size},\textup{z\_size})(l,h,w)(如上右图所示)。 

        朝向角为边界框绕高度轴的旋转角度(从X轴正向与边界框朝向之间的角度),其正负按照右手螺旋定则确定。

1.3 边界框的坐标变换

        从激光雷达坐标系到相机坐标系:

  • 位置变换直接按照点的坐标变换方法进行(需要坐标变换矩阵);
  • 尺寸上,x_size不变,y_size和z_size交换(原因见1.2节中灰底内容);
  • 旋转角先取相反数,再减去90度。

        角度的变换是由于两个坐标系中,\theta=0的基准轴X轴并不是同一个(相差90度),且由于相机坐标系高度轴正方向向下, 故角度增大的方向从上向下看是顺时针,与激光雷达坐标系中相反。

        注意:上述旋转角的变换的前提条件是,相机坐标系Y轴与激光雷达坐标系-Z轴朝向相同(多数情况下均符合此条件)。

后续内容是MMDetection3D的相关概念、函数和数据类型的介绍。若只是想了解3D目标检测的坐标系和边界框,则无需继续往下看。 

1.4 origin

        在MMDetection3D一些边界框相关的函数中(如2.3节的函数),存在origin参数,这个origin表示边界框位置坐标对应的那个点在边界框中的相对位置。

        具体来说,在坐标系下先旋转3D边界框到朝向角为0,然后将其缩放为单位正方体,并平移到第一象限,使其一个角点位于坐标系原点,与角点相邻的三条棱分别与三个坐标轴重合。此时边界框位置坐标也相应地被变换到某处,其变换后的坐标即为origin。

        举例来说,一般的数据集会使用边界框底面中心坐标作为边界框的位置坐标,则在激光雷达坐标系下,origin应设为(0.5,0.5,0),如下左图所示:

        而在相机坐标系下,origin应设为(0.5,1,0.5),如上右图所示。

2. mmdet3d/core/bbox/box_np_ops.py中的常用函数

        mmdet3d/core/bbox/box_np_ops.py中有很多与边界框相关的函数,这些函数通常会在数据准备的相关代码中看到。

2.1 remove_outside_points

        目的是去除图像视锥外的点云,仅保留能投影到图像范围内的那些点。

  • 输入
    • 原始点云(N\times(3+\textup{dims}));
    • 相机修正矩阵(3\times3扩维成4\times4);
    • 点云坐标系到相机坐标系的坐标变换阵(3\times4扩维成4\times4);
    • 相机内参矩阵(3\times4扩维成4\times4);
    • 图像大小(H,W)
  • 输出
    • 能投影到图像范围内的点云子集(N'\times(3+\textup{dims}))。

2.2 box_camera_to_lidar

        目的是将相机坐标系下的边界框参数变换为激光雷达坐标系下的参数。

  • 输入
    • 相机坐标系下的3D边界框(M\times7);
    • 相机修正矩阵(3\times3扩维成4\times4);
    • 点云坐标系到相机坐标系的坐标变换阵(3\times4扩维成4\times4)。
  • 输出
    • 激光雷达坐标系下的3D边界框(M\times7)。

        该函数的原理见1.3节。

        注意:该函数默认相机坐标系Y轴和激光雷达坐标系-Z轴同向;若坐标系不完全对齐(如View-of-Delft数据集),若输入该函数的旋转角定义为绕激光雷达-Z轴的旋转角(朝向激光雷达-Y轴时角度为0),则也可使用该函数。

2.3 points_in_bbox

        目的是统计各点是否落在每个边界框内。

  • 输入
    • 点云 (N\times(3+\textup{dims}));
    • 边界框( M\times7 ,其与点云定义于同一坐标系下);
    • 旋转轴序号(0,1,2之一,表示高度轴是第几个坐标轴;对于图像坐标系,应设置为1;对于激光雷达坐标系,应设置为2);
    • origin(表示边界框位置坐标在边界框中的相对位置,详见1.4节)。
  • 输出
    • 二值矩阵(N\times M,其第i行第j列为True表示第i个点位于第j个边界框内) 。

2.4 center_to_corner_box3d

        目的是将边界框的位置、尺寸、朝向角参数转换为边界框的8个角点坐标。

  • 输入
    • 各边界框位置(N\times3);
    • 各边界框尺寸(N\times3);
    • 各边界框朝向角(N);
    • origin(表示边界框位置坐标在边界框中的相对位置,详见1.4节);
    • 旋转轴序号(0,1,2之一,表示高度轴是第几个坐标轴;对于图像坐标系,应设置为1;对于激光雷达坐标系,应设置为2)。
  • 输出
    • 各边界框的8个角点坐标(N\times8\times3)。

        注意:所有边界框参数、origin以及旋转轴应对应同一坐标系。

3.点云在不同坐标系下的变换

3.1 view_points(位于nuscenes/utils/geometry_utils.py

        目的是将相机坐标系下的点云坐标转换到图像坐标系下。

  • 输入
    • 相机坐标系下的点云(3\times N);
    • 相机内参矩阵(3\times4;可扩维成4\times4);
    • 归一化选择(True则输出像素坐标,False则输出像平面上的坐标)。
  • 输出
    • 图像坐标系下的点云(N\times 3,归一化时前两维为像素坐标(u,v),最后一维恒为1;否则最后一维为深度d,前两维为(ud,vd))。

3.2 points_cam2img(位于mmdet3d/core/bbox/structures/utils.py)

        目的是将相机坐标系下的点云坐标转换到图像坐标系下。

  • 输入
    • 相机坐标系下的点云(*\times 3);
    • 相机内参矩阵(3\times3,可扩维成3\times44\times4);
    • 是否包含深度信息的选择(True则输出包含深度信息)。
  • 输出
    • 图像坐标系下的点云(若输出包含深度信息则为*\times 3,前两维为像素坐标(u,v),最一维为深度d;否则输出为*\times2,为像素坐标(u,v))。

注:上述维度中的 “ * ” 代表任意多个维度,如*\times3可以为N \times 3M\times N\times3等。

3.3 点云数据类型及其坐标变换

        mmdet3d提供了定义好的边界框数据类型LiDARPoints(位于mmdet3d/core/points/lidar_points.py下)和CameraPoints(位于mmdet3d/core/points/camera_points.py下),分别是激光雷达坐标系下的点云以及相机坐标系下的点云数据类型。一些方法已经内置于数据结构中,可直接调用。

        以LiDARPoints为例,首先需要创建该类的实例:

# 设pts为(N,C)的Tensor,表示N个C维的点(C>=3),其中前三个维度分别是x,y,z坐标
pts = LiDARPoints(pts, points_dim=C)

         然后可以直接调用flip/rotate等数据增广方法以及坐标变换方法。

  • convert_to:坐标变换方法。
    • 输入:
      • dst:目标坐标系,为Coord3DMode.LIDARCoord3DMode.CAM
      • rt_mat:坐标变换矩阵。
    • 若输入dst=Coord3dMode.LIDAR,则输出数据类型为LiDARPoints;若输入dst=Coord3dMode.CAM,则输出数据类型为CameraPoints。

4.边界框的数据类型及其在不同坐标系下的变换

        mmdet3d提供了定义好的边界框数据类型LiDARInstance3DBoxes(位于mmdet3d/core/bbox/structure/lidar_box3d.py下)以及CameraInstance3DBoxes(位于mmdet3d/core/bbox/structure/cam_box3d.py下),分别是激光雷达坐标系下的3D边界框以及相机坐标系下的3D边界框数据类型,许多方法已经内置于数据结构中,可直接调用。

        以LiDARInstance3DBoxes类为例,首先需要创建该类的实例:

# 设bboxes为大小(M,7)的Tensor,其中M为边界框数量,7代表x,y,z坐标,x,y,z尺寸以及朝向角,若有速度等其它参数,需放置在最后
bboxes = LiDARInstance3DBoxes(bboxes)
# 另有三项输入box_dim(每个边界框的参数数量),with_yaw(包含朝向角为True)和origin(含义见前文介绍,指示3D坐标在边界框中的相对位置)
# 可使用默认值box_dim=7, with_yaw=True, origin=(0.5, 0.5, 0),

注意:对于边界框的朝向角,LiDARInstance3DBoxes是绕激光雷达坐标系Z轴定义的,而CameraInstance3DBoxes是绕相机坐标系Y轴定义的。

        然后可以直接调用如下方法(没有全部介绍):

  • gravity_center:取边界框几何中心(M,3)
  • corners:取边界框8个角点(M,8,3)
  • bev:取BEV下的边界框参数(x,y坐标、x,y尺寸以及朝向角)(M,5)
  • in_range_bev:检查中心在BEV范围内的边界框。
    • 输入:BEV范围(x_min,y_min,x_max,y_max);
    • 输出:M维bool值向量,若第i个元素为True则表示第i个边界框中心在该范围内。
  • limit_yaw:限制朝向角范围。
    • 输入:
      • offset:原点在角度区间中的相对位置;
      • period:角度范围的大小。
    • 例如,要将朝向角限制在(-\pi,\pi)的范围内,period需取2\pi,offset取0.5(表示原点在区间正中)。
    • 该方法的实现实际上是调用了mmdet3d/core/bboxes/structures/utils.py中的limit_period函数,因此在单独限制角度范围时可直接调用limit_period函数(输入依次为角度张量、offset和period)。
  • ​​​​​​​convert_to:坐标系变换方法。
    • 输入:
      • dst:目标坐标系,为Box3dMode.LIDARBox3dMode.CAM(Box3dMode类位于mmdet3d/core/bbox/structure/box_3d_mode.py下);
      • rt_mat:源坐标系到目标坐标系的坐标变换矩阵(4\times4)。
    • 若输入dst=Box3dMode.LIDAR,则输出数据类型为LiDARInstance3DBoxes;若输入dst=Box3dMode.CAM,则输出数据类型为CameraInstance3DBoxes。
    • 注意:当相机坐标系Y轴与激光雷达坐标系-Z轴朝向不完全相同时,朝向角的变换是不正确的。

调用上述方法的代码如下(以gravity_center为例):

bboxes_centers = bboxes.gravity_center
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MMDetection3D/3D目标检测中的边界框和坐标系介绍(含相关函数以及坐标变换的介绍) 的相关文章

  • 如何正确地将 MIDI 刻度转换为毫秒?

    我正在尝试将 MIDI 刻度 增量时间转换为毫秒 并且已经找到了一些有用的资源 MIDI Delta 时间刻度到秒 http www lastrayofhope co uk 2009 12 23 midi delta time ticks
  • Python逻辑运算符优先级[重复]

    这个问题在这里已经有答案了 哪个运算符优先4 gt 5 or 3 lt 4 and 9 gt 8 这会被评估为真还是假 我知道该声明3 gt 4 or 2 lt 3 and 9 gt 10 显然应该评估为 false 但我不太确定 pyth
  • 通过列表理解压平列表列表

    我正在尝试使用 python 中的列表理解来展平列表 我的清单有点像 1 2 3 4 5 6 7 8 只是为了打印这个列表列表中的单个项目 我编写了这个函数 def flat listoflist for item in listoflis
  • 将数据帧行转换为字典

    我有像下面的示例数据这样的数据帧 我正在尝试将数据帧中的一行转换为类似于下面所需输出的字典 但是当我使用 to dict 时 我得到了索引和列值 有谁知道如何将行转换为像所需输出那样的字典 任何提示都非常感激 Sample data pri
  • if 语句未命中中的 continue 断点

    在下面的代码中 两者a and b是生成器函数的输出 并且可以评估为None或者有一个值 def testBehaviour self a None b 5 while True if not a or not b continue pri
  • 填充两个函数之间的区域

    import matplotlib pyplot as plt import numpy as np def domain x np arange 0 10 0 001 f1 lambda x 2 x x 2 0 5 plt plot x
  • 以同步方式使用 FastAPI,如何获取 POST 请求的原始正文?

    在中使用 FastAPIsync not async模式 我希望能够接收 POST 请求的原始 未更改的正文 我能找到的所有例子都显示async代码 当我以正常同步方式尝试时 request body 显示为协程对象 当我通过发布一些内容来
  • 在Python中调整图像大小

    我有一张尺寸为 288 352 的图像 我想将其大小调整为 160 240 我尝试了以下代码 im imread abc png img im resize 160 240 Image ANTIALIAS 但它给出了一个错误TypeErro
  • 如何通过在 Python 3.x 上按键来启动和中断循环

    我有这段代码 当按下 P 键时会中断循环 但除非我按下非 P 键 否则循环不会工作 def main openGame while True purchase imageGrab if a sum gt 1200 fleaButton ti
  • 使用鼻子获取设置中当前测试的名称

    我目前正在使用鼻子编写一些功能测试 我正在测试的库操作目录结构 为了获得可重现的结果 我存储了一个测试目录结构的模板 并在执行测试之前创建该模板的副本 我在测试中执行此操作 setup功能 这确保了我在测试开始时始终具有明确定义的状态 现在
  • Numpy 过滤器平滑零区域

    我有一个 0 及更大整数的 2D numpy 数组 其中值代表区域标签 例如 array 9 9 9 0 0 0 0 1 1 1 9 9 9 9 0 7 1 1 1 1 9 9 9 9 0 2 2 1 1 1 9 9 9 8 0 2 2 1
  • Seaborn Pairplot 图例不显示颜色

    我一直在学习如何在Python中使用seaborn和pairplot 这里的一切似乎都工作正常 但由于某种原因 图例不会显示相关的颜色 我无法找到解决方案 因此如果有人有任何建议 请告诉我 x sns pairplot stats2 hue
  • 将 JSON 对象传递给带有请求的 url

    所以 我想利用 Kenneth 的优秀请求模块 https github com kennethreitz requests 在尝试使用时偶然发现了这个问题自由库API http wiki freebase com wiki API 基本上
  • 如何在 python 中没有 csv.reader 迭代器的情况下解析单行 csv 字符串?

    我有一个 CSV 文件 需要重新排列和重新编码 我想跑 line line decode windows 1250 encode utf 8 在由 CSV 读取器解析和分割之前的每一行 或者我想自己迭代行 运行重新编码 并仅使用单行解析表单
  • python Soap zeep模块获取结果

    我从 SOAP API 得到如下结果 client zeep Client wsdl self wsdl transport transport auth header lb E authenticate self login res cl
  • 使用 NumPy 将非均匀数据从文件读取到数组中

    假设我有一个如下所示的文本文件 33 346 1223 10 23 11 23 12 23 13 23 14 23 15 23 16 24 10 24 11 24 12 24 13 24 14 24 15 24 16 25 14 25 15
  • 如何在 OSX 上安装 numpy 和 scipy?

    我是 Mac 新手 请耐心等待 我现在使用的是雪豹 10 6 4 我想安装numpy和scipy 所以我从他们的官方网站下载了python2 6 numpy和scipy dmg文件 但是 我在导入 numpy 时遇到问题 Library F
  • Ubuntu 上的 Python 2.7

    我是 Python 新手 正在 Linux 机器 Ubuntu 10 10 上工作 它正在运行 python 2 6 但我想运行 2 7 因为它有我想使用的功能 有人敦促我不要安装 2 7 并将其设置为我的默认 python 我的问题是 如
  • 限制 django 应用程序模型中的单个记录?

    我想使用模型来保存 django 应用程序的系统设置 因此 我想限制该模型 使其只能有一条记录 极限怎么办 尝试这个 class MyModel models Model onefield models CharField The fiel
  • 在Python中按属性获取对象列表中的索引

    我有具有属性 id 的对象列表 我想找到具有特定 id 的对象的索引 我写了这样的东西 index 1 for i in range len my list if my list i id specific id index i break

随机推荐

  • openGL之API学习(三十八)投影变换公式

    原文在https blog csdn net gggg ggg article details 45969499 这里只记录几个重要结论 1 正交投影变换 1 1一般形式 1 2常用形式 2 透视投影 2 1一般形式 2 2常用形式 经过投
  • Git修改代码并提交上传

    1 创建本地git 仓库 在本地磁盘创建一个文件夹 用来存放需要push到coding上的文件 打开此文件夹 单击右键 git bash here 输入 git init 此步操作完成后 会在此文件夹下生成一个隐藏的 git后缀文件 2 添
  • 路由器学习总结

    路由器在网络中的作用至关重要 就好像我们坐公交车到某个地方 公交车肯定不是一站直达的 中间要经过许多个公交站点 网络中数据的传输也是一样 源地址与目标地址之间并不是直接到达的 中间也要经过一系列的路由器转发 所以路由器的作用 就是用来转发数
  • 毕业设计-基于卷积神经网络的遥感图像语义分割方法

    目录 前言 课题背景和意义 实现技术思路 一 相关技术理论 二 基于残差融合和多尺度上下文信息的遥感图像语义分割方法 三 基于注意力机制和边缘检测的遥感图像语义分割方法 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着
  • 计算机网络第五篇【网络层之二】

    tags 计算机网络 title 计算机网络第五篇 网络层之二 IP数据包的首部格式 一个 IP 数据报由首部和数据两部分组成 首部的前一部分是固定长度 共 20 字节 是所有 IP 数据报必须具有的 版本 占 4 位 指 IP 协议的版本
  • 认知:大数据-Big Data

    大数据 Big Data 作者 WenasWei 一 大数据 大数据 Big Data 也称为海量数据 Massivee 是随着计算机技术及互联网技术的高速发展而产生的数据现象 2013年也称为大数据元年 标志着全球正式步入了大数据时代 大
  • kali工具-信息收集之存活主机识别(arping)

    一 介绍 ARP协议是 Address Resolution Protocol 地址解析协议 的缩写 在同一以太网中 通过地址解析协议 源主机可以通过目的主机的IP地址获得目的主机的MAC地址 arping程序就是完成上述过程的程序 arp
  • Hudi学习1:概述

    Hudi 概念 Hudi跟hive很像 不存储数据 只是管理hdfs数据 1 小文件处理 2 增加支持update delete等操作 3 实时数据写入 以下是官方点介绍 Apache Hudi 是一个支持插入 更新 删除的增量数据湖处理框
  • 求枚举变量长度‘’ sizeof_sizeof你真的弄明白了吗?

    sizeof基础 在C语言中 sizeof是一个操作符 operator 而不是函数 其用于判断数据类型或者表达式长度 所占的内存字节数 其有两种表达形式 1 sizeof 类型说明符 2 sizeof 表达式 我们通常使用第 1 种形式
  • redis持久化之AOF(Append Only File)及其总结

    1 是什么 以日志的形式来记录每个写操作 将redis执行过的所有写指令记录下来 读操作不记录 只许追加文件但不可以改写文件 redis启动之初会读取该文件重新构建数据 换言之 redis重启的话就根据日志文件的内容将写指令从前到后执行一次
  • windows10上的MySQL8.0 安装、配置、启动及登录

    MySQL8 0安装 1 首先下载MySQL8 0社区版 Community 安装程序 下载地址 https dev mysql com downloas windows installer 8 0 html 2 下载后打开安装程序按提示操
  • 大语言模型之一 Attention is all you need ---Transformer

    大语言模型已经在很多领域大显身手 其应用包括只能写作 音乐创作 知识问答 聊天 客服 广告文案 论文 新闻 小说创作 润色 会议 文章摘要等等领域 在商业上模型即产品 服务即产品 插件即产品 任何形态的用户可触及的都可以是产品 商业付费一般
  • jstat -gc pid 查询jvm 状态

    top命令查看相关应用的pid jstat gc 24272 参数说明 S0C 第一个幸存区的大小 S1C 第二个幸存区的大小 S0U 第一个幸存区的使用大小 S1U 第二个幸存区的使用大小 EC 伊甸园区的大小 EU 伊甸园区的使用大小
  • Linux 没有鼠标解决复制粘贴问题

    1 复制粘贴命令 在一行的任何位置按下yy y是yanked拷贝的意思 然后去想粘贴的位置按下p即可 p是粘贴的意思 2 如果想复制3行的话 按下3yy 就复制3行 如果想复制多行的话 直接按数字可以选中多好 然后粘贴 3 剪切和粘贴 把光
  • 【C语言技巧】51单片机打印 printf 格式化字符不正确解决办法

    原文来自keil软件 help 一栏 如下图 printf include
  • Windows防火墙配置脚本讲解

    一 natsh命令 Netsh 是命令行脚本实用工具 它允许从本地或远程显示或修改当前正在运行的计算机的网络配置 Netsh 还提供了一个脚本功能 对于指定计算机 可以通过此功能以批处理模式运行一组命令 为了存档或配置其他服务器 Netsh
  • 爬虫写得好,‘劳烦’吃得饱

    前言 提起 爬虫 总有一丝神秘色彩 大家都调侃 爬虫写得好 劳烦 吃得饱 虽然是 高危职业 但在大数据横行的年代 爬虫与反爬虫的需求却在猛烈增加 他们的关系就像矛与盾 越来越多的公司造 矛 发起攻势 获取数据 又或者在造 盾 封锁信息 这种
  • echarts设置tooltip的宽高问题

    ECharts容器 1 ECharts容器设置宽度width 值可以是百分比或者是像素 当设置为百分比时 要检查父元素是否设置了宽度 注意 容器宽度设置不要用min width 不然会发现tooltip的宽度等于min width设置的宽度
  • flutter 微信支付 跳转小程序 分享到小程序

    flutter 微信支付 跳转小程序 分享到小程序 直接上步骤 第一步 pubspec yaml 添加依赖 fluwx 1 2 1 1 fluwx最新3 0不太好用 第二步 界面添加 import package fluwx fluwx d
  • MMDetection3D/3D目标检测中的边界框和坐标系介绍(含相关函数以及坐标变换的介绍)

    1 准备知识 参考 带你玩转 3D 检测和分割 二 核心组件分析之坐标系和 Box 知乎 1 1 坐标系介绍 激光雷达坐标系通常定义如下左图所示 其中指向前方 指向左方 指向上方 相机坐标系通常定义如上右图所示 其中指向右方 指向下方 指向