I have a structure from motion (SfM) 3D dense point cloud of a landscape that has 200,000,000+ points (and this is one of the smaller point clouds) and am trying to compute the standard deviation of every point given a user-specified search radius so that I can feed these values into a machine learning model alongside other metrics and information. I'm using a cKDTree and the query_ball_point function from scipy to perform the neighborhood search. I think the real slowdown is coming from having to iterate over every point in the point cloud but don't know of a more efficient way to accomplish this.
Here is the code that I currently have to compute the standard deviation of every point in the dense point cloud and return a numpy array of standard deviation values. Is there a more efficient way to iterate over all points in the dense point cloud?
import math
from scipy.spatial import cKDTree
def calc_3d_sd(coords, rad=0.5):
# build the KDTree
tree = cKDTree(coords, leafsize=5)
# intiialize an empty numpy array of the same length as coords
sd = np.zeros(len(coords))
# iterate over every point in the dense point cloud
# (I think this is where the real slowdown is happening)
for count,elem in enumerate(coords):
# perform spatial query on point
result = tree.query_ball_point(elem, r=rad)
# if at least one other point is returned, then continue
if len(result) > 0:
# intialize 'sums' var to track sum
sums = 0
# compute standard deviation of X, Y, and Z separately
# then combine these through the sqrt of the sum of squares to get 3D standard deviation
for x in np.std(coords[result],axis=0):
sums += x**2
sd[count] = math.sqrt(sums)
# otherwise, no points were found in the search radius, return zero
else:
sd[count] = 0
# return the numpy array of computed standard deviation values all points in the cloud
return sd
# create 'coords' variable containing all X, Y, and Z coordinates from the dense cloud
coords = np.stack([testcloud.x, testcloud.y, testcloud.z]).transpose()
# iterate over all points in the dense cloud and return the standard deviation of all other points within a 0.5m radius
sd3d = calc_3d_sd(coords, rad=0.5)
In testing a couple of different search radius for the spatial query, it is not surprising to find that the computation time increases substantially with larger radius queries. This doesn't address the primary question though, which is still searching for a more efficient approach to iterating over every point in the dense point cloud (or some equivalent function).