欢迎光临散文网 会员登陆 & 注册

LiDAR点云转深度图

2022-09-02 21:18 作者:KERO  | 我要投稿

之前写了python的深度图转点云的文章

这次文章说的是它的逆变换 点云——到深度图


测试用例

本文用KITTI数据集来作为测试用例

以下的图片以及LiDAR数据取自2011_09_26_drive_0005

代码的colab在线版:https://colab.research.google.com/drive/1uq2wKbfqYI9LMkPRL-Zm22ljwfLutYln?usp=sharing


数据导入

图像在kitti数据集中的路径为

kitti/2011_09_26/2011_09_26_drive_0005_sync/image_00/0000000150.png 

LiDAR的二进制文件路径为

kitti/2011_09_26/2011_09_26_drive_0005_sync/velodyne_points/data/0000000150.bin

colab里面直接上传到了根目录

kitti数据集的LiDAR数据有4位 分别是 X Y Z 反射率,反射率本次暂时用不到 所以只取前三位

    

投影变换 1

想要做出深度图,首先得将点云给投影到图像上,取得像素坐标值

一个简单的方法是利用opencv的函数 CV2.projectPoints

函数需要的参数有

  1. 点云

  2. 点云坐标系到相机坐标系的旋转矩阵

  3. 点云坐标系到相机坐标系的平移向量

  4. 相机内参

  5. 相机畸变参数

其实就是所谓的 外参(2+3)和内参(4+5)

LiDAR和相机1的外参可以在数据集中

/kitti/2011_09_26/calib_velo_to_cam.txt

里找到

calib_time: 15-Mar-2012 11:37:16

R: 7.533745e-03 -9.999714e-01 -6.166020e-04 1.480249e-02 7.280733e-04 -9.998902e-01 9.998621e-01 7.523790e-03 1.480755e-02

T: -4.069766e-03 -7.631618e-02 -2.717806e-01


相机内参则是参考ORB_SLAM3的kitti示例配置文件

并且,相机的视角是朝前方的 后面的点云自然不可能投影到相机上,所以这里把点云中在后方的点去掉,也就是X为负的部分

接着把上面的参数全部传入CV2.projectPoints

就可以得到点云投影在画像上的像素坐标,因为像素坐标是只有整数 所以转为整数型

刚刚去除了LiDAR中心后半部分的点

因为相机有FOV 视野的限制,所以前半部分的点也并不是全部都能投影到画像上

所以这里把坐标超出画像的无效点给去除

画出来观察一下

看起来没毛病。虽然仔细看有的点也并不是和物体严丝合缝,比如右手边的胖大叔

不过这应该是LIDAR数据的采集时间和拍照时间有细微的时间差

数据集里面有时间戳,可以看得出两个数据之间略微有时间差


投影变换 2

刚才利用了opencv的函数一下就完成了点云到画像的投影。

不过很可惜这样只能知道点云对应的画像坐标,并不能达到我们的目的——做出深度图

为了做出深度图 除了点云的画像坐标以外,我们还需要每个点的深度

而深度——depth的定义,是一个点在相机坐标系下的Z值

相机坐标系和画像坐标系

刚才opencv的函数拿了相机和LiDAR的外参以及内参

一口气完成了如下的变换

LiDAR坐标系——外参——相机坐标系——内参——画像坐标系

而为了得到深度值,我们需要点群在相机坐标系下的坐标

所以先来手动写一下前面这部分变换


在齐次坐标系下 坐标系和坐标系的变换可以写成

中间的那个矩阵也就是相机的外参矩阵 也叫三维空间几何变换矩阵

其中 左上角的3x3为旋转矩阵 而右边下3x1为平移向量

重新导入我们的LiDAR点云,这次不删掉第四位 而是将其全部设置成1 让XYZ变成齐次坐标XYZ1

然后把之前的旋转矩阵以及平移向量拼接一下 得到变换矩阵

7.533745e-03 -9.999714e-01 -6.166020e-04 -4.069766e-03
1.480249e-02 7.280733e-04 -9.998902e-01 -7.631618e-02
9.998621e-01 7.523790e-03 1.480755e-02 -2.717806e-01
0.000000e+00 0.000000e+00 0.000000e+00 1.000000e+00

接下来用矩阵乘以点云里所有的点,就完成了点云从LiDAR坐标系到相机坐标系的变换

之后是相机坐标系到画像坐标系的变换

因为相机背面的点不会投影到相机上,所以我们删掉背面的点

而相机坐标系下,背面指的也就Z值小于0的部分


和前面的坐标变换一样,在有内参矩阵的情况下,乘以所有点就可以完成变换

但是这里偷个懒,继续使用我们的CV2.projectPoints

不过因为我们已经自己完成了到相机坐标系的变换,所以这时候外参就应该等于0

将旋转以及平移都设为0 0 0


接下来一样是处理一下画面外的点以及可视化

当然,两次的结果肯定是完全一致的,区别就是这次我们取得了点云在相机坐标系下的数据 

可以来做我们的深度图了

深度图作成

上一步的最后我们用一个filter来去除了超出图片范围之外的无效点,同理用这个filter也删除对应点云里的点。

这样两边剩下的点就能按顺序一一对应

而我们想要的深度值是Z,那便取XYZ点云的第三位

接着用numpy创建一个和画像长宽一致的二维矩阵

把先前计算的像素坐标pixel里面填入对应的深度值,一张稀疏的深度图就做好了

用opencv保存后

RGB点云

取得深度图以后当然用途很多,不过你可以选择再一次将他投射成点云

不过这一次因为你知道了每个点对应图像的坐标值,可以从彩色图像中获取RGB值

也就可以投影出所谓的RGB点云


LiDAR点云转深度图的评论 (共 条)

分享到微博请遵守国家法律