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

深度图转点云(2)—再略微优化了下

2022-09-16 02:57 作者:KERO  | 我要投稿

最近回过头优化以前写的代码,还是不少地方能好好捯饬捯饬加快点速度

这段之前写成博客的深度图转点云的代码就是其中一个

由于B站文章投稿只能修改三次,而之前那篇已经因为改错字用光了次数 

所以新开一篇写写


新代码


修改的是初始化的时候会用到的get_depth_vector()这个函数

用jyupyter notebook来测试的话,之前的函数用时将近7秒 而新函数用时0.5秒


校验两个函数的得到的数据是否一致

旧算法

整体的流程并没有改变,这里只重新简单地说一下


已知一个像素点(u,v)的深度值depth的情况下

点从画面坐标系到相机坐标系可以用[u,v,depth]乘以相机内参矩阵的逆矩阵

相机坐标系和画像坐标系


然后为了更快连续地计算多张深度图,我们假设有一张深度图,所有像素的深度值都为1

用循环计算其中所有像素的结果, 也就是遍历图片的像素坐标(u,v),反复用[u,v,1]乘以相机的逆矩阵 保存得到的三维坐标[x,y,1]

这时得到的[x,y,1]可以看成是一个方向向量

因为两点确定一条直线 

光心以及像素点两点确定了一个方向,所以无论depth值为多少,点都应该在这个方向上


有了所有像素点的方向向量数组以后,只需要将新来的深度图的depth乘以数组,便可以得到点云数组


而旧的get_depth_vector()函数就遍历所有像素点的方式在计算方向向量


新算法

代码中为了计算方便和速度,一直用了矩阵来计算变换

而画面坐标到相机坐标系的变换也可以写成以下形式,其中cx cy为光心坐标,fx fy为焦距,这些都包含在相机内参矩阵中

  • z = depth

  • x = (u - cx) * z / fx

  • y = (v - cy) * z / fy

以x为例,在计算图像中所有像素点的时候 式子右边cx fx是固定值 u和z是变量

但由于我们计算假设所有像素点的深度值都为1,所以这时变量只剩下了 u

u图像分辨率的宽,以代码中的分辨率(960,720)的情况

那么 变量u 就是 0-959 的960个整数

那么可知 相应的结果 x 也应该只有 960种 ,对应着960个u

同理 y应该只有720种 结果 对应着 720个v的量


所以我们并不需要遍历一张图像上的所有像素坐标,只需要计算出0~959 的u以及0~719的v的结果 然后将他们按照顺序组合起来,便可以得到同之前一样的结果

当然,具体的实现为了计算速度 还是采用了矩阵计算的形式


首先根据图像的分辨率我们构建代表长宽的竖数组和横横数组

为了保存结果[x,y,1] ,第三个维度为3

注意这里两个数组的长度都暂时为 u,因为u>v 为了下一步计算的方便暂且都设置成大的这个数



接着遍历0~959 ,通过[u,v,1]乘以相机逆矩阵得到对应的 x 和y  ,存入刚才的两个数组的对应位置中

为了计算方便我们一并计算了960个y值,但是实际上只有720个 所以队v_vector进行切片取前720

接着对竖数组,此时为 720*1*3的v_vector,竖着复制960列

对横数组,1*960*3的u_vector, 横着复制720行

 复制之后两者的shape都为 720*960*3

接着只要直接将两组数据相乘,便可得到和旧函数一样的结果

此时 对应每个像素点上都会 [x,1,1] * [1,y,1] = [x,y,1]

        


如此一来 ,从之前遍历所有点 (720*960个点) 进行[u,v,1]乘以相机矩阵逆计算的步骤

变成了现在只计算960次再通过numpy的复制 ,乘法融合 得到相同的结果

深度图转点云(2)—再略微优化了下的评论 (共 条)

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