-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBoundingBoxDetector.m
153 lines (136 loc) · 6.3 KB
/
BoundingBoxDetector.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
146
147
148
149
150
151
classdef BoundingBoxDetector < matlab.System
% BoundingBoxDetector 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.
%
% Copyright 2020 The MathWorks, Inc.
% 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;
% Range of Cluster Length(min-max)
RangeOfClusterLength = [2 5];
% Range of Cluster Width(min-max)
RangeOfClusterWidth = [1 3];
% Range of Cluster Height(min-max)
RangeOfClusterHeight = [1 10];
end
% Ego vehicle radius to remove ego vehicle point cloud.
properties
% EgoVehicleRadius Radius of ego vehicle
EgoVehicleRadius = 3;
end
methods
function obj = BoundingBoxDetector(varargin)
setProperties(obj,nargin,varargin{:})
end
end
methods (Access = protected)
function [pcObstacles, labels, validLabels, detBBoxes] = 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
% クラスタリングとBoundingBox作成
[detBBoxes,labels, validLabels] = getBoundingBoxes(pcObstacles,obj.SegmentationMinDistance,obj.MinDetectionsPerCluster,obj.MaxZDistanceCluster,obj.MinZDistanceCluster,...
obj.RangeOfClusterLength, obj.RangeOfClusterWidth, obj.RangeOfClusterHeight);
end
end
end
function [bboxes, labels, validLabels] = getBoundingBoxes(ptCloud,minDistance,minDetsPerCluster,maxZDistance,minZDistance,...
clusterLength,clusterWidth,clusterHeight)
% 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]';
% Select cluster which is in user defined range.
isValidCluster(i) = l > clusterLength(1) && l < clusterLength(2) &&...
w > clusterWidth(1) && w < clusterWidth(2) &&....
h > clusterHeight(1) && h < clusterHeight(2);
end
end
bboxes = bboxes(:,isValidCluster);
validLabels = find(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;
locations = reshape(locations,[],3);
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