API reference¶
Registration¶
-
patty.registration.
get_stick_scale
(pointcloud, eps=0.1, min_samples=20)[source]¶ 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.
-
patty.registration.
align_footprints
(loose_pc, fixed_pc, allow_scaling=True, allow_rotation=True, allow_translation=True)[source]¶ Align a pointcloud ‘loose_pc’ by placing it on top of ‘fixed_pc’ as good as poosible. Done by aligning the principle axis of both pointclouds.
NOTE: Both pointclouds are assumed to be the footprint (or projection) on the xy plane, with basically zero extent along the z-axis.
- (allow_rotation=True)
- The pointcloud boundary is alinged with the footprint by rotating its pricipal axis in the (x,y) plane.
- (allow_translation=True)
- Then, it is translated so the centers of mass coincide.
- (allow_scaling=True)
- Finally, the pointcloud is scaled to have the same extent.
- Arguments:
loose_pc : pcl.PointCloud fixed_pc : pcl.PointCloud
allow_scaling : Bolean allow_rotation : Bolean allow_translation : Bolean
- Returns:
- rot_matrix, rot_center, scale, translation : np.array()
-
patty.registration.
coarse_registration
(pointcloud, drivemap, footprint, downsample=None)[source]¶ Improve the initial registration. Find the proper scale by looking for the red meter sticks, and calculate and align the pointcloud’s footprint.
- Arguments:
- pointcloud: pcl.PointCloud
- The high-res object to register.
- drivemap: pcl.PointCloud
- A small part of the low-res drivemap on which to register
- footprint: pcl.PointCloud
- Pointlcloud containing the objects footprint
- downsample: float, default=None, no resampling
- Downsample the high-res pointcloud before footprint calculation.
-
patty.registration.
estimate_pancake_up
(pointcloud)[source]¶ Assuming a pancake like pointcloud, the up direction is the third PCA.
-
patty.registration.
find_rotation_xy
(pc, ref)[source]¶ Find the transformation that rotates the principal axis of the pointcloud onto those of the reference. Keep the z-axis pointing upwards.
- Arguments:
pc: pcl.PointCloud
ref: pcl.PointCloud
- Returns:
- numpy array of shape [3,3], can be used to rotate pointclouds with pc.rotate()
-
patty.registration.
fine_registration
(pointcloud, drivemap, center, voxelsize=0.05)[source]¶ Final registration step using ICP.
Find the local optimal postion of the pointcloud on the drivemap; due to our coarse_registration algorithm, we have to try two orientations: original, and rotated by 180 degrees around the z-axis.
- Arguments:
- pointcloud: pcl.PointCloud
- The high-res object to register.
- drivemap: pcl.PointCloud
- A small part of the low-res drivemap on which to register
- center: np.array([3])
- Vector giving the centerpoint of the pointcloud, used to do the 180 degree rotations.
- voxelsize: float default : 0.05
- Size in [m] of the voxel grid used for downsampling
-
patty.registration.
initial_registration
(pointcloud, up, drivemap, initial_scale=None, trust_up=True)[source]¶ Initial registration adds an spatial reference system to the pointcloud, and place the pointlcoud on top of the drivemap. The pointcloud is rotated so that the up vector points along [0,0,1], and scaled such that it has the right order of magnitude in size.
- Arguments:
- pointcloud : pcl.PointCloud
- The high-res object to register.
- up: np.array([3])
- Up direction for the pointcloud. If None, assume the object is pancake shaped, and chose the upvector such that it is perpendicullar to the pancake.
- drivemap : pcl.PointCloud
- A small part of the low-res drivemap on which to register.
- initial_scale : float
- if given, scale pointcloud using this value; estimate scale factor from bounding boxes.
- trust_up : Boolean, default to True
True: Assume the up vector is exact. False: Calculate ‘up’ as if it was None, but orient it such that
np.dot( up, pancake_up ) > 0
NOTE: Modifies the input pointcloud in-place, and leaves it in a undefined state.
Segmentation¶
-
patty.segmentation.
dbscan_labels
(pointcloud, epsilon, minpoints, rgb_weight=0, algorithm='ball_tree')[source]¶ Find an array of point-labels of clusters found by the DBSCAN algorithm.
- pointcloud : pcl.PointCloud
- Input pointcloud.
- 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.)
- labels : Sequence
- A sequence of labels per point. Label -1 indicates a point does not belong to any cluster, other labels indicate the cluster number a point belongs to.
-
patty.segmentation.
get_largest_dbscan_clusters
(pointcloud, min_return_fragment=0.7, epsilon=0.1, minpoints=250, rgb_weight=0)[source]¶ 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.
- 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.)
- cluster : pcl.PointCloud
- Registered pointcloud of the largest cluster found by dbscan.
-
patty.segmentation.
segment_dbscan
(pointcloud, epsilon, minpoints, **kwargs)[source]¶ Run the DBSCAN clustering+outlier detection algorithm on pointcloud.
- 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
clusters : iterable over registered PointCloud
-
patty.segmentation.
get_red_mask
(pointcloud)[source]¶ Returns a mask for the red parts of a pointcloud.
Red points are points that have hue larger than 0.9 and saturation larger than 0.5 in HSV colorspace.
-
patty.segmentation.
boundary_of_center_object
(pc, downsample=None, angle_threshold=0.1, search_radius=0.1, normal_search_radius=0.1)[source]¶ Find the boundary of the main object. First applies dbscan to find the main object, then estimates its footprint by taking the pointcloud boundary. Resulting pointcloud has the same SRS and offset as the input.
- Arguments:
pointcloud : pcl.PointCloud
- downsample : If given, reduce the pointcloud to given percentage
- values should be in [0,1]
angle_threshold : float defaults to 0.1
search_radius : float defaults to 0.1
normal_search_radius : float defaults to 0.1
- Returns:
- boundary : pcl.PointCloud
-
patty.segmentation.
boundary_of_drivemap
(drivemap, footprint, height=1.0, edge_width=0.25)[source]¶ Construct an object boundary using the manually recorded corner points. Do this by finding all the points in the drivemap along the footprint. Use the bottom ‘height’ meters of the drivemap (not trees). Resulting pointcloud has the same SRS and offset as the input.
- Arguments:
drivemap : pcl.PointCloud footprint : pcl.PointCloud height : Cut-off height, points more than this value above the
lowest point of the drivemap are considered trees, and dropped. default 1 m.- edge_width : Points belong to the boundary when they are within
- this distance from the footprint. default 0.25
- Returns:
- boundary : pcl.PointCloud
-
patty.segmentation.
boundary_of_lowest_points
(pc, height_fraction=0.01)[source]¶ Construct an object boundary by taking the lowest (ie. min z coordinate) fraction of points. Resulting pointcloud has the same SRS and offset as the input.
- Arguments:
- pc : pcl.PointCloud height_fraction : float
- Returns:
- boundary : pcl.PointCloud
SRS¶
-
patty.srs.
force_srs
(pc, srs=None, offset=None, same_as=None)[source]¶ Set a spatial reference system (SRS) and offset for a pointcloud. Either give a SRS and offset, or a reference pointcloud This function affects the metadata only.
This is the recommended way to turn a python-pcl pointcloud to a registerd pointcloud with absolute coordiantes.
NOTE: To change the SRS for an already registered pointcloud, use set_srs()
Example:
# set the SRS to lat/lon, leave offset unchanged force_srs( pc, srs=”EPSG:4326” )- Arguments:
pc : pcl.Pointcloud
same_as : pcl.PointCloud
- offset : np.array([3])
- Must be added to the points to get absolute coordinates, neccesary to retain precision for LAS pointclouds.
- srs : object or osgeo.osr.SpatialReference
- If it is an SpatialReference, it will be used directly. Otherwise it is passed to osr.SpatialReference.SetFromUserInput()
- Returns:
- pc : pcl.PointCloud
- The input pointcloud.
-
patty.srs.
is_registered
(pointcloud)[source]¶ Returns True when a pointcloud is registered; ie coordinates are relative to a specific spatial reference system or offset.
In that case, first transform one pointcloud to the reference system of the other, before doing processing on the points:
set_srs(pcA, same_as=pcB)
-
patty.srs.
same_srs
(pc_one, pc_two)[source]¶ True if the two pointclouds have the same coordinate system
- Arguments:
- pc_one : pcl.PointCloud pc_two : pc..PointCloud
-
patty.srs.
set_srs
(pc, srs=None, offset=array([ 0., 0., 0.]), same_as=None)[source]¶ Set the spatial reference system (SRS) and offset for a pointcloud. This function transforms all the points to the new reference system, and updates the metadata accordingly.
Either give a SRS and offset, or a reference pointcloud
- NOTE: Pointclouds in PCL do not have absolute coordinates, ie.
- latitude / longitude. This function sets metadata to the pointcloud describing an absolute frame of reference. It is left to the user to make sure pointclouds are in the same reference system, before passing them on to PCL functions. This can be checked with patty.utils.same_srs().
- NOTE: To add a SRS to a point cloud, or to update incorrect metadata,
- use force_srs().
Example:
# set the SRS to lat/lon, # don’t use an offset, so it defaults to [0,0,0] set_srs( pc, srs=”EPSG:4326” )- Arguments:
pc : pcl.Pointcloud, with pcl.is_registered() == True
same_as : pcl.PointCloud
- offset : np.array([3], dtype=np.float64 )
- Must be added to the points to get absolute coordinates, neccesary to retain precision for LAS pointclouds.
- srs : object or osgeo.osr.SpatialReference
- If it is an SpatialReference, it will be used directly. Otherwise it is passed to osr.SpatialReference.SetFromUserInput()
- Returns:
- pc : pcl.PointCloud
- The input pointcloud.
Utils¶
Pointcloud functions for reading/writing LAS files, and functions for dealing with the spatial reference system.
-
class
patty.utils.
BoundingBox
(points=None, min=None, max=None)[source]¶ A bounding box for a sequence of points.
Center, size and diagonal are updated when the minimum or maximum are updated.
Constructor usage: either set points (any object that is converted to an NxD array by np.asarray, with D the number of dimensions) or a fixed min and max.
-
center
¶ Center point of the bounding box
-
diagonal
¶ Length of the diagonal of the box.
-
size
¶ N-dimensional size array
-
-
patty.utils.
clone
(pc)[source]¶ Return a copy of a pointcloud, including registration metadata
- Arguments:
- pc: pcl.PointCloud()
- Returns:
- cp: pcl.PointCloud()
-
patty.utils.
downsample_random
(pc, fraction, random_seed=None)[source]¶ Randomly downsample pointcloud to a fraction of its size.
Returns a pointcloud of size fraction * len(pc), rounded to the nearest integer. Resulting pointcloud has the same SRS and offset as the input.
Use random_seed=k for some integer k to get reproducible results. Arguments:
- pc : pcl.PointCloud
- Input pointcloud.
- fraction : float
- Fraction of points to include.
- random_seed : int, optional
- Seed to use in random number generator.
- Returns:
- pcl.Pointcloud
-
patty.utils.
downsample_voxel
(pc, voxel_size=0.01)[source]¶ Downsample a pointcloud using a voxel grid filter. Resulting pointcloud has the same SRS and offset as the input.
- Arguments:
- pc : pcl.PointCloud
- Original pointcloud
- float : voxel_size
- Grid spacing for the voxel grid
- Returns:
- pc : pcl.PointCloud
- filtered pointcloud
-
patty.utils.
extract_mask
(pointcloud, mask)[source]¶ Extract all points in a mask into a new pointcloud.
- Arguments:
- pointcloud : pcl.PointCloud
- Input pointcloud.
- mask : numpy.ndarray of bool
- mask for which points from the pointcloud to include.
- Returns:
- pointcloud with the same registration (if any) as the original one.
-
patty.utils.
load
(path, format=None, load_rgb=True)[source]¶ Read a pointcloud file.
Supports LAS and CSV files, and lets PCD and PLY files be read by python-pcl.
- Arguments:
- path : string
- Filename.
- format : string, optional
- File format: “PLY”, “PCD”, “LAS”, “CSV”, or None to detect the format from the file extension.
- load_rgb : bool
- Whether RGB is loaded for PLY and PCD files. For LAS files, RGB is always read.
- Returns:
- pc : pcl.PointCloud
-
patty.utils.
make_las_header
(pointcloud)[source]¶ Make a LAS header for given pointcloud.
If the pointcloud is registered, this is taken into account for the header metadata.
LAS rounds the coordinates on writing; this is controlled via the ‘precision’ attribute of the input pointcloud. By default this is 0.01 in units of the projection.
- Arguments:
- pointcloud : pcl.PointCloud
- Input pointcloud.
- Returns:
- header : liblas.header.Header
- Header for writing the pointcloud to a LAS file.
-
patty.utils.
measure_length
(pointcloud)[source]¶ Returns the length of a point cloud in its longest direction.
-
patty.utils.
save
(cloud, path, format=None, binary=False, las_header=None)[source]¶ Save a pointcloud to file.
Supports LAS and CSV files, and lets PCD and PLY files be saved by python-pcl.
- Arguments:
- cloud : pcl.PointCloud or pcl.PointCloudXYZRGB
- Pointcloud to save.
- path : string
- Filename.
- format : string
- File format: “PLY”, “PCD”, “LAS”, “CSV”, or None to detect the format from the file extension.
- binary : boolean
- Whether PLY and PCD files are saved in binary format.
- las_header: liblas.header.Header
- LAS header to use. When none, a default header is created by make_las_header(). Default: None