Apollo 11.0
自动驾驶开放平台
apollo::perception::lidar::NCutSegmentation类 参考

#include <ncut_segmentation.h>

类 apollo::perception::lidar::NCutSegmentation 继承关系图:
apollo::perception::lidar::NCutSegmentation 的协作图:

Public 成员函数

 NCutSegmentation ()=default
 
virtual ~NCutSegmentation ()
 
bool Init (const LidarDetectorInitOptions &options=LidarDetectorInitOptions()) override
 Init ncut segmentation
 
bool Detect (const LidarDetectorOptions &options, LidarFrame *frame) override
 Detection function of ncut
 
std::string Name () const override
 Get class name
 
void ByPassROIService ()
 Reset roi and ground flag false
 
- Public 成员函数 继承自 apollo::perception::lidar::BaseLidarDetector
 BaseLidarDetector ()=default
 Construct a new Base Lidar Detector object
 
virtual ~BaseLidarDetector ()=default
 Destroy the Base Lidar Detector object
 

详细描述

在文件 ncut_segmentation.h 第 37 行定义.

构造及析构函数说明

◆ NCutSegmentation()

apollo::perception::lidar::NCutSegmentation::NCutSegmentation ( )
default

◆ ~NCutSegmentation()

virtual apollo::perception::lidar::NCutSegmentation::~NCutSegmentation ( )
inlinevirtual

在文件 ncut_segmentation.h 第 40 行定义.

40{};

成员函数说明

◆ ByPassROIService()

void apollo::perception::lidar::NCutSegmentation::ByPassROIService ( )
inline

Reset roi and ground flag false

在文件 ncut_segmentation.h 第 70 行定义.

70 {
71 remove_roi_ = false;
72 remove_ground_ = false;
73 }

◆ Detect()

bool apollo::perception::lidar::NCutSegmentation::Detect ( const LidarDetectorOptions &  options,
LidarFrame *  frame 
)
overridevirtual

Detection function of ncut

参数
options
framelocation to save segment objects
返回
true
false

实现了 apollo::perception::lidar::BaseLidarDetector.

在文件 ncut_segmentation.cc 第 101 行定义.

