将三维点及其颜色映射到二维图像w/o循环



我正在处理点云,我试图在图像平面上高效地渲染模型,而不在三维点上循环。

输入:.ply型号

输出:二维图像

到目前为止我所做的:

我已经构建了3x4投影矩阵,使用python中的open3d库来获得点云的三维点及其颜色,加载模型后它只是(pcl.points和pcl.colors(,我通过添加1将三维点(pcl.points(转换为齐次坐标,因为第4列的形状是(9729509,4),然后我通过将投影矩阵乘以(9729509,4)的转置得到新的矩阵(3, 9729509)来接收我的二维点,然后将第一行和第二行除以第三行来归一化并得到二维像素。

现在我有一个矩阵(3, #of_2d_pixels),我甚至可以去掉第三行,因为它只是归一化后的一行,我有(2, #of_2d_pixels),将其定义为p

问题是:如何使用for循环并将颜色(从pcl.colors(分配给空的2d array来构建一个不带for循环的二维图像,其中分配索引是p矩阵中的值?最后,我将展示使用OpenCV来渲染这个数组

使用for循环需要很多时间,我相信有一种方法可以更快地完成,就像我一次在所有点上使用投影矩阵,而不使用for循环(在3d点上循环并将我收到的2d点附加到新阵列需要很多时间(

我的答案假设您在python上写作。

从理论角度来看,我们可以将绘制点想象为卷积函数,通过对其进行转换,我们可以实现关联性,这将允许我们使用并行计算。在实践中,这并不能很好地工作,因为这样的卷积函数的计算是昂贵的,并且结果将与正常循环相当。因此,我决定在代码的C级使用带有循环的函数,例如标准函数映射(func,arr(。通过使用numpy对索引计算操作进行矢量化,我设法获得了约4倍的性能提升。这样你就可以理解代码的上下文:

import numpy as np
# image width = height
width = 1000
number_of_points = 1000000
# ps = [(x,y,color),(x,y,color),(x,y,color),...]
ps = np.random.randint(width,size=(number_of_points,3))
# color buffer
pixels = np.array([0]*width*width)
  • 正常循环:
for (x,y,c) in ps:
pixels[x+y*width] = c

1.24 s±37.5 ms每个循环(7次运行的平均值±标准偏差,每个循环1次(

  • 映射+numpy:
# f2(x)  <-> f2([idx,color])
# x[0] = idx
# x[1] = color
def f2(x):
global all_screen
pixels[x[0]] = x[1]
# unpack xs,ys,colors
xs,ys,clrs = ps.T
# calculate index in pixel array
idxs = xs + ys*width
# draw all
list(map(f2,zip(idxs,clrs)))
# cast to list use only for evaluate map function, because in default it lazy

306 ms±31.3 ms每个循环(7次运行的平均值±标准偏差,每个循环1次(

如果您对没有可变变量(赋值(的纯函数样式感兴趣,我们可以创建一个pixel_idx->带有静态哈希表的color函数(python中的dict(:

# unpack xs,ys,colors
xs,ys,clrs = ps.T
# calculate index on pixel array
idxs = xs + ys*width
ddd = dict(zip(idxs,clrs))
def f3(x):
return ddd.get(x,0)
# draw all
pixels1 = list(map(f3,np.arange(0,width*width,1)))

每个循环809 ms±21.5 ms(7次运行的平均值±标准偏差,每个循环1次(

最新更新