Source code for laserfarm.classification

import logging
import pathlib
import numpy as np
import shapefile
import shapely
import laserfarm
import laserchicken
from shapely.geometry import shape
from laserfarm.pipeline_remote_data import PipelineRemoteData
from laserchicken.io.load import load
from laserchicken.io.export import export
from laserchicken import filter

logger = logging.getLogger(__name__)


[docs] class Classification(PipelineRemoteData): """ Classify points using polygons provided as shapefiles. """ def __init__(self, input_file=None, label=None): self.pipeline = ('locate_shp', 'classification', 'export_point_cloud') self.input_shp = [] self.point_cloud = None if input_file is not None: self.input_path = input_file if label is not None: self.label = label
[docs] def locate_shp(self, shp_dir): """ Locate the corresponding ESRI shape file of the point cloud :param shp_dir: directory which contains all candidate shp file for classification """ laserfarm.utils.check_file_exists(self.input_path, should_exist=True) pc = load(self.input_path.as_posix()) shp_path = self.input_folder / shp_dir laserfarm.utils.check_dir_exists(shp_path, should_exist=True) # Get boundary of the point cloud self.point_cloud = pc x = pc[laserchicken.keys.point]['x']['data'] y = pc[laserchicken.keys.point]['y']['data'] point_box = shapely.geometry.box(np.min(x), np.min(y), np.max(x), np.max(y)) for shp in sorted([f.absolute() for f in shp_path.iterdir() if f.suffix == '.shp']): sf = shapefile.Reader(shp.as_posix()) mbr = shapely.geometry.box(*sf.bbox) if point_box.intersects(mbr): self.input_shp.append(shp) return self
[docs] def classification(self, ground_type): """ Classify the pointset according to the given shape file. A new feature "ground_type" will be added to the point cloud. The value of the column identify the ground type. :param ground_type: identifier of the groud type. 0 is not identified. """ # Get the mask of points which fall in the shape file(s) pc_mask = np.zeros(len(self.point_cloud['vertex']['x']['data']), dtype=bool) for shp in self.input_shp: this_mask = filter.select_polygon(self.point_cloud, shp.as_posix(), read_from_file=True, return_mask=True) pc_mask = np.logical_or(pc_mask, this_mask) # Add the ground type feature laserchicken.utils.update_feature(self.point_cloud, feature_name='ground_type', value=ground_type, array_mask=pc_mask) # Clear the cached KDTree laserchicken.kd_tree.initialize_cache() return self
[docs] def export_point_cloud(self, filename='', overwrite=False): """ Export the classified point cloud :param filename: filename where to write point-cloud data :param overwrite: if file exists, overwrite """ if pathlib.Path(filename).parent.name: raise IOError('filename should not include path!') if not filename: filename = '_classification'.join([self.input_path.stem, self.input_path.suffix]) export_path = (self.output_folder / filename).as_posix() export(self.point_cloud, export_path, overwrite=overwrite) return self