Main Content

segmentGroundSMRF

Segment ground from lidar data using a Simple morphological filter (SMRF) algorithm

Description

example

groundPtsIdx = segmentGroundSMRF(ptCloud) segments the input point cloud, ptCloud into ground and non-ground points and returns a logical matrix or vector groundPtsIdx. The function sets the ground point indices to true and false for non-ground points.

groundPtsIdx = segmentGroundSMRF(ptCloud,gridResolution) additionally specifies the dimension of the grid element.

[groundPtsIdx,nonGroundPtCloud,groundPtCloud] = segmentGroundSMRF(___) additionally returns ground points and non-ground points as individual pointCloud objects. Use this syntax with any of the input argument combinations in previous syntaxes.

example

[___] = segmentGroundSMRF(___,Name,Value) specifies options using one or more name-value arguments. For example, 'ElevationThreshold',0.4 sets the elevation threshold for identifying non-ground points to 0.4.

Examples

collapse all

Segment the ground in an unorganized aerial point cloud.

Create a lasFileReader object to access the LAS file data.

fileName = fullfile(toolboxdir('lidar'), 'lidardata', 'las', ...
    'aerialLidarData2.las');
lasReader = lasFileReader(fileName);

Read point cloud data from the LAS file using the readPointCloud function.

ptCloud = readPointCloud(lasReader);

Segment ground data from the point cloud.

[groundPtsIdx,nonGroundPtCloud,groundPtCloud] = segmentGroundSMRF(ptCloud);

Visualize the ground and non-ground points.

figure
pcshowpair(groundPtCloud, nonGroundPtCloud)

Figure contains an axes object. The axes object contains 2 objects of type scatter.

Segment and remove ground from an organized point cloud. The point cloud was captured in a highway scenario.

Load the point cloud data into the workspace.

ld = load('drivingLidarPoints.mat');

Display input point cloud.

pcshow(ld.ptCloud)
xlim([-40 40])
ylim([-50 50])

Figure contains an axes object. The axes object contains an object of type scatter.

Segment ground data from the point cloud.

[~,nonGroundPtCloud,groundPtCloud] = segmentGroundSMRF(...,
  ld.ptCloud,'MaxWindowRadius',5,'ElevationThreshold',0.1,'ElevationScale',0.25);

Visualize the non-ground points.

figure
pcshow(nonGroundPtCloud)
xlim([-40 40])
ylim([-50 50])

Figure contains an axes object. The axes object contains an object of type scatter.

Input Arguments

collapse all

Point cloud data, specified as a pointCloud object.

Dimension of each grid element, specified as a positive scalar.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

Name-Value Arguments

Specify optional comma-separated pairs of Name,Value arguments. Name is the argument name and Value is the corresponding value. Name must appear inside quotes. You can specify several name and value pair arguments in any order as Name1,Value1,...,NameN,ValueN.

Example: 'ElevationThreshold',0.4 sets the elevation threshold to identify non-ground points to 0.4.

Maximum radius of the disk-shaped structuring element in the morphological opening operation, specified as a positive scalar. Increase this value to segment large buildings as non-ground at the expense of additional computation.

Note

The default value works effectively for aerial lidar data. For better performance on terrestrial data, set MaxWindowRadius to a smaller value like 8.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

Slope threshold to identify non-ground grid elements in the minimum elevation surface map, specified as a nonnegative scalar. The function classifies a grid element as non-ground if its slope is greater than SlopeThreshold. Increase this value to classify steep slopes as ground.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

Elevation threshold to identify non-ground points, specified as a nonnegative scalar. The function classifies a point as non-ground if the elevation difference between the point and estimated ground surface is greater than ElevationThreshold. Increase this value to encompass more points from bumpy ground.

Note

The default value works effectively for aerial lidar data. For best results on terrestrial data, set ElevationThreshold to a smaller value like 0.1.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

Elevation threshold scaling factor with respect to the slope of the estimated ground surface, specified as a nonnegative scalar. Increase this value to identify ground points on steep slopes.

Data Types: single | double | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64

Output Arguments

collapse all

Binary map of the segmented point cloud, returned as a logical matrix for organized point clouds, and as a logical vector for unorganized point clouds. The function sets the locations of ground points in the matrix to true and non-ground points to false.

Point cloud of non-ground points, returned as a pointCloud object.

Point cloud of ground points, returned as a pointCloud object.

Algorithms

A simple morphological filter (SMRF) algorithm [1] segments point cloud data into ground and non-ground points. The algorithm is divided into three stages:

  1. Create a minimum elevation surface from the point cloud data.

  2. Segment the surface into ground and non-ground grid elements.

  3. Segment the original point cloud data.

Minimum Surface Creation

  1. Divide the point cloud data into a grid along the xy-dimension (bird's eye view). Specify the grid element dimension using gridResolution.

  2. Find the lowest elevation (Zmin) value for each grid element (pixel).

  3. Combine all the Zmin values into a 2-D matrix (raster image) to create a minimum elevation surface map.

Surface Map Segmentation

  1. Apply a morphological opening operation on the minimum surface map. For more information about morphological opening, see Types of Morphological Operations.

  2. Use a disk-shaped structuring element with a radius of 1 pixel. For more information, see Structuring Elements.

  3. Calculate the slope between the minimum surface and opened surface maps at each grid element. If the difference is greater than elevation threshold, classify the pixel as non-ground.

  4. Execute steps 1 through 3 iteratively. Increase the structuring element radius by 1 pixel in each iteration until it reaches the maximum radius specified by MaxWindowRadius.

  5. The end result of the iteration process is a binary mask where each pixel is classified as being either ground or non-ground.

Point Cloud Segmentation

  1. Apply the binary mask on the original minimum surface map to remove non-ground grids.

  2. Fill the unfilled grids using image interpolation techniques to create an estimated elevation model.

  3. Calculate the elevation difference between each point in the original point cloud and the estimated elevation model. If the difference is greater than ElevationThreshold, classify the pixel as non-ground.

References

[1] Pingel, Thomas J., Keith C. Clarke, and William A. McBride. “An Improved Simple Morphological Filter for the Terrain Classification of Airborne LIDAR Data.” ISPRS Journal of Photogrammetry and Remote Sensing 77 (March 2013): 21–30.

Extended Capabilities

Introduced in R2021a