def get_largest_dbscan_clusters(pointcloud, min_return_fragment=0.7, epsilon=0.1, minpoints=250, rgb_weight=0): ''' Finds the largest clusters containing together at least min_return_fragment of the complete point cloud. In case less points belong to clusters, all clustered points are returned. Parameters ---------- pointcloud : pcl.PointCloud Input pointcloud. min_return_fragment : float Minimum desired fragment of pointcloud to be returned epsilon : float Neighborhood radius for DBSCAN. minpoints : integer Minimum neighborhood density for DBSCAN. rgb_weight : float, optional If non-zero, cluster on color information as well as location; specifies the relative weight of the RGB components to spatial coordinates in distance computations. (RGB values have wildly different scales than spatial coordinates.) Returns ------- cluster : pcl.PointCloud Registered pointcloud of the largest cluster found by dbscan. ''' labels = dbscan_labels(pointcloud, epsilon, minpoints, rgb_weight=rgb_weight).astype(np.int64) selection, selected_count = _get_top_labels(labels, min_return_fragment) # No clusters were found if selected_count < min_return_fragment * len(labels): return extract_mask(pointcloud, np.ones(len(pointcloud), dtype=bool)) else: mask = [label in selection for label in labels] return extract_mask(pointcloud, mask)
def get_largest_dbscan_clusters(pointcloud, min_return_fragment=0.7, epsilon=0.1, minpoints=250, rgb_weight=0): """ Finds the largest clusters containing together at least min_return_fragment of the complete point cloud. In case less points belong to clusters, all clustered points are returned. Parameters ---------- pointcloud : pcl.PointCloud Input pointcloud. min_return_fragment : float Minimum desired fragment of pointcloud to be returned epsilon : float Neighborhood radius for DBSCAN. minpoints : integer Minimum neighborhood density for DBSCAN. rgb_weight : float, optional If non-zero, cluster on color information as well as location; specifies the relative weight of the RGB components to spatial coordinates in distance computations. (RGB values have wildly different scales than spatial coordinates.) Returns ------- cluster : pcl.PointCloud Registered pointcloud of the largest cluster found by dbscan. """ labels = dbscan_labels(pointcloud, epsilon, minpoints, rgb_weight=rgb_weight).astype(np.int64) selection, selected_count = _get_top_labels(labels, min_return_fragment) # No clusters were found if selected_count < min_return_fragment * len(labels): return extract_mask(pointcloud, np.ones(len(pointcloud), dtype=bool)) else: mask = [label in selection for label in labels] return extract_mask(pointcloud, mask)
def get_stick_scale(pointcloud, eps=0.1, min_samples=20): """Takes a point cloud, as a numpy array, looks for red segments of scale sticks and returns the scale estimation with most support. Method: pointcloud --dbscan--> clusters --lengthEstimation--> lengths --ransac--> best length Arguments: pointcloud Point cloud containing only measuring stick segments (only the red, or only the white parts) eps DBSCAN parameter: Maximum distance between two samples for them to be considered as in the same neighborhood. min_samples DBSCAN parameter: The number of samples in a neighborhood for a point to be considered as a core point. Returns: scale Estimate of the size of one actual meter in expressed in units of the pointcloud's coordinates. confidence A number expressing the reliability of the estimated scale. Confidence is in [0, 1]. With a confidence greater than .5, the estimate can be considered useable for further calculations. """ # quickly return for trivial case if pointcloud.size == 0: return 1, 0 # find the red segments to measure pc_reds = extract_mask(pointcloud, get_red_mask(pointcloud)) if len(pc_reds) == 0: # unit scale, zero confidence (ie. any other estimation is better) return 1.0, 0.0 cluster_generator = segment_dbscan( pc_reds, eps, min_samples, algorithm='kd_tree') sizes = [{'len': len(cluster), 'meter': measure_length(cluster) * SEGMENTS_PER_METER} for cluster in cluster_generator] if len(sizes) == 0: return 1.0, 0.0 scale, votes, n_clusters = ransac(sizes) confidence = get_confidence_level(votes, n_clusters) return scale, confidence
def segment_dbscan(pointcloud, epsilon, minpoints, **kwargs): """Run the DBSCAN clustering+outlier detection algorithm on pointcloud. Parameters ---------- pointcloud : pcl.PointCloud Input pointcloud. epsilon : float Neighborhood radius for DBSCAN. minpoints : integer Minimum neighborhood density for DBSCAN. **kwargs : keyword arguments, optional arguments passed to _dbscan_labels Returns ------- clusters : iterable over registered PointCloud """ labels = dbscan_labels(pointcloud, epsilon, minpoints, **kwargs) return (extract_mask(pointcloud, labels == label) for label in np.unique(labels[labels != -1]))
#!/usr/bin/env python """Segment points by colour from a pointcloud file and saves all reddish points target pointcloud file. Autodectects ply, pcd and las files. Usage: redstickdetection.py [-h] <infile> <outfile> """ from docopt import docopt from patty.segmentation.segRedStick import get_red_mask from patty.utils import extract_mask, load, save if __name__ == '__main__': args = docopt(__doc__) pc = load(args['<infile>']) red_pc = extract_mask(pc, get_red_mask(pc)) save(red_pc, args['<outfile>'])