I am trying to classify ground point in .las file. Points are never classified which is 0.
I read something about, if the number of return is 1, we can declare it as ground. Is it true? las.number_of_returns == las.return_number
.
After that with that points I will create a KDTree so I can determine the all ground points.
Is this a correct approach?
I found the following code and I'm trying to change it.
import laspy
import numpy as np
from scipy.spatial import cKDTree
in_file = laspy.read(las_filepath)
output_file = 'out.las'
point_records = in_file.points.copy()
single_veg = np.where(in_file.num_returns == 1)
# pull out full point records of filtered points, and create an XYZ array for KDTree
single_veg_points = in_file.points[single_veg]
single_veg_points_xyz = np.array((single_veg_points['X'],
single_veg_points['Y'],
single_veg_points['Z'])).transpose()
ground_only = np.where(in_file.number_of_returns == in_file.return_number)
ground_points = in_file.points[ground_only]
ground_points_xyz = np.array((ground_points['X'],
ground_points['Y'],
ground_points['Z'])).transpose()
#create a KDTree to query against
ctree = cKDTree(ground_points_xyz)
#For every single return veg point query against all points within 20 meters.
#If a higher elevation ground point is nearby, then change the classification
#from vegetation to ground in the original point array.
for idx, record in enumerate(single_veg_points_xyz):
neighbors = ctree.query_ball_point(record, 2000)
for neighbor in neighbors:
neighbor_z = ground_points[neighbor]['Z']
record_z = single_veg_points[idx]['Z']
if neighbor_z >= record_z:
single_veg_points[idx]['raw_classification'] = 2
#update points just once
point_records[single_veg] = single_veg_points
out_file = laspy.open(output_file, mode='w', header=in_file.header)
out_file.points = point_records
out_file.close()