101 {
102 // check input
103 if (frame == nullptr) {
104 AERROR << "Input null frame ptr.";
105 return false;
106 }
107 if (frame->cloud == nullptr) {
108 AERROR << "Input null frame cloud.";
109 return false;
110 }
111 if (frame->world_cloud == nullptr) {
112 AERROR << "Input null frame world cloud.";
113 return false;
114 }
115 if (frame->cloud->size() == 0) {
116 AERROR << "Input none points.";
117 return false;
118 }
119 if (frame->cloud->size() != frame->world_cloud->size()) {
120 AERROR << "Cloud size and world cloud size not consistent.";
121 return false;
122 }
123
124 // record input cloud and lidar frame
125 original_cloud_ = frame->cloud;
126 original_world_cloud_ = frame->world_cloud;
127 lidar_frame_ref_ = frame;
128
129 std::vector<base::ObjectPtr>* segments = &(frame->segmented_objects);
130 double start_t = omp_get_wtime();
131
132 AINFO << "input point cloud: " << original_cloud_->size() << " points";
133#ifdef DEBUG_NCUT
134 VisualizePointCloud(original_cloud_);
135#endif
136
137 base::PointFCloudPtr cloud_above_ground(new base::PointFCloud);
138 if (remove_ground_) {
139 AINFO << "remove ground";
140 CloudMask mask;
141 mask.Set(original_cloud_->size(), 0);
142 mask.AddIndicesOfIndices(lidar_frame_ref_->roi_indices, lidar_frame_ref_->non_ground_indices, 1);
143 mask.GetValidIndices(&lidar_frame_ref_->secondary_indices);
144 }
145
146 // if used as secondary segmentor, got from cloud directly
147 cloud_above_ground->CopyPointCloud(*lidar_frame_ref_->cloud, lidar_frame_ref_->secondary_indices);
148
149#ifdef DEBUG_NCUT
150 AINFO << "filter ground, elapsed time: " << omp_get_wtime() - start_t << cloud_above_ground->size()
151 << " points left";
152 start_t = omp_get_wtime();
153 VisualizePointCloud(cloud_above_ground);
154#endif
155
156 // .3 filter vehicle
157 base::PointFCloudPtr cloud_after_car_filter = cloud_above_ground;
158 if (filter_vehicle_) {
159 ObstacleFilter(cloud_above_ground, vehicle_filter_cell_size_, false, &cloud_after_car_filter, segments);
160 }
161#ifdef DEBUG_NCUT
162 AINFO << "filter vehicle, elapsed time: " << omp_get_wtime() - start_t
163 << "filter vehicle: " << cloud_after_car_filter->size() << " points left";
164 start_t = omp_get_wtime();
165 VisualizePointCloud(cloud_after_car_filter);
166#endif
167
168 // .4 filter pedestrian
169 base::PointFCloudPtr cloud_after_people_filter = cloud_after_car_filter;
170 if (filter_pedestrian_) {
171 ObstacleFilter(
172 cloud_after_car_filter, pedestrian_filter_cell_size_, true, &cloud_after_people_filter, segments);
173 }
174
175#ifdef DEBUG_NCUT
176 AINFO << "filter pedestrian, elapsed time: " << omp_get_wtime() - start_t;
177 start_t = omp_get_wtime();
178 AINFO << "filter pedestrian: " << cloud_after_people_filter->size() << " points left";
179 VisualizePointCloud(cloud_after_people_filter);
180 AINFO << "after filter car/pedestrian #segments " << segments->size();
181// VisualizeSegments(*segments);
182#endif
183
184 // .5 partition into small regions
185 std::vector<base::PointFCloudPtr> cloud_components;
186 PartitionConnectedComponents(cloud_after_people_filter, partition_cell_size_, &cloud_components);
187
188#ifdef DEBUG_NCUT
189 AINFO << "partition small regions, elapsed time: " << omp_get_wtime() - start_t;
190 start_t = omp_get_wtime();
191 AINFO << "partition " << cloud_components.size() << " components";
192#endif
193
194 std::vector<bool> cloud_outlier_flag(cloud_components.size());
195
196#pragma omp parallel
197 {
198#pragma omp for
199 for (size_t i = 0; i < cloud_components.size(); ++i) {
200 cloud_outlier_flag[i] = IsOutlier(cloud_components[i]);
201 }
202 }
203
204 std::vector<int> cloud_outlier;
205 std::vector<int> cloud_tbd;
206 for (int i = 0; i < static_cast<int>(cloud_components.size()); ++i) {
207 if (cloud_outlier_flag[i]) {
208 cloud_outlier.push_back(i);
209 } else {
210 cloud_tbd.push_back(i);
211 }
212 }
213
214 // .5.1 outlier
215 for (size_t i = 0; i < cloud_outlier.size(); ++i) {
216 base::PointFCloudPtr pc = cloud_components[cloud_outlier[i]];
217 base::ObjectPtr obj(new base::Object);
218 obj->lidar_supplement.cloud = *pc;
219 _outliers->push_back(obj);
220 }
221#ifdef DEBUG_NCUT
222 AINFO << "filter outlier, elapsed time: " << omp_get_wtime() - start_t;
223 start_t = omp_get_wtime();
224#endif
225 // .6 graph cut each
226 std::vector<std::vector<base::PointFCloudPtr>> threads_segment_pcs(num_threads_);
227 std::vector<std::vector<std::string>> threads_segment_labels(num_threads_);
228 std::vector<std::vector<base::PointFCloudPtr>> threads_outlier_pcs(num_threads_);
229 // .6.1 process each component in parallel
230 omp_set_num_threads(num_threads_);
231#pragma omp parallel
232 {
233 int tid = omp_get_thread_num();
234 std::shared_ptr<NCut> my_ncut = _segmentors[tid];
235 std::vector<base::PointFCloudPtr>& my_segment_pcs = threads_segment_pcs[tid];
236 std::vector<std::string>& my_segment_labels = threads_segment_labels[tid];
237 std::vector<base::PointFCloudPtr>& my_outlier_pcs = threads_outlier_pcs[tid];
238
239#pragma omp for schedule(guided)
240 for (size_t i = 0; i < cloud_tbd.size(); ++i) {
241 my_ncut->Segment(cloud_components[cloud_tbd[i]]);
242 ADEBUG << "after segment with num segments" << my_ncut->NumSegments();
243 for (int j = 0; j < my_ncut->NumSegments(); ++j) {
244 base::PointFCloudPtr pc = my_ncut->GetSegmentPointCloud(j);
245 std::string label = my_ncut->GetSegmentLabel(j);
246 if (IsOutlier(pc)) {
247 my_outlier_pcs.push_back(pc);
248 } else {
249 my_segment_pcs.push_back(pc);
250 my_segment_labels.push_back(label);
251 }
252 }
253 }
254 }
255#ifdef DEBUG_NCUT
256 ADEBUG << "parallel normalized cut, elapsed time: " << omp_get_wtime() - start_t;
257 start_t = omp_get_wtime();
258#endif
259 // .6.2 aggregate results
260 std::vector<int> segment_offset(num_threads_, static_cast<int>(segments->size()));
261 for (int i = 1; i < num_threads_; ++i) {
262 segment_offset[i] = segment_offset[i - 1] + static_cast<int>(threads_segment_pcs[i - 1].size());
263 }
264 int new_num_segments
265 = static_cast<int>(threads_segment_pcs[num_threads_ - 1].size()) + segment_offset[num_threads_ - 1];
266 segments->resize(new_num_segments);
267#pragma omp parallel for
268 for (int i = 0; i < num_threads_; ++i) {
269 int offset = segment_offset[i];
270 for (size_t j = 0; j < threads_segment_pcs[i].size(); ++j) {
271 base::ObjectPtr& obj_ptr = (*segments)[offset + j];
272 obj_ptr.reset(new base::Object());
273 obj_ptr->lidar_supplement.cloud = *threads_segment_pcs[i][j];
274
275 if (do_classification_) {
276 obj_ptr->type = Label2Type(threads_segment_labels[i][j]);
277 }
278 }
279 }
280 std::vector<int> outlier_offset(num_threads_, static_cast<int>(_outliers->size()));
281 for (int i = 1; i < num_threads_; ++i) {
282 outlier_offset[i] = outlier_offset[i - 1] + static_cast<int>(threads_outlier_pcs[i - 1].size());
283 }
284 int new_num_outliers
285 = static_cast<int>(threads_outlier_pcs[num_threads_ - 1].size()) + outlier_offset[num_threads_ - 1];
286 _outliers->resize(new_num_outliers);
287#pragma omp parallel for
288 for (int i = 0; i < num_threads_; ++i) {
289 int offset = outlier_offset[i];
290 for (size_t j = 0; j < threads_outlier_pcs[i].size(); ++j) {
291 base::ObjectPtr& obj_ptr = (*_outliers)[offset + j];
292 obj_ptr.reset(new base::Object);
293 obj_ptr->lidar_supplement.cloud = *threads_outlier_pcs[i][j];
294 }
295 }
296 AINFO << "aggregate results, elapsed time: " << omp_get_wtime() - start_t;
297 AINFO << "final #segments " << segments->size();
298 AINFO << "final #outliers " << _outliers->size();
299
300#ifdef DEBUG_NCUT
301 VisualizeSegments(*segments);
302 VisualizeSegments(*_outliers);
303#endif
304
305 return true;
306}
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
AttributePointCloud< PointF > PointFCloud
std::shared_ptr< PointFCloud > PointFCloudPtr
std::shared_ptr< Object > ObjectPtr
Definition object.h:127
std::shared_ptr< base::AttributePointCloud< base::PointF > > cloud
Definition lidar_frame.h:35

