我正在处理点云,我试图在图像平面上高效地渲染模型,而不在三维点上循环。
输入:.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次(