def do_hm(target_tile_path): # load tile for matching target_tile_name = target_tile_path.stem + target_tile_path.suffix try: target_tile = File(target_tile_path, mode='r') # this can take some time # use global to get the info, apologize to programming teachers global ref_tile global ky_lidar_fix_path # match histograms new_dist = hist_match(target_tile.intensity, ref_tile.intensity) # apply transformation new_tile_path = ky_lidar_fix_path / target_tile_name new_tile = File(new_tile_path, mode='w', header=target_tile.header) new_tile.points = target_tile.points new_tile.intensity = new_dist new_tile.close() return (True, new_tile_path) except: # if we can't load the file, that's a big problem, but it seems to happen # sometimes. return (False, target_tile_path)
def write_LAS(pc_xyz, v, output_las_fn, input_las_fn, cmap=cm.terrain, rescale='none'): import datetime from laspy.file import File from skimage import exposure import copy inFile = File(input_las_fn, mode='r') #normalize input and generate colors for height using colormap #stretch to 10-90th percentile #v_1090p = np.percentile(v, [10, 90]) #stretch to 2-98th percentile v_0298p = np.percentile(v, [2, 98]) if rescale == 'none': v_rescale = exposure.rescale_intensity(v, in_range=(v_0298p[0], v_0298p[1])) elif rescale == 'median': bounds = np.round(np.median(np.abs(v_0298p)), decimals=2) v_rescale = exposure.rescale_intensity(v, in_range=(-bounds, bounds)) colormap_terrain = cmap rgb = colormap_terrain(v_rescale) #remove last column - alpha value rgb = (rgb[:, :3] * (np.power(2, 16) - 1)).astype('uint16') outFile = File(output_las_fn, mode='w', header=inFile.header) new_header = copy.copy(outFile.header) #setting some variables new_header.created_year = datetime.datetime.now().year new_header.created_day = datetime.datetime.now().timetuple().tm_yday new_header.x_max = pc_xyz[:, 0].max() new_header.x_min = pc_xyz[:, 0].min() new_header.y_max = pc_xyz[:, 1].max() new_header.y_min = pc_xyz[:, 1].min() new_header.z_max = pc_xyz[:, 2].max() new_header.z_min = pc_xyz[:, 2].min() new_header.point_records_count = pc_xyz.shape[0] new_header.point_return_count = 0 outFile.header.count = v.shape[0] new_header.scale = inFile.header.scale new_header.offset = inFile.header.offset outFile.X = (pc_xyz[:, 0] - inFile.header.offset[0]) / inFile.header.scale[0] outFile.Y = (pc_xyz[:, 1] - inFile.header.offset[1]) / inFile.header.scale[1] outFile.Z = (pc_xyz[:, 2] - inFile.header.offset[2]) / inFile.header.scale[2] outFile.Red = rgb[:, 0] outFile.Green = rgb[:, 1] outFile.Blue = rgb[:, 2] outFile.close()
def z_adjustData(tile, source_data,target_data,filetype,outputfolder): tilename = tile.name source_tile = os.path.join(source_data, '{0}.{1}'.format(tilename,filetype)).replace('\\','/') target_tile = os.path.join(target_data, '{0}.{1}'.format(tilename,filetype)).replace('\\','/') temp_outputfile = os.path.join(outputfolder, '{0}.{1}'.format(tilename,'las')).replace('\\','/') outputfile = os.path.join(outputfolder, '{0}.{1}'.format(tilename,filetype)).replace('\\','/') #read the obfuscated tile sourcefile = File(source_tile, mode='r') targetfile = File(target_tile, mode='r') #get z values from source z_values=sourcefile.get_z_scaled() outfile = File(temp_outputfile, mode="w", header=targetfile.header) outfile.points=targetfile.points #Replace the z values from source file outfile.set_z_scaled(z_values) outfile.close() sourcefile.close() targetfile.close() #lascopy all x,y,z,classification based on the corrected gps time subprocessargs=['C:/LAStools/bin/las2las.exe', '-i', temp_outputfile, '-olaz', '-o', outputfile] subprocessargs=list(map(str,subprocessargs)) p = subprocess.run(subprocessargs,stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=False, check=True, universal_newlines=True) if os.path.isfile(outputfile): #read the obfuscated tile log = f'Z replaced from {source_tile} -> {target_tile}' os.remove(temp_outputfile) print(log) return(True,outputfile,log) else: log = f'Failed replacing Z from {source_tile} -> {target_tile}' #os.remove(temp_outputfile) print(log) return(False,None,log)
def store_point_cloud(filepath: str, points: np.ndarray, header): outFile = File(filepath, mode="w", header=header) outFile.x = points[:, 0] + header.min[0] outFile.y = points[:, 1] + header.min[1] outFile.z = points[:, 2] + header.min[2] outFile.close()
def subsample_from_las_data(filename, desired_number_points=10000): points = [] with File(filename, mode='r') as in_file: scales = in_file.header.scale offsets = in_file.header.offset x_s, y_s, z_s = scales[0], scales[1], scales[2] x_o, y_o, z_o = offsets[0], offsets[1], offsets[2] i = 0 for point in tqdm(in_file.points, total=len(in_file.points), desc="Sampling"): # for i in trange(len(in_file.x), desc="Sampling"): if i < desired_number_points: points.append(np.array([scale(point[0][0], x_s, x_o), scale(point[0][1], y_s, y_o), scale(point[0][2], z_s, z_o)], dtype=np.float32)) # points.append(np.asarray([in_file.x[i], in_file.y[i], in_file.z[i]], dtype=np.float32)) # pdb.set_trace() else: rand = np.random.randint(0, i) if rand < desired_number_points: points[rand] = np.array([scale(point[0][0], x_s, x_o), scale(point[0][1], y_s, y_o), scale(point[0][2], z_s, z_o)], dtype=np.float32) i += 1 return points
def load_lidar_info(lidar_directory): print("Loading LIDARs data...") f = open(l_file, "w") for base, dirs, files in os.walk(lidar_directory): for lidar_file in files: lidar_file = lidar_directory + lidar_file f.write(lidar_file) os.system(laszip + " -i " + lidar_file + " -o " + lidar_file[:-3] + "LAS") inFile = File(lidar_file[:-3] + "LAS", mode='r') x_min = inFile.header.min[0] x_max = inFile.header.max[0] y_min = inFile.header.min[1] y_max = inFile.header.max[1] f.write(" " + str(x_min) + " " + str(y_min) + " " + str(x_max) + " " + str(y_max) + "\n") inFile.close() os.system("rm " + lidar_file[:-3] + "LAS") f.close() print("Load successful")
def get_stats_by_geom_mfn(filenames, poly): points = [] for fn in filenames: inFile = File(fn, mode="r") results = spatial.get_stats_by_geom(inFile, poly["rings"], ["z"], True) points += results return js.dumps({"params": ["z"], "points": points})
def get_stats_by_geom(filename, poly): inFile = File(filename, mode="r") results = spatial.las_within(inFile, poly["rings"], ["z"]) inFile.close() stats = spatial.las_statistics(results["points"]) json = js.dumps(stats) return json
def read_files(files, srs, group_name): """ Open a .las file and extract information from header block. Then add information to a record in the database. """ for las_file in files: las = File(las_file.file.name, mode='r') lidar_obj = LidarFiles() lidar_obj.name = las_file lidar_obj.group = group_name lidar_obj.srs = SpatialReference( srs) # srs saved as user selection TXSP lidar_obj.bbox = get_bbox(las, srs) # srs saved as 3857 for web maps lidar_obj.web_srs = lidar_obj.bbox.srid lidar_obj.centroid = lidar_obj.bbox.centroid # srs saved as 3857 for web maps lidar_obj.point_count = get_point_count(las) lidar_obj.epsg = lidar_obj.srs.srid lidar_obj.file_size = float(las_file.size) x_scale, y_scale, z_scale = get_scale(las) lidar_obj.scale = (x_scale, y_scale, z_scale) offsets = get_offset(las) lidar_obj.offset = offsets mins_maxs = get_min_max(las) lidar_obj.min_max_XYZ = mins_maxs lidar_obj.version = get_version(las) lidar_obj.date_created = get_creation_date(las) lidar_obj.las_file = las_file lidar_obj.sys_id = get_system_identifier(las) lidar_obj.software_id = get_software_id(las) lidar_obj.save() las.close() return
def __init__(self, grid_id): self.grid_id = grid_id filepath = os.path.join(BASE_PATH, f'{grid_id}.las') self._infile = File(filepath, mode='r') self._points = None self._xrange = (None, None) self._yrange = (None, None)
def las_prepare(size, fpath, gnd_only=False): """Takes the filepath to an input LAS file and the desired output raster cell size. Reads the LAS file and outputs the ground points as a numpy array. Also establishes some basic raster parameters: - the extents - the resolution in coordinates - the coordinate location of the relative origin (bottom left) If called with gnd_only = True, it will ignore non-ground points, but this should optimally be done in the PDAL pipeline, not here. """ in_file = File(fpath, mode="r") header = in_file.header if gnd_only == True: in_np = np.vstack((in_file.raw_classification, in_file.x, in_file.y, in_file.z)).transpose() in_np = in_np[in_np[:, 0] == 2].copy()[:, 1:] else: in_np = np.vstack((in_file.x, in_file.y, in_file.z)).transpose() extents = [[header.min[0], header.max[0]], [header.min[1], header.max[1]]] res = [ math.ceil((extents[0][1] - extents[0][0]) / size), math.ceil((extents[1][1] - extents[1][0]) / size) ] origin = [ np.mean(extents[0]) - (size / 2) * res[0], np.mean(extents[1]) - (size / 2) * res[1] ] return in_np, res, origin
def boundingInImage(filename, imageBoundingBox): # Check if a point cloud is contained in an image bounding box # Input: # filename: Point cloud .las filename # imageBoundingBox: Numpy array (4,2) giving the lat long of the four corners of the image # Output: # Boolean indicating if the point cloud is in the image inFile = File(filename, mode='r') EPSG = 32700 - np.max( np.round((45 + imageBoundingBox[0, 1]) / 90) * 100, 0) + np.max( np.round((183 + imageBoundingBox[0, 0]) / 6), 0) inProj = Proj(init='epsg:' + str(int(EPSG))) outProj = Proj(init='epsg:4326') long0, lat0 = transform(inProj, outProj, inFile.header.min[0], inFile.header.min[1]) long1, lat1 = transform(inProj, outProj, inFile.header.max[0], inFile.header.max[1]) polygon = Polygon(imageBoundingBox) inBox = True if not polygon.contains(Point(long0, lat0)): inBox = False if not polygon.contains(Point(long0, lat1)): inBox = False if not polygon.contains(Point(long1, lat0)): inBox = False if not polygon.contains(Point(long1, lat1)): inBox = False return inBox
def get_point_cloud(filepath: str, header): lasFile = File(filepath, mode='r') points = np.vstack((lasFile.x - header.min[0], lasFile.y - header.min[1], lasFile.z - header.min[2])).transpose() return points
def readlas_convertgpd(file, epsg, luclass): """Reads a las file and converts it to a geopandas object""" # Read file pcloud = File(file, mode="r") # Convert to numpy pcloud_np = np.array( (pcloud.x, pcloud.y, pcloud.z, pcloud.red, pcloud.green, pcloud.blue, pcloud.raw_classification)).transpose() # Transform to pandas DataFrame pcloud_df = pd.DataFrame(pcloud_np) pcloud_df.columns = ['x', 'y', 'z', 'red', 'green', 'blue', 'ground'] pcloud_df['ground'] = pcloud_df['ground'].apply(int).apply(str) pcloud_df['class'] = luclass # Transform to geopandas GeoDataFrame crs = None geometry = [Point(xyz) for xyz in zip(pcloud.x, pcloud.y, pcloud.z)] pcloud_geodf = gpd.GeoDataFrame(pcloud_df, crs=crs, geometry=geometry) epsg_str = 'epsg:' + epsg pcloud_geodf.crs = {'init': epsg_str} # Close file pcloud.close() return pcloud_geodf
def create_df_hd5(file_dir, filename, column_names): inFile = File(file_dir + filename, mode='r') raw = inFile.get_points() df = raw_to_df(raw, column_names) df = scale_and_offset(df, inFile.header, append_to_df=True) hdf_name = 'las_points_' + filename[34:40] + '.lz' df.to_hdf(file_dir + hdf_name, key='df', complevel=1, complib='lzo')
def create_df_pickle(file_dir, filename, column_names): inFile = File(file_dir + filename, mode='r') raw = inFile.get_points() df = raw_to_df(raw, column_names) df = scale_and_offset(df, inFile.header, append_to_df=True) pickle_name = 'las_points_' + filename[34:40] + '.pkl' df.to_pickle(file_dir + pickle_name)
def open_las(file='none'): if file == 'none': print('No files selected') return las_header = None max_points = 1000000000 f = File(file) if las_header is None: las_header = f.header.copy() if max_points is not None and max_points < f.header.point_records_count: mask = Mask(f.header.point_records_count, False) mask[np.random.choice(f.header.point_records_count, max_points)] = True else: mask = Mask(f.header.point_records_count, True) new_df = pd.DataFrame(np.array((f.x, f.y, f.z)).T[mask.bools]) new_df.columns = ['x', 'y', 'z'] if f.header.data_format_id in [2, 3, 5, 7, 8]: rgb = pd.DataFrame( np.array((f.red, f.green, f.blue), dtype='int').T[mask.bools]) rgb.columns = ['r', 'g', 'b'] new_df = new_df.join(rgb) new_df['class'] = f.classification[mask.bools] if np.sum(f.user_data): new_df['user_data'] = f.user_data[mask.bools].copy() if np.sum(f.intensity): new_df['intensity'] = f.intensity[mask.bools].copy() return new_df
def load_las(path, extra_dim_list=None, scale_colors=True): """Load las/laz from given path, laz fiels require laszip on path""" input_las = File(path, mode='r') point_records = input_las.points.copy() las_scaleX = input_las.header.scale[0] las_offsetX = input_las.header.offset[0] las_scaleY = input_las.header.scale[1] las_offsetY = input_las.header.offset[1] las_scaleZ = input_las.header.scale[2] las_offsetZ = input_las.header.offset[2] # calculating coordinates if scale_colors: color_div = 65536 else: color_div = 1 p_X = np.array((point_records['point']['X'] * las_scaleX) + las_offsetX) p_Y = np.array((point_records['point']['Y'] * las_scaleY) + las_offsetY) p_Z = np.array((point_records['point']['Z'] * las_scaleZ) + las_offsetZ) try: points = np.vstack((p_X, p_Y, p_Z, input_las.red/color_div, input_las.green/color_div, input_las.blue/color_div)).T except: pass return points
def importLidarDataToScene(context, filepath): # Get a reference to the scene scn = bpy.context.scene # Create a new mesh me = bpy.data.meshes.new("LiDARMesh") # Create a new object with the mesh obj = bpy.data.objects.new("LiDARObj", me) # Link the object to the scene scn.collection.objects.link(obj) # Read the file inFile = File(filepath, mode="r") # Get all the points point_records = inFile.points # X,Y,Z Coords Array coords = np.vstack((inFile.x, inFile.y, inFile.z)).transpose() # Update the Mesh me.from_pydata(coords, [], []) me.update() # Center to Origin obj.select_set(True) bpy.ops.object.origin_set(type='GEOMETRY_ORIGIN', center='MEDIAN') # Close the File inFile.close() return {'FINISHED'}
def generateContourPlots(file, show_3D_plot=False, contour_levels=0): data = File(file, mode='r') # Extract X, Y, Z points from data d = {'X': data.X, 'Y': data.Y, 'Z': data.Z} datapoints = pd.DataFrame(d) print("total points:", len(datapoints)) max_x = datapoints['X'].max() min_y = datapoints['Y'].min() segmentationBlock = datapoints.loc[(datapoints['X'] >= max_x - 50000) & (datapoints['Y'] <= min_y + 50000)] x = segmentationBlock.X y = segmentationBlock.Y z = segmentationBlock.Z print("points in segmentation block:", len(segmentationBlock)) # Contour plot xi, yi = np.linspace(min(x), max(x), 500), np.linspace(min(y), max(y), 500) xi, yi = np.meshgrid(xi, yi) zi = scipy.interpolate.griddata((x, y), z, (xi, yi), method='linear') plt.axis('off') if contour_levels > 0: plt.contourf(xi, yi, zi, cmap=cm.jet, levels=np.linspace(min(z), max(z), contour_levels)) else: plt.contourf(xi, yi, zi, cmap=cm.jet) plt.savefig('contour_plot_levels_3.png',transparent=True,bbox_inches='tight') # 3_D Plot if show_3D_plot: fig = plt.figure() ax = Axes3D(fig) ax.set_axis_off() plt.show()
def __load_las_file(self, filename): if filename.endswith('.laz'): orig_filename = filename filename = 'TEMPORARY.las' self.__unzip_laz(orig_filename, filename) with File(filename) as f: if self.las_header is None: self.las_header = f.header.copy() if self.max_points is not None and self.max_points < f.header.point_records_count: mask = Mask(f.header.point_records_count, False) mask[np.random.choice(f.header.point_records_count, self.max_points)] = True else: mask = Mask(f.header.point_records_count, True) new_df = pd.DataFrame(np.array((f.x, f.y, f.z)).T[mask.bools]) new_df.columns = ['x', 'y', 'z'] print(f.header.data_format_id) if f.header.data_format_id in [2, 3, 5, 7, 8]: rgb = pd.DataFrame( np.array((f.red, f.green, f.blue), dtype='int').T[mask.bools]) rgb.columns = ['r', 'g', 'b'] new_df = new_df.join(rgb) new_df['class'] = f.classification[mask.bools] if np.sum(f.user_data): new_df['user_data'] = f.user_data[mask.bools].copy() if np.sum(f.intensity): new_df['intensity'] = f.intensity[mask.bools].copy() self.points = self.points.append(new_df, sort=False) if filename == 'TEMPORARY.las': os.system('rm TEMPORARY.las')
def lasToRaster(las_filename, transform, shape_out, NODATA): # Load LAS file test_las = File(las_filename, mode='r') x = test_las.x y = test_las.y z = test_las.z # Project to output image space # TODO: call map2pix map_to_pix = gdal.InvGeoTransform(transform) x0 = np.round(map_to_pix[0] + x * map_to_pix[1] + y * map_to_pix[2]) y0 = np.round(map_to_pix[3] + x * map_to_pix[4] + y * map_to_pix[5]) x0 = x0.astype(int) y0 = y0.astype(int) # Generate MAX value DSM raster = np.zeros(shape_out, np.float32) + NODATA for ii in range(0, x0.size): if (x0[ii] >= 0) & (x0[ii] < raster.shape[1]) & (y0[ii] >= 0) & ( y0[ii] < raster.shape[0]): if z[ii] > raster[y0[ii], x0[ii]]: raster[y0[ii], x0[ii]] = z[ii] return raster
def write(self): output = self.configs["paths"]["output"] points = np.array(self.points, dtype=self.dtype) #print self.header outfile = File(output + self.filename, mode="w", header=self.header) outfile.points = points outfile.close()
def write_las_file(self): """ Create and write a new lidar file with the desirable points """ if self.surfaces: self.out_full_path = os.path.join( self.out_dir, ('Surfaces_' + self.templates_dict['las'].format(self.name))) elif self.terrain: self.out_full_path = os.path.join( self.out_dir, ('Terrain_' + self.templates_dict['las'].format(self.name))) out_file = File(self.out_full_path, mode='w', header=self.in_file.header) if self.terrain: class_2_points, class_2_bool = self.get_points_by_class( self.class_flag) out_file.points = self.in_file.points[class_2_bool] elif self.surfaces: out_file.points = self.in_file.points[self.in_file.return_num == 1] out_file.close()
def write_obj(file_path: FilePath, xyz: ndarray, rgb: ndarray = None, scale: float = 1e-05): """Write :param:`xyz` and :param:`rgb` to .las file.""" file_path = Path(file_path).with_suffix(extensions['las']['format']) point_format = 0 if rgb is not None and rgb.shape[1] > 0: if xyz.shape != rgb.shape: raise ValueError(f'xyz and rgb shape must match.\n' f'Got {xyz.shape} and {rgb.shape}') point_format = 2 header = Header(point_format=point_format) with File(str(file_path), mode="w", header=header) as f: f.header.scale = (scale, scale, scale) f.header.offset = np.min(xyz, axis=0) f.x = xyz[:, 0] f.y = xyz[:, 1] f.z = xyz[:, 2] if rgb is not None and rgb.shape[1] > 0: f.red = rgb[:, 0] * 2**8 f.green = rgb[:, 1] * 2**8 f.blue = rgb[:, 2] * 2**8 return file_path.resolve()
def prepare_data(point_file, number_of_points=None, point_cloud_class=None, segmentation_label_file=None, segmentation_classes_offset=None): infile = File(point_file, mode="r") x, y, z = infile.x, infile.y, infile.z min_x, min_y, min_z = np.min(x), np.min(y), np.min(z) x = np.array((1/0.01)*(x - min_x), dtype=np.int) y = np.array((1/0.01)*(y - min_y), dtype=np.int) z = np.array((1/0.01)*(z - min_z), dtype=np.int) point_cloud = np.stack((x, y, z), axis=1).astype(np.float32) if number_of_points: sampling_indices = np.random.choice(point_cloud.shape[0], number_of_points) point_cloud = point_cloud[sampling_indices, :] point_cloud = torch.from_numpy(point_cloud) if segmentation_label_file: segmentation_classes = np.loadtxt(segmentation_label_file).astype(np.int64) if number_of_points: segmentation_classes = segmentation_classes[sampling_indices] segmentation_classes = segmentation_classes + segmentation_classes_offset -1 segmentation_classes = torch.from_numpy(segmentation_classes) return point_cloud, segmentation_classes elif point_cloud_class is not None: point_cloud_class = torch.tensor(point_cloud_class) return point_cloud, point_cloud_class else: return point_cloud
def main(): ''' read data from file ''' print('Reading files') file1='F:/temp/Brisbane_2014_LGA_SW_502000_6965000_1K_Las.laz' tic = time.perf_counter() inFile1 = File(file1, mode='r') toc = time.perf_counter() print(f"{len(inFile1.points):d} records read from {file1:s} in {toc - tic:0.4f} seconds") print('permuting data') tic = time.perf_counter() xvalues=inFile1.get_x_scaled() yvalues=inFile1.get_y_scaled() zvalues=inFile1.get_z_scaled() tvalues=inFile1.get_gps_time() pointclasses=inFile1.get_classification() #tile lower left corner originx, originy=502000,6965000 xoffset=randrange(-500000,500000) yoffset=randrange(-500000,500000) zoffset=randrange(-200,200)``
def getBorderPoints(): path = raw_input("Input file path: ") # lasFile = File('/home/linche/Desktop/Foresight/ROS/0615_las_test/1648443908000pcdboardSeg.las', mode='r') lasFile = File(path, mode='r') ##############Getting all border points################ # Look at what laser_id values there are and store in a list readDic = {} for idNum in lasFile.pt_src_id: readDic[idNum] = 1 idList = readDic.keys() # Build a dictionary with laser_id as keys and a list of cloud point indices as values # Initialize dictionary idDic = {} for i in range(len(idList)): idDic.setdefault(idList[i], []) # Store cloud points in their repective laser_ids for i in range(len(lasFile.pt_src_id)): idDic[ lasFile.pt_src_id[i] ].append(i) # Get timestamp of each point in each laser_id and select out the min and max indices # Initialize output array: Nx2 -> N id channels, 2 columns corresponding to min, max borderPointIdx = np.zeros( (len(idList), 2) ) for i in range(len(idList)): # for each laser_id idx = idDic[ idList[i] ] # the index of points in a given laser_id ts_vals = lasFile.gps_time[idx] # print("ts_vals: ") # print(ts_vals) min_idx = np.argmin(ts_vals) max_idx = np.argmax(ts_vals) borderPointIdx[i, 0] = idx[min_idx] borderPointIdx[i, 1] = idx[max_idx] print("borderPointIdx: ") print(borderPointIdx) borderPointIdx = borderPointIdx.flatten() borderPointIdx = borderPointIdx.astype(int) offset = lasFile.header.offset x_offset = offset[0] y_offset = offset[1] z_offset = offset[2] xs_border = lasFile.X[borderPointIdx]/100.0 + x_offset ys_border = lasFile.Y[borderPointIdx]/100.0 + y_offset zs_border = lasFile.Z[borderPointIdx]/100.0 + z_offset borderPoints = np.vstack((xs_border,ys_border)) borderPoints = np.vstack((borderPoints,zs_border)) borderPoints = borderPoints.T print("borderPoints.shape: ") print(borderPoints.shape) return borderPoints
def load(file): with File(file.as_posix(), mode='r') as las_data: las_df = pd.DataFrame(las_data.points['point'], dtype=float).drop(dropped_columns, axis=1) las_df.X = las_df.X * 0.01 las_df.Y = las_df.Y * 0.01 las_df.Z = las_df.Z * 0.01 return las_df
def save_las(xyzc, header, path): # header = Header() outfile = File(path, mode="w", header=header) outfile.X = xyzc[:, 0] outfile.Y = xyzc[:, 1] outfile.Z = xyzc[:, 2] outfile.Classification = xyzc[:, 3].astype(np.uint8) outfile.close()