大数跨境
0
0

技术干货 | Xtreme1 融合标注 实践指南——融合标注的映射原理与实践系列

技术干货 | Xtreme1 融合标注 实践指南——融合标注的映射原理与实践系列 Xtreme1
2022-12-05
0
导读:想要进行融合标注,应该怎样调整数据格式?相机参数与外参矩阵分别如何转换?今日的文章帮您一站解答!


在《融合标注的映射原理与实践》系列的往期文章中讲解了融合标注的内参与外参原理。进入实战环节,想要进行融合标注,应该怎样调整数据格式?相机参数外参矩阵分别如何转换?今日的文章帮您一站解答!


点击下方标题,阅读 Xtreme1《融合标注的映射原理与实践》系列的往期文章:

技术干货 | Xtreme1 融合标注 外参介绍
技术干货|Xtreme1 融合标注 内参介绍


前言


平台对需要做融合标注的数据有一定格式要求,下面我们来详细地说明。


文件目录结构


数据可以以压缩包(.zip、.rar)的形式上传。

压缩包里的文件目录可以是多级目录,但包含 pcd 文件2D 图像文件相机参数的文件夹必须是下图的结构:

详细说明如下:

  1. point_cloud 文件夹存放 pcd 文件(.pcd),camera_config 文件夹存放相机参数文件(.json),image 文件夹存放 2D 图像文件;

  2. 文件夹名称必须和上图一模一样(除了图片文件夹最后的编号);

  3. 一张 pcd 有几个方向的 2D 图像,就要创建几个 3d_img 文件夹,编号从 0 开始自增,并把图片分别放入这些文件夹;

  4. 这三种文件夹里的文件名需要一一对应(例如 3d_url 里的 abc.pcd 对应 3d_img0 里的 abc.jpg 对应 3d_img1 里的 abc.jpg 对应 camera_config 里的 abc.json)

  5. 缺少 3d_img 文件夹或者 camera_config 文件夹均会导致在标注平台无法显示 2D 图像。

连续帧目录结构:

同一连续帧的数据需要放在相同的"frame_series n"目录下,否则以离散帧进行展示。


相机参数格式


