如何提高将值存入大型 3d 网格的速度
How to increase speed of depositing values onto a large 3d grid
我在 3 个列向量中有大量数据点。有 1000 万个具有 x,y,z 坐标的点。
我正在对这些点进行体素化处理(根据占用情况将它们分配到离散网格)。有两种方法可以完成体素化。第一种方法是一个简单的分箱程序,如果点落在某个分箱内,则分箱的强度增加 1。另一种方法是将一个点分配给多个分箱,并根据与分箱中心的距离增加强度。我希望完成第二种体素化方法。
一个简单的二维示例是:
假设你有点 x,y=1.7,2.2
并有一个均匀分布的网格,x 和 y 中的节点之间的距离为 0.5。
使用方法一:
该点将被分箱到 x,y=1.5,2 with intensity=1
使用方法二:
该点将分配给 (x,y),(x-.5,y),(x+.5,y),(x,y-.5),(x,y+.5)
强度=(distTOpoint1/sumDistances),(distTopoint2/sumDistances),...,(distTopoint5/sumDistances)
def floorPartial (value, resolution):
return np.floor (value / resolution) * resolution
def EucDistSq(x1,y1,z1,x2,y2,z2):
return (x1-x2)**2+(y1-y2)**2+(z1-z2)**2
xCoord=100*np.random.random(10000000)
yCoordC=100*np.random.random(10000000)
zCoord=100*np.random.random(10000000)
Xspacing=.1
Yspacing=.1
zspacing=.1
Grid=np.empty([len(xCoord),8,4])
for i in range(len(xCoord)):
Grid[i,0,:]=[xCoord[i],yCoordC[i],zCoord[i],0] #Save original Point
#calculate voxel which it would go to if it was simple binning
vX=floorPartial(xCoord[i],Xspacing)
vY=floorPartial(yCoordC[i],Yspacing)
vZ=floorPartial(zCoord[i],Zspacing)
d1=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY,vZ)
d2=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX+Xspacing,vY,vZ)
d3=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX-Xspacing,vY,vZ)
d4=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY+Yspacing,vZ)
d5=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY-Yspacing,vZ)
d6=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY,vZ+Zspacing)
d7=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY,vZ-Zspacing)
dt=np.sum([d1,d2,d3,d4,d5,d6,d7])
#VoxelX,VoxelY,VoxelZ,intensity
Grid[i,1,:]=[vX,vY,vZ,d1/dt]
Grid[i,2,:]=[vX+Xspacing,vY,vZ,d2/dt]
Grid[i,3,:]=[vX-Xspacing,vY,vZ,d3/dt]
Grid[i,4,:]=[vX,vY+Yspacing,vZ,d4/dt]
Grid[i,5,:]=[vX,vY-Yspacing,vZ,d5/dt]
Grid[i,6,:]=[vX,vY,vZ+Zspacing,d6/dt]
Grid[i,7,:]=[vX,vY,vZ-Zspacing,d7/dt]
然后我计划在这个巨大的阵列中回溯并将所有这些强度加起来以获得我的最终地图,但这并不重要。
此代码可对 3d 点进行体素化,但速度非常慢。有没有办法不那么天真和更快地做到这一点?我想事先创建一个网格,每个点的坐标和强度都为 0,并在循环中用 += 或类似的东西更新强度。
可以删除 for 循环并使用 numpy 操作来处理它。没有 for 循环和索引的代码与您的代码相同,速度快约 60 倍:
def ver_2(xCoord, yCoord, zCoord, xSpacing, ySpacing, zSpacing):
Grid = numpy.empty([len(xCoord), 8, 4])
Grid[:, 0, 0] = xCoord
Grid[:, 0, 1] = yCoord
Grid[:, 0, 2] = zCoord
Grid[:, 0, 3] = 0
#
vX = floorPartial(xCoord, xSpacing)
vY = floorPartial(yCoord, ySpacing)
vZ = floorPartial(zCoord, zSpacing)
#
d1 = EucDistSq(xCoord, yCoord, zCoord, vX, vY, vZ)
d2 = EucDistSq(xCoord, yCoord, zCoord, vX+xSpacing, vY, vZ)
d3 = EucDistSq(xCoord, yCoord, zCoord, vX-xSpacing, vY, vZ)
d4 = EucDistSq(xCoord, yCoord, zCoord, vX, vY+ySpacing, vZ)
d5 = EucDistSq(xCoord, yCoord, zCoord, vX, vY-ySpacing, vZ)
d6 = EucDistSq(xCoord, yCoord, zCoord, vX, vY, vZ+zSpacing)
d7 = EucDistSq(xCoord, yCoord, zCoord, vX, vY, vZ-zSpacing)
#
dt = numpy.sum([d1, d2, d3, d4, d5, d6, d7], axis=0)
# VoxelX,VoxelY,VoxelZ,intensity
Grid[:, 1] = numpy.stack((vX, vY, vZ, d1/dt), axis=-1)
Grid[:, 2] = numpy.stack((vX+xSpacing, vY, vZ, d2/dt), axis=-1)
Grid[:, 3] = numpy.stack((vX-xSpacing, vY, vZ, d3/dt), axis=-1)
Grid[:, 4] = numpy.stack((vX, vY+ySpacing, vZ, d4/dt), axis=-1)
Grid[:, 5] = numpy.stack((vX, vY-ySpacing, vZ, d5/dt), axis=-1)
Grid[:, 6] = numpy.stack((vX, vY, vZ+zSpacing, d6/dt), axis=-1)
Grid[:, 7] = numpy.stack((vX, vY, vZ-zSpacing, d7/dt), axis=-1)
return Grid
我想可以通过更多面向矩阵的计算进行更多优化,但我没有确切掌握代码必须做什么:-/可能之前设置了网格的 [:, 1-7, 0-2] 值计算距离,而不是仅使用 Grid 值进行距离计算可以减少一些时间,因为省略了一些不需要的分配。
我在 3 个列向量中有大量数据点。有 1000 万个具有 x,y,z 坐标的点。
我正在对这些点进行体素化处理(根据占用情况将它们分配到离散网格)。有两种方法可以完成体素化。第一种方法是一个简单的分箱程序,如果点落在某个分箱内,则分箱的强度增加 1。另一种方法是将一个点分配给多个分箱,并根据与分箱中心的距离增加强度。我希望完成第二种体素化方法。
一个简单的二维示例是: 假设你有点 x,y=1.7,2.2 并有一个均匀分布的网格,x 和 y 中的节点之间的距离为 0.5。
使用方法一: 该点将被分箱到 x,y=1.5,2 with intensity=1
使用方法二: 该点将分配给 (x,y),(x-.5,y),(x+.5,y),(x,y-.5),(x,y+.5) 强度=(distTOpoint1/sumDistances),(distTopoint2/sumDistances),...,(distTopoint5/sumDistances)
def floorPartial (value, resolution):
return np.floor (value / resolution) * resolution
def EucDistSq(x1,y1,z1,x2,y2,z2):
return (x1-x2)**2+(y1-y2)**2+(z1-z2)**2
xCoord=100*np.random.random(10000000)
yCoordC=100*np.random.random(10000000)
zCoord=100*np.random.random(10000000)
Xspacing=.1
Yspacing=.1
zspacing=.1
Grid=np.empty([len(xCoord),8,4])
for i in range(len(xCoord)):
Grid[i,0,:]=[xCoord[i],yCoordC[i],zCoord[i],0] #Save original Point
#calculate voxel which it would go to if it was simple binning
vX=floorPartial(xCoord[i],Xspacing)
vY=floorPartial(yCoordC[i],Yspacing)
vZ=floorPartial(zCoord[i],Zspacing)
d1=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY,vZ)
d2=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX+Xspacing,vY,vZ)
d3=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX-Xspacing,vY,vZ)
d4=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY+Yspacing,vZ)
d5=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY-Yspacing,vZ)
d6=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY,vZ+Zspacing)
d7=EucDistSq(xCoord[i],yCoordC[i],zCoord[i],vX,vY,vZ-Zspacing)
dt=np.sum([d1,d2,d3,d4,d5,d6,d7])
#VoxelX,VoxelY,VoxelZ,intensity
Grid[i,1,:]=[vX,vY,vZ,d1/dt]
Grid[i,2,:]=[vX+Xspacing,vY,vZ,d2/dt]
Grid[i,3,:]=[vX-Xspacing,vY,vZ,d3/dt]
Grid[i,4,:]=[vX,vY+Yspacing,vZ,d4/dt]
Grid[i,5,:]=[vX,vY-Yspacing,vZ,d5/dt]
Grid[i,6,:]=[vX,vY,vZ+Zspacing,d6/dt]
Grid[i,7,:]=[vX,vY,vZ-Zspacing,d7/dt]
然后我计划在这个巨大的阵列中回溯并将所有这些强度加起来以获得我的最终地图,但这并不重要。
此代码可对 3d 点进行体素化,但速度非常慢。有没有办法不那么天真和更快地做到这一点?我想事先创建一个网格,每个点的坐标和强度都为 0,并在循环中用 += 或类似的东西更新强度。
可以删除 for 循环并使用 numpy 操作来处理它。没有 for 循环和索引的代码与您的代码相同,速度快约 60 倍:
def ver_2(xCoord, yCoord, zCoord, xSpacing, ySpacing, zSpacing):
Grid = numpy.empty([len(xCoord), 8, 4])
Grid[:, 0, 0] = xCoord
Grid[:, 0, 1] = yCoord
Grid[:, 0, 2] = zCoord
Grid[:, 0, 3] = 0
#
vX = floorPartial(xCoord, xSpacing)
vY = floorPartial(yCoord, ySpacing)
vZ = floorPartial(zCoord, zSpacing)
#
d1 = EucDistSq(xCoord, yCoord, zCoord, vX, vY, vZ)
d2 = EucDistSq(xCoord, yCoord, zCoord, vX+xSpacing, vY, vZ)
d3 = EucDistSq(xCoord, yCoord, zCoord, vX-xSpacing, vY, vZ)
d4 = EucDistSq(xCoord, yCoord, zCoord, vX, vY+ySpacing, vZ)
d5 = EucDistSq(xCoord, yCoord, zCoord, vX, vY-ySpacing, vZ)
d6 = EucDistSq(xCoord, yCoord, zCoord, vX, vY, vZ+zSpacing)
d7 = EucDistSq(xCoord, yCoord, zCoord, vX, vY, vZ-zSpacing)
#
dt = numpy.sum([d1, d2, d3, d4, d5, d6, d7], axis=0)
# VoxelX,VoxelY,VoxelZ,intensity
Grid[:, 1] = numpy.stack((vX, vY, vZ, d1/dt), axis=-1)
Grid[:, 2] = numpy.stack((vX+xSpacing, vY, vZ, d2/dt), axis=-1)
Grid[:, 3] = numpy.stack((vX-xSpacing, vY, vZ, d3/dt), axis=-1)
Grid[:, 4] = numpy.stack((vX, vY+ySpacing, vZ, d4/dt), axis=-1)
Grid[:, 5] = numpy.stack((vX, vY-ySpacing, vZ, d5/dt), axis=-1)
Grid[:, 6] = numpy.stack((vX, vY, vZ+zSpacing, d6/dt), axis=-1)
Grid[:, 7] = numpy.stack((vX, vY, vZ-zSpacing, d7/dt), axis=-1)
return Grid
我想可以通过更多面向矩阵的计算进行更多优化,但我没有确切掌握代码必须做什么:-/可能之前设置了网格的 [:, 1-7, 0-2] 值计算距离,而不是仅使用 Grid 值进行距离计算可以减少一些时间,因为省略了一些不需要的分配。