-
Notifications
You must be signed in to change notification settings - Fork 1
/
HelperBoundingBoxDetector.m
145 lines (133 loc) · 5.99 KB
/
HelperBoundingBoxDetector.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
classdef HelperBoundingBoxDetector < matlab.System
% HelperBoundingBoxDetector A helper class to segment the point cloud
% into bounding box detections.
% The step call to the object does the following things:
%
% 1. Removes point cloud outside the limits.
% 2. From the survived point cloud, segments out ground
% 3. From the obstacle point cloud, forms clusters and puts bounding
% box on each cluster.
% Cropping properties
properties
% XLimits XLimits for the scene
XLimits = [-70 70];
% YLimits YLimits for the scene
YLimits = [-6 6];
% ZLimits ZLimits fot the scene
ZLimits = [-2 10];
end
% Ground Segmentation Properties
properties
% GroundMaxDistance Maximum distance of point to the ground plane
GroundMaxDistance = 0.3;
% GroundReferenceVector Reference vector of ground plane
GroundReferenceVector = [0 0 1];
% GroundMaxAngularDistance Maximum angular distance of point to reference vector
GroundMaxAngularDistance = 5;
end
% Bounding box Segmentation properties
properties
% SegmentationMinDistance Distance threshold for segmentation
SegmentationMinDistance = 1.6;
% MinDetectionsPerCluster Minimum number of detections per cluster
MinDetectionsPerCluster = 2;
% MaxZDistanceCluster Maximum Z-coordinate of cluster
MaxZDistanceCluster = 3;
% MinZDistanceCluster Minimum Z-coordinate of cluster
MinZDistanceCluster = -3;
end
% Ego vehicle radius to remove ego vehicle point cloud.
properties
% EgoVehicleRadius Radius of ego vehicle
EgoVehicleRadius = 3;
end
properties
% MeasurementNoise Measurement noise for the bounding box detection
MeasurementNoise = blkdiag(eye(3),eye(3));
end
methods
function obj = HelperBoundingBoxDetector(varargin)
setProperties(obj,nargin,varargin{:})
end
end
methods (Access = protected)
function [bboxDets,obstacleIndices,groundIndices,croppedIndices] = stepImpl(obj,currentPointCloud,time)
% Crop point cloud
[pcSurvived,survivedIndices,croppedIndices] = cropPointCloud(currentPointCloud,obj.XLimits,obj.YLimits,obj.ZLimits,obj.EgoVehicleRadius);
% Remove ground plane
[pcObstacles,obstacleIndices,groundIndices] = removeGroundPlane(pcSurvived,obj.GroundMaxDistance,obj.GroundReferenceVector,obj.GroundMaxAngularDistance,survivedIndices);
% Form clusters and get bounding boxes
detBBoxes = getBoundingBoxes(pcObstacles,obj.SegmentationMinDistance,obj.MinDetectionsPerCluster,obj.MaxZDistanceCluster,obj.MinZDistanceCluster);
% Assemble detections
bboxDets = assembleDetections(detBBoxes,obj.MeasurementNoise,time);
end
end
end
function detections = assembleDetections(bboxes,measNoise,time)
% This method assembles the detections in objectDetection format.
numBoxes = size(bboxes,2);
detections = cell(numBoxes,1);
for i = 1:numBoxes
detections{i} = objectDetection(time,cast(bboxes(:,i),'double'),...
'MeasurementNoise',double(measNoise),'ObjectAttributes',struct);
end
end
function bboxes = getBoundingBoxes(ptCloud,minDistance,minDetsPerCluster,maxZDistance,minZDistance)
% This method fits bounding boxes on each cluster with some basic
% rules.
% Cluster must have atleast minDetsPerCluster points.
% Its mean z must be between maxZDistance and minZDistance.
% length, width and height are calculated using min and max from each
% dimension.
[labels,numClusters] = pcsegdist(ptCloud,minDistance);
pointData = ptCloud.Location;
bboxes = nan(6,numClusters,'like',pointData);
isValidCluster = false(1,numClusters);
for i = 1:numClusters
thisPointData = pointData(labels == i,:);
meanPoint = mean(thisPointData,1);
if size(thisPointData,1) > minDetsPerCluster && ...
meanPoint(3) < maxZDistance && meanPoint(3) > minZDistance
xMin = min(thisPointData(:,1));
xMax = max(thisPointData(:,1));
yMin = min(thisPointData(:,2));
yMax = max(thisPointData(:,2));
zMin = min(thisPointData(:,3));
zMax = max(thisPointData(:,3));
l = (xMax - xMin);
w = (yMax - yMin);
h = (zMax - zMin);
x = (xMin + xMax)/2;
y = (yMin + yMax)/2;
z = (zMin + zMax)/2;
bboxes(:,i) = [x y z l w h]';
isValidCluster(i) = l < 20; % max length of 20 meters
end
end
bboxes = bboxes(:,isValidCluster);
end
function [ptCloudOut,obstacleIndices,groundIndices] = removeGroundPlane(ptCloudIn,maxGroundDist,referenceVector,maxAngularDist,currentIndices)
% This method removes the ground plane from point cloud using
% pcfitplane.
[~,groundIndices,outliers] = pcfitplane(ptCloudIn,maxGroundDist,referenceVector,maxAngularDist);
ptCloudOut = select(ptCloudIn,outliers);
obstacleIndices = currentIndices(outliers);
groundIndices = currentIndices(groundIndices);
end
function [ptCloudOut,indices,croppedIndices] = cropPointCloud(ptCloudIn,xLim,yLim,zLim,egoVehicleRadius)
% This method selects the point cloud within limits and removes the
% ego vehicle point cloud using findNeighborsInRadius
locations = ptCloudIn.Location;
insideX = locations(:,1) < xLim(2) & locations(:,1) > xLim(1);
insideY = locations(:,2) < yLim(2) & locations(:,2) > yLim(1);
insideZ = locations(:,3) < zLim(2) & locations(:,3) > zLim(1);
inside = insideX & insideY & insideZ;
% Remove ego vehicle
nearIndices = findNeighborsInRadius(ptCloudIn,[0 0 0],egoVehicleRadius);
nonEgoIndices = true(ptCloudIn.Count,1);
nonEgoIndices(nearIndices) = false;
validIndices = inside & nonEgoIndices;
indices = find(validIndices);
croppedIndices = find(~validIndices);
ptCloudOut = select(ptCloudIn,indices);
end