相机参数以 json 格式存放,格式如下:
[  {           //首个列表元素对应 image0 视角相机的参数    "camera_internal": {   //相机内参      "fx": 933.4667,      "fy": 934.6754,      "cx": 896.4692,      "cy": 507.3557    },    "width": 1920,  //图像分辨率(可省略)    "height": 1080,    "camera_external": [   //外参       0.15507753102020391,      -0.98789957539112982,      0.0023212743705054379,      -17.735591210606444,      0.0020841948660559892,      -0.0020225262130809719,      -0.99999578275084622,      1.2557627497829358,      0.9879001040107438,      0.15508171500774312,      0.0017453268516608449,      -56.1919827741359,      0.0,      0.0,      0.0,      1.0    ]  },  {     ...  },    ...}
详细说明如下:

1. 同一个pcd文件对应的2D图像的相机参数均存放在一个参数文件内,且要注意参数在列表中的索引顺序需要和2D图片文件夹相对应;

2. 内参的键叫 "camera_external", 值为一个字典,字典的键为 fxfycxcy,这四个量在第一期已经介绍过,注意键名不可更改;外参的键叫 "camera_external",值为一个列表,列表中的元素为 4×4 外参矩阵转为列表得到。


外参矩阵构造


很多时候我们的外参不是矩阵形式,或是已有的外参矩阵不符合平台要求,这些都需要后续做转换。


4.1 产生旋转矩阵


在整个外参中,一般表示平移变换的参数都是一个三维向量,主要的不同点在旋转变换部分。


4.1.1 旋转向量→旋转矩阵


旋转向量到旋转矩阵的转换用 Python 实现如下, 我们下面用绕 z 轴旋转 180 度举例。

第一个参数为旋转向量,第二个 degrees 参数,表示使用角度还是弧度,默认 False,弧度。

(1)传入角度:
from scipy.spatial.transform import Rotation as RR.from_rotvec([0, 0, 180], degrees=True).as_matrix()
结果如下,注意那些 的数其实就是 0:
array([[-1.00000000e+00, -1.22460635e-16,  0.00000000e+00],       [ 1.22460635e-16, -1.00000000e+00,  0.00000000e+00],       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])
(2)传入弧度:
R.from_rotvec([0, 0, np.pi], degrees=False).as_matrix()
结果是一样的:
array([[-1.00000000e+00, -1.22460635e-16,  0.00000000e+00],       [ 1.22460635e-16, -1.00000000e+00,  0.00000000e+00],       [ 0.00000000e+00,  0.00000000e+00,  1.00000000e+00]])
我们可以使用下面的公式来验证,得到的矩阵当然是一致的。


4.1.2 MRPs→旋转矩阵


MRPs 到旋转矩阵的转换用 Python 实现如下,我们继续用z 轴旋转 180 度举例。

由于 MRPs 的模长本来就是 tan 函数的值,而不是一个角度,所以这个函数没有 degrees 参数。
R.from_mrp([0, 0, 1]).as_matrix()
结果和上面旋转向量得到的矩阵一样:
array([[-1.,  0.,  0.],       [ 0., -1.,  0.],       [ 0.,  0.,  1.]])

4.1.3 欧拉角→旋转矩阵


欧拉角到旋转矩阵的转换用 Python 实现如下,以动态欧拉角(内旋),先绕自身 X 轴旋转 90°,再绕自身 Y 轴旋转 90° 为例。

第一个参数同时表示了旋转顺序内/外旋(大写内旋,小写外旋),第二个参数为欧拉角,第三个参数为使用角度/弧度。
from scipy.spatial.transform import Rotation as Rimport numpy as np
R.from_euler('XYZ', [np.pi/2, np.pi/2, 0], degrees=False).as_matrix()
得到的结果如下:
array([[ 2.22044605e-16,  0.00000000e+00,  1.00000000e+00],       [ 1.00000000e+00,  2.22044605e-16, -2.22044605e-16],       [-2.22044605e-16,  1.00000000e+00,  0.00000000e+00]])

我们也可以自己验证,注意内旋时矩阵右乘。结果和上面一致:


4.1.4 四元数→旋转矩阵


四元数到旋转矩阵的转换用Python实现如下。

注意此时的四元数顺序为 xyzw,其中 w 为实部

(1)看看旋转 360°,此时实部为 1:
from scipy.spatial.transform import Rotation as Rimport numpy as np
R.from_quat([0, 0, 0, 1]).as_matrix()

结果当然是一个单位矩阵:

array([[1., 0., 0.],       [0., 1., 0.],       [0., 0., 1.]])
(2)不论传入的四元数是不是单位四元数,都会被函数作归一化处理,可以用以下代码验证:
a = R.from_quat([1.5, 2.5, 3.5, 4.5]).as_matrix()b = R.from_quat([3.0, 5.0, 7.0, 9.0]).as_matrix()print(a == b)

结果:

[[ True  True  True] [ True  True  True] [ True  True  True]]

4.2 外参矩阵的注意事项


到了现在,我们手里已经有了外参矩阵,但仍要注意它是否满足以下的要求。


4.2.1 外参排列


参数文件里的外参矩阵是上期提到的格式,即旋转矩阵R和平移向量 t 左右排列

平台要求的外参是一个列表,相当于上面的元素如下排列:


4.2.2 映射方向


参数文件里的外参矩阵指的是雷达坐标系相机坐标系的变换,不能反过来。

如果手里的外参对应相机坐标系雷达坐标系的变换,那么在构造好外参矩阵后,可以取它的逆矩阵,Python 实现如下:

import numpy as np
ext_inv = np.linalg.inv(ext)

本篇文章属《融合标注的映射原理与实践》系列,关注我们,第一时间获取更新!

如果大家对 Xtreme1 感兴趣,欢迎关注 GitHub Repo:

https://github.com/basicai/xtreme1/

如果您遇到了一些问题,欢迎在交流群讨论或者通过提 issue 的方式告诉我们,我们一定会帮到您。

往期回顾

关于我们

【声明】内容源于网络
0
0
Xtreme1
Linux基金会下的全球首个开源多模态训练数据平台
内容 31
粉丝 0
Xtreme1 Linux基金会下的全球首个开源多模态训练数据平台
总阅读10
粉丝0
内容31