101 {
102
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
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
138 if (remove_ground_) {
139 AINFO <<
"remove ground";
140 CloudMask mask;
141 mask.Set(original_cloud_->size(), 0);
144 }
145
146
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
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
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
182#endif
183
184
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
215 for (size_t i = 0; i < cloud_outlier.size(); ++i) {
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
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
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) {
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
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) {
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) {
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}
AttributePointCloud< PointF > PointFCloud
std::shared_ptr< PointFCloud > PointFCloudPtr
std::shared_ptr< Object > ObjectPtr
base::PointIndices roi_indices
base::PointIndices non_ground_indices
base::PointIndices secondary_indices
std::shared_ptr< base::AttributePointCloud< base::PointF > > cloud