◆ Init()

bool apollo::perception::lidar::NCutSegmentation::Init ( const LidarDetectorInitOptions &  options = LidarDetectorInitOptions())
overridevirtual

Init ncut segmentation

参数
options
返回
true
false

实现了 apollo::perception::lidar::BaseLidarDetector.

在文件 ncut_segmentation.cc 第 37 行定义.

37 {
38 std::string param_file = GetConfigFile(options.config_path, options.config_file);
39 AINFO << "-- param_file: " << param_file;
40
41 if (!Configure(param_file)) {
42 AERROR << "failed to load ncut config.";
43 return false;
44 }
45
46 _outliers.reset(new std::vector<ObjectPtr>);
47 if (!_outliers) {
48 AERROR << "Failed to reset outliers.";
49 return false;
50 }
51#pragma omp parallel
52 { num_threads_ = omp_get_num_threads(); }
53
54 AINFO << "number threads " << num_threads_;
55 _segmentors.resize(num_threads_);
56 for (int i = 0; i < num_threads_; ++i) {
57 _segmentors[i].reset(new NCut);
58 if (!(_segmentors[i]->Init(ncut_param_))) {
59 AERROR << "failed to init NormalizedCut " << i << ".";
60 return false;
61 }
62 }
63
64 roi_cloud_ = base::PointFCloudPool::Instance().Get();
65 roi_world_cloud_ = base::PointDCloudPool::Instance().Get();
66
67#ifdef DEBUG_NCUT
68 _viewer = pcl::visualization::PCLVisualizer::Ptr(new pcl::visualization::PCLVisualizer("3D Viewer"));
69 _viewer->setBackgroundColor(0, 0, 0);
70 _viewer->addCoordinateSystem(1.0);
71 _viewer->initCameraParameters();
72 _viewer_count = 0;
73 _rgb_cloud = CPointCloudPtr(new CPointCloud);
74#endif
75
76 AINFO << "NCutSegmentation init success, num_threads: " << num_threads_;
77 return true;
78}
bool Init(const LidarDetectorInitOptions &options=LidarDetectorInitOptions()) override
Init ncut segmentation
pcl::PointCloud< CPoint > CPointCloud
Definition pcl_util.h:33
pcl::PointCloud< CPoint >::Ptr CPointCloudPtr
Definition pcl_util.h:34
std::string GetConfigFile(const std::string &config_path, const std::string &config_file)
Definition util.cc:80

◆ Name()

std::string apollo::perception::lidar::NCutSegmentation::Name ( ) const
inlineoverridevirtual

Get class name

返回
std::string

实现了 apollo::perception::lidar::BaseLidarDetector.

在文件 ncut_segmentation.h 第 63 行定义.

63 {
64 return "NCutSegmentation";
65 }

该类的文档由以下文件生成: