简体   繁体   English

将 3d 点及其 colors 映射到不带循环的 2D 图像

[英]Mapping 3d points and their colors to 2D image w/o loops

I'm working with point clouds, and I'm trying to render the model on the image plane efficiently w/o looping over the 3d points.我正在使用点云,并且正在尝试在图像平面上有效地渲染 model,而无需在 3d 点上循环。

Input: .ply model输入: .ply model

Output: 2d image Output:二维图像

What I've done so far:到目前为止我所做的:

I've constructed the 3x4 projection matrix, using open3d library in python to get the the 3d points of the point cloud and their colors, after loading the model it's just (pcl.points and pcl.colors), I've transformed the 3d points (pcl.points) to homogeneous coords by adding ones as the 4th column the shape is (9729509,4) , then I received my 2d points by multiplying the projection matrix by the transpose of (9729509,4) and getting a new matrix (3, 9729509) and then divide the first row and second row by the third row to normalize and get the 2d pixels. I've constructed the 3x4 projection matrix, using open3d library in python to get the the 3d points of the point cloud and their colors, after loading the model it's just (pcl.points and pcl.colors), I've transformed the 3d通过将形状添加为第 4 列的点 (pcl.points) 到齐次坐标(9729509,4) ,然后我通过将投影矩阵乘以(9729509,4)的转置并得到一个新矩阵来接收我的 2d 点(3, 9729509)然后将第一行和第二行除以第三行以归一化并得到 2d 像素。

Now I have a matrix of (3, #of_2d_pixels) and I can even get rid of the third row because it's just ones after normalizing and I have (2, #of_2d_pixels) , define it as P .现在我有一个(3, #of_2d_pixels)矩阵,我什至可以去掉第三行,因为它只是标准化后的矩阵,我有(2, #of_2d_pixels) ,将其定义为P

The question is: How can I construct a 2d image w/o using for loops and assigning the colors (from pcl.colors) to an empty 2d array where the indices of assignment are the values in the P matrix?问题是:如何使用 for 循环构造一个 2d 图像,并将 colors(来自 pcl.colors)分配给一个空的2d array ,其中赋值索引是P矩阵中的值? Finally I'll show use OpenCV to render this array最后我将展示使用 OpenCV 来渲染这个数组

Using for loops takes a lot of time and I'm sure there's a way to do it faster, like I did with using the projection matrix on all the points at once w/o using for loops (looping over the 3d points and appending the 2d points I received to a new array takes a lot of time)使用 for 循环需要很多时间,我相信有一种方法可以更快地做到这一点,就像我在不使用 for 循环的情况下一次在所有点上使用投影矩阵所做的那样(循环 3d 点并附加我收到一个新数组的 2d 点需要很多时间)

My answer assumes you are writing on python.我的回答假设您正在写 python。

From a theoretical point of view, we could imagine drawing points as a convolution function, and by transforming it, we can achieve associativity, which will allow us to use concurrent computing.从理论上讲,我们可以把画点想象成一个卷积function,通过对它的变换,我们可以实现关联性,这将允许我们使用并发计算。 In practice, this does not work so well, since the computation of such a convolution function is expensive and the result will be comparable to a normal loop.在实践中,这并不能很好地工作,因为这样的卷积 function 的计算是昂贵的,并且结果将与正常循环相当。 Therefore, I decided to use functions with loops at the C levels of the code, for example the standard function map (func, arr).因此,我决定在代码的 C 级别使用带有循环的函数,例如标准 function map (func, arr)。 I managed to get a ~ 4x performance gain by vectorizing the index calculation operations using numpy.通过使用 numpy 对索引计算操作进行矢量化,我设法获得了约 4 倍的性能提升。 So that you can understand the context of the code:以便您了解代码的上下文:

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)
  • normal loop:正常循环:
for (x,y,c) in ps:
    pixels[x+y*width] = c

1.24 s ± 37.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)每个循环 1.24 秒 ± 37.5 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)

  • map + numpy: map + 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 per loop (mean ± std. dev. of 7 runs, 1 loop each)每个循环 306 毫秒 ± 31.3 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)

if you are interested in pure functional style without mutable variables (assignments), we can create a pixel_idx -> color function with a static hash table (dict in python):如果您对没有可变变量(赋值)的纯函数样式感兴趣,我们可以使用 static Z0800FC577294C34E0B28AD283943594Z 创建pixel_idx -> color function Z0800FC577294C34E0B28AD283943594Z

# 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 per loop (mean ± std. dev. of 7 runs, 1 loop each)每个循环 809 毫秒 ± 21.5 毫秒(平均值 ± 标准偏差。7 次运行,每个循环 1 个)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM