Home > OS >  Trouble vectoring a NumPy
Trouble vectoring a NumPy

Time:09-17

I am trying to write some efficient code for a school project using LIDAR. The goal is to filter out anything in the point cloud past 10 meters in the point cloud and pass it out. I can write a for loop to do this but it's not very optimized. My goal is to this efficiently with NumPy.

def get_distance(input_array):
        return np.sqrt(np.sum(np.square(input_array)))

def filter_by_distance(cloud, distance=10):
     cloud1 = [item for item in cloud if get_distance(item) <= distance]
     return np.asarray(cloud1)

cloud is a mulidimensional np.array containing [X,Y,Z,I]

[[23.157  0.032  0.992  0.34 ]
 [23.219  0.105  0.994  0.29 ]
 [23.282  0.179  0.996  0.26 ]
 ...
 [ 1.548 -1.101 -0.77   0.   ]
 [ 1.388 -0.978 -0.676  0.   ]
 [ 1.42  -0.964 -0.684  0.   ]]

I'm using get_distance(cloud[:,0:2]) the get the x,y distance, but I can't seem to find a way to use this trim the original point cloud without a for loop. I'd appreciate any help!

CodePudding user response:

Calculate sum of square inner rows and no need to sqrt, directly compare with square distance

def filter_by_distance(cloud, distance=10):
    # np.sum is implemented c and very fast
    # axis = 1 for summing row
    # no need to sqaure root (save computation)
    # : stand for row, 0:3 stand for column 0, 1, 2
    umask = np.sum(cloud[:, 0:3]**2, axis=1) < distance**2
    # umask is boolean array, whereever it is false, that cloud point will not be shown
    return cloud[umask]

CodePudding user response:

You are almost there. You can add or leave out z, im not sure what I represents.

points = cloud[:,0:3]
points = np.sqrt(np.sum(np.square(points), axis=1))
points_filtered = points[points<=distance]

The additions are an axis for summing along your x,y and z values for each point and included filtering in numpy. points<=distance returns a bool array thats used as a mask.

CodePudding user response:

You can pass an index (or mask) of True False booleans to the ndarray as a selection criteria. Get the distance from the origin with the method you have shown. Just expand it to operate over the cloud array row-wise. See sum documentation and look under axis. You want the sums of each row since you have stored the data with one X,Y,Z,I as a row. If you transposed it in the future use axis = 0 for columns.

dist = np.sqrt(np.sum(np.square(cloud[:,0:2]), axis = 1))

This will give you a vector of distances as long as the number of points in your point cloud. Now make the index with:

index = dist <= 10

If you print this index you will see a series of True False. Now do the filtering

filtered_cloud = cloud[index,:]

And of course, the ever so ugly one-liner. If you do this...please comment it so people know what you did.

filtered_cloud = cloud[np.sqrt(np.sum(np.square(cloud[:,0:2]), axis = 1)) <= 10, :]

Curious, why use only x and y for distance?

  • Related