Extract On-Road and Off-Road Points from Point Cloud
This example shows how to extract on-road and off-road points from point cloud data.
Detecting road boundaries is an essential part of autonomous vehicle localization and decision-making. Road boundaries usually include curbs, walls, and berms.
In most scenarios, the boundary of a road is defined by the curb. A curb connects the roadway to the sidewalk. Curbs are important for safe driving, as they distinguish the drivable area from the restricted region.
To extract curb points, you must first process the point cloud data to distinguish on-road and off-road points. The on-road area consists of sidewalks, curbs, and road surfaces. The off-road area usually consists of trees, buildings, and other objects. You can extract on-road and off-road points using algorithms such as plane-fitting or ground segmentation, depending on your input data.
Plane-Fitting Method
Preprocess Point Cloud
Read the point cloud data into the workspace.
inputPtCloud = pcread(fullfile(toolboxdir("lidar"),"lidardata", ... "sampleWPIPointClouds","pointClouds","005.pcd"));
Extract a region of interest containing a road area from the point cloud.
xLim = [0 25];
yLim = [-10 10];
roiIdx = findPointsInROI(inputPtCloud,[xLim yLim inputPtCloud.ZLimits]);
ptCloud = select(inputPtCloud,roiIdx,OutputSize="full");
Divide the point cloud into grids.
gridSize = [1 1]; % in meters
ptCloud = pointCloud(reshape(ptCloud.Location(:,:,:),[],3));
numGridsX = round(diff(ptCloud.XLimits)/gridSize(1));
numGridsY = round(diff(ptCloud.YLimits)/gridSize(2));
Extract the point indices from each grid.
indices = pcbin(ptCloud,[numGridsX numGridsY 1]);
Extract Off-Road Points
Specify an off-road height threshold.
offRoadHeightThreshold = 1.5; % in meters
Extract the indices of the off-road points from the grids.
offRoadPointsIdx = false(size(ptCloud.Location,1),1); for i=1:numGridsX*numGridsY if ~isempty(indices{i}) gridHeight = ptCloud.Location(indices{i},3); if (max(gridHeight) - min(gridHeight)) > offRoadHeightThreshold offRoadPointsIdx(indices{i}) = true; end end end
Extract the off-road point cloud.
offRoadPtCloud = select(inputPtCloud,offRoadPointsIdx);
Extract On-Road Points
Extract the on-road points from the remaining points in the point cloud by using the pcfitplane
function. Alternatively, you can use the segmentGroundFromLidarData
function.
remainingPtCloud = select(inputPtCloud,~offRoadPointsIdx,OutputSize="full"); [~,inlierIdx,~] = pcfitplane(remainingPtCloud,1,[0 0 1]); onRoadPtCloud = select(remainingPtCloud,inlierIdx,OutputSize="full");
Display the on-road and off-road points.
pcshowpair(offRoadPtCloud,onRoadPtCloud)
Ground Segmentation Method
Preprocess Point Cloud
Read point cloud data into the workspace.
ptCloud = pcread("HDL64LidarData.pcd");
Organize the point cloud.
ptCloud = pcorganize(ptCloud,lidarParameters("HDL64E",1024));
Extract a region of interest containing a road area from the point cloud.
roi = [-25 25 -10 24 ptCloud.ZLimits];
indices = findPointsInROI(ptCloud,roi);
ptCloud = select(ptCloud,indices,OutputSize="full");
Extract On-Road and Off-Road Points
Segment the on-road and off-road points from the point cloud by using the segmentGroundSMRF
function. Alternatively, you can use the segmentGroundFromLidarData
function.
[~,offRoadPtCloud,onRoadPtCloud] = segmentGroundSMRF(ptCloud);
Display the on-road and off-road points.
pcshowpair(offRoadPtCloud,onRoadPtCloud)
Detecting Road Boundary
After extracting the on-road and off-road points, you can further process them by using the detectRoadAngles
function, to identify the road directions. Then, use the segmentCurbPoints
function to extract the curb points from the on-road point cloud.
See Also
Functions
detectRoadAngles
|segmentCurbPoints
|segmentGroundSMRF
|segmentLidarData
|segmentGroundFromLidarData