Apollo 10.0
自动驾驶开放平台
postprocess.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2023 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
17
18#include "cyber/common/log.h"
20
21namespace apollo {
22namespace perception {
23namespace camera {
24
26 const NormalizedBBox &bbox2,
27 NormalizedBBox *intersect_bbox) {
28 if (bbox2.xmin > bbox1.xmax || bbox2.xmax < bbox1.xmin ||
29 bbox2.ymin > bbox1.ymax || bbox2.ymax < bbox1.ymin) {
30 // Return [0, 0, 0, 0] if there is no intersection.
31 intersect_bbox->xmin = 0;
32 intersect_bbox->ymin = 0;
33 intersect_bbox->xmax = 0;
34 intersect_bbox->ymax = 0;
35 } else {
36 intersect_bbox->xmin = std::max(bbox1.xmin, bbox2.xmin);
37 intersect_bbox->ymin = std::max(bbox1.ymin, bbox2.ymin);
38 intersect_bbox->xmax = std::min(bbox1.xmax, bbox2.xmax);
39 intersect_bbox->ymax = std::min(bbox1.ymax, bbox2.ymax);
40 }
41}
42
43float get_bbox_size(const NormalizedBBox &bbox) {
44 if (bbox.xmax < bbox.xmin || bbox.ymax < bbox.ymin) {
45 // If bbox is invalid (e.g. xmax < xmin or ymax < ymin), return 0.
46 return 0;
47 } else {
48 if (bbox.size >= 0) {
49 return bbox.size;
50 } else {
51 float width = bbox.xmax - bbox.xmin;
52 float height = bbox.ymax - bbox.ymin;
53 return width * height;
54 }
55 }
56}
57
59 const NormalizedBBox &bbox2) {
60 NormalizedBBox intersect_bbox;
61 get_intersect_bbox(bbox1, bbox2, &intersect_bbox);
62 float intersect_width = 0.f;
63 float intersect_height = 0.f;
64 intersect_width = intersect_bbox.xmax - intersect_bbox.xmin;
65 intersect_height = intersect_bbox.ymax - intersect_bbox.ymin;
66
67 if (intersect_width > 0 && intersect_height > 0) {
68 float intersect_size = intersect_width * intersect_height;
69 float bbox1_size = get_bbox_size(bbox1);
70 float bbox2_size = get_bbox_size(bbox2);
71 return intersect_size / (bbox1_size + bbox2_size - intersect_size);
72 } else {
73 return 0.;
74 }
75}
76
77void get_max_score_index(const std::vector<float> &scores,
78 const float threshold, const int top_k,
79 std::vector<std::pair<float, int>> *score_index_vec) {
80 // Generate index score pairs.
81 for (int i = 0; i < static_cast<int>(scores.size()); ++i) {
82 if (scores[i] > threshold) {
83 score_index_vec->push_back(std::make_pair(scores[i], i));
84 }
85 }
86
87 // Sort the score pair according to the scores in descending order
88 std::stable_sort(score_index_vec->begin(), score_index_vec->end(),
89 sort_score_pair_descend<int>);
90
91 // Keep top_k scores if needed.
92 if (top_k > -1 && top_k < static_cast<int>(score_index_vec->size())) {
93 score_index_vec->resize(top_k);
94 }
95}
96
97void apply_softnms_fast(const std::vector<NormalizedBBox> &bboxes,
98 std::vector<float> *scores, const float score_threshold,
99 const float nms_threshold, const int top_k,
100 std::vector<int> *indices, bool is_linear,
101 const float sigma) {
102 // Sanity check.
103 CHECK_EQ(bboxes.size(), scores->size())
104 << "bboxes and scores have different size.";
105
106 // Get top_k scores (with corresponding indices).
107 std::vector<std::pair<float, int>> score_index_vec;
108 get_max_score_index(*scores, score_threshold, top_k, &score_index_vec);
109
110 // Do nms.
111 indices->clear();
112 while (!score_index_vec.empty()) {
113 auto best_it =
114 max_element(std::begin(score_index_vec), std::end(score_index_vec));
115 const int best_idx = (*best_it).second;
116 score_index_vec.erase(best_it);
117 const NormalizedBBox &best_bbox = bboxes[best_idx];
118 indices->push_back(best_idx);
119 for (std::vector<std::pair<float, int>>::iterator it =
120 score_index_vec.begin();
121 it != score_index_vec.end();) {
122 int cur_idx = it->second;
123 const NormalizedBBox &cur_bbox = bboxes[cur_idx];
124
125 float cur_overlap = 0.;
126 cur_overlap = get_jaccard_overlap(best_bbox, cur_bbox);
127 if (is_linear) {
128 (*scores)[cur_idx] *= static_cast<float>((1.0 - cur_overlap));
129 } else {
130 (*scores)[cur_idx] *=
131 static_cast<float>(exp(-1.0 * pow(cur_overlap, 2) / sigma));
132 }
133 ++it;
134 }
135 }
136}
137
138void apply_boxvoting_fast(std::vector<NormalizedBBox> *bboxes,
139 std::vector<float> *scores,
140 const float conf_threshold, const float nms_threshold,
141 const float sigma, std::vector<int> *indices) {
142 if (bboxes->size() == 0) {
143 return;
144 }
145 indices->clear();
146 for (int i = 0; i < static_cast<int>(bboxes->size()); i++) {
147 (*bboxes)[i].mask = false;
148 if ((*scores)[i] > conf_threshold) {
149 indices->push_back(i);
150 }
151 }
152 for (int count = 0; count < static_cast<int>(indices->size()); count++) {
153 int max_box_idx = 0;
154
155 for (int i = 1; i < static_cast<int>(indices->size()); i++) {
156 int idx = indices->at(i);
157 if ((*bboxes)[idx].mask) {
158 continue;
159 }
160 if ((*scores)[idx] > (*scores)[max_box_idx]) {
161 max_box_idx = idx;
162 }
163 }
164
165 NormalizedBBox &best_bbox = (*bboxes)[max_box_idx];
166 best_bbox.score = (*scores)[max_box_idx];
167 best_bbox.mask = true;
168 float s_vt = (*scores)[max_box_idx];
169 float x1_vt = best_bbox.xmin * s_vt;
170 float x2_vt = best_bbox.xmax * s_vt;
171 float y1_vt = best_bbox.ymin * s_vt;
172 float y2_vt = best_bbox.ymax * s_vt;
173 for (int i = 0; i < static_cast<int>(indices->size()); i++) {
174 int sub_it = indices->at(i);
175 if ((*bboxes)[sub_it].mask) {
176 continue;
177 }
178 float cur_overlap = 0.;
179 cur_overlap = get_jaccard_overlap(best_bbox, (*bboxes)[sub_it]);
180 if (sigma == 0) {
181 (*bboxes)[sub_it].mask = true;
182 } else {
183 (*scores)[sub_it] *=
184 static_cast<float>(exp(-1.0 * pow(cur_overlap, 2) / sigma));
185 }
186 (*bboxes)[sub_it].score = (*scores)[sub_it];
187
188 // Remove it if necessary
189 if (cur_overlap > nms_threshold) {
190 float s_vt_cur = (*bboxes)[sub_it].score;
191 s_vt += s_vt_cur;
192 x1_vt += (*bboxes)[sub_it].xmin * s_vt_cur;
193 x2_vt += (*bboxes)[sub_it].xmax * s_vt_cur;
194 y1_vt += (*bboxes)[sub_it].ymin * s_vt_cur;
195 y2_vt += (*bboxes)[sub_it].ymax * s_vt_cur;
196 }
197 }
198 if (s_vt > 0.0001) {
199 (*bboxes)[max_box_idx].xmin = x1_vt / s_vt;
200 (*bboxes)[max_box_idx].xmax = x2_vt / s_vt;
201 (*bboxes)[max_box_idx].ymin = y1_vt / s_vt;
202 (*bboxes)[max_box_idx].ymax = y2_vt / s_vt;
203 }
204 }
205}
206
207void apply_nms_fast(const std::vector<NormalizedBBox> &bboxes,
208 const std::vector<float> &scores,
209 const float score_threshold, const float nms_threshold,
210 const float eta, const int top_k,
211 std::vector<int> *indices) {
212 // Sanity check.
213 CHECK_EQ(bboxes.size(), scores.size())
214 << "bboxes and scores have different size.";
215
216 // Get top_k scores (with corresponding indices).
217 std::vector<std::pair<float, int>> score_index_vec;
218 get_max_score_index(scores, score_threshold, top_k, &score_index_vec);
219
220 // Do nms.
221 float adaptive_threshold = nms_threshold;
222 indices->clear();
223 while (!score_index_vec.empty()) {
224 const int idx = score_index_vec.front().second;
225 bool keep = true;
226 for (int k = 0; k < static_cast<int>(indices->size()); ++k) {
227 if (keep) {
228 const int kept_idx = (*indices)[k];
229 float overlap = get_jaccard_overlap(bboxes[idx], bboxes[kept_idx]);
230 keep = overlap <= adaptive_threshold;
231 } else {
232 break;
233 }
234 }
235 if (keep) {
236 indices->push_back(idx);
237 }
238 score_index_vec.erase(score_index_vec.begin());
239 if (keep && eta < 1 && adaptive_threshold > 0.5) {
240 adaptive_threshold *= eta;
241 }
242 }
243}
244
245void filter_bbox(const MinDims &min_dims,
246 std::vector<base::ObjectPtr> *objects) {
247 int valid_obj_idx = 0;
248 int total_obj_idx = 0;
249 while (total_obj_idx < static_cast<int>(objects->size())) {
250 const auto &obj = (*objects)[total_obj_idx];
251 if ((obj->camera_supplement.box.ymax - obj->camera_supplement.box.ymin) >=
252 min_dims.min_2d_height &&
253 (min_dims.min_3d_height <= 0 ||
254 obj->size[2] >= min_dims.min_3d_height) &&
255 (min_dims.min_3d_width <= 0 || obj->size[1] >= min_dims.min_3d_width) &&
256 (min_dims.min_3d_length <= 0 ||
257 obj->size[0] >= min_dims.min_3d_length)) {
258 (*objects)[valid_obj_idx] = (*objects)[total_obj_idx];
259 ++valid_obj_idx;
260 }
261 ++total_obj_idx;
262 }
263 AINFO << valid_obj_idx << " of " << total_obj_idx << " obstacles kept";
264 objects->resize(valid_obj_idx);
265 AINFO << "Number of detected obstacles: " << objects->size();
266}
267void recover_bbox(int roi_w, int roi_h, int offset_y,
268 std::vector<base::ObjectPtr> *objects) {
269 for (auto &obj : *objects) {
270 float xmin = obj->camera_supplement.box.xmin;
271 float ymin = obj->camera_supplement.box.ymin;
272 float xmax = obj->camera_supplement.box.xmax;
273 float ymax = obj->camera_supplement.box.ymax;
274 int x = static_cast<int>(xmin * static_cast<float>(roi_w));
275 int w = static_cast<int>((xmax - xmin) * static_cast<float>(roi_w));
276 int y = static_cast<int>(ymin * static_cast<float>(roi_h)) + offset_y;
277 int h = static_cast<int>((ymax - ymin) * static_cast<float>(roi_h));
278 base::RectF rect_det(static_cast<float>(x), static_cast<float>(y),
279 static_cast<float>(w), static_cast<float>(h));
280 base::RectF rect_img(0, 0, static_cast<float>(roi_w),
281 static_cast<float>(roi_h + offset_y));
282 base::RectF rect = rect_det & rect_img;
283 obj->camera_supplement.box = rect;
284
285 double eps = 1e-2;
286
287 // Truncation assignment based on bbox positions
288 if ((ymin < eps) || (ymax >= 1.0 - eps)) {
289 obj->camera_supplement.truncated_vertical = 0.5;
290 } else {
291 obj->camera_supplement.truncated_vertical = 0.0;
292 }
293 if ((xmin < eps) || (xmax >= 1.0 - eps)) {
294 obj->camera_supplement.truncated_horizontal = 0.5;
295 } else {
296 obj->camera_supplement.truncated_horizontal = 0.0;
297 }
298
299 obj->camera_supplement.front_box.xmin *= static_cast<float>(roi_w);
300 obj->camera_supplement.front_box.ymin *= static_cast<float>(roi_h);
301 obj->camera_supplement.front_box.xmax *= static_cast<float>(roi_w);
302 obj->camera_supplement.front_box.ymax *= static_cast<float>(roi_h);
303
304 obj->camera_supplement.back_box.xmin *= static_cast<float>(roi_w);
305 obj->camera_supplement.back_box.ymin *= static_cast<float>(roi_h);
306 obj->camera_supplement.back_box.xmax *= static_cast<float>(roi_w);
307 obj->camera_supplement.back_box.ymax *= static_cast<float>(roi_h);
308
309 obj->camera_supplement.front_box.ymin += static_cast<float>(offset_y);
310 obj->camera_supplement.front_box.ymax += static_cast<float>(offset_y);
311 obj->camera_supplement.back_box.ymin += static_cast<float>(offset_y);
312 obj->camera_supplement.back_box.ymax += static_cast<float>(offset_y);
313 }
314}
315
316void fill_base(base::ObjectPtr obj, const float *bbox) {
317 obj->camera_supplement.box.xmin = bbox[0];
318 obj->camera_supplement.box.ymin = bbox[1];
319 obj->camera_supplement.box.xmax = bbox[2];
320 obj->camera_supplement.box.ymax = bbox[3];
321}
322
323void fill_bbox3d(bool with_box3d, base::ObjectPtr obj, const float *bbox) {
324 if (with_box3d) {
325 obj->camera_supplement.alpha = bbox[0];
326 obj->size[2] = bbox[1];
327 obj->size[1] = bbox[2];
328 obj->size[0] = bbox[3];
329 }
330}
331
332void fill_frbox(bool with_frbox, base::ObjectPtr obj, const float *bbox) {
333 if (with_frbox) {
334 obj->camera_supplement.front_box.xmin = bbox[0];
335 obj->camera_supplement.front_box.ymin = bbox[1];
336 obj->camera_supplement.front_box.xmax = bbox[2];
337 obj->camera_supplement.front_box.ymax = bbox[3];
338
339 obj->camera_supplement.back_box.xmin = bbox[4];
340 obj->camera_supplement.back_box.ymin = bbox[5];
341 obj->camera_supplement.back_box.xmax = bbox[6];
342 obj->camera_supplement.back_box.ymax = bbox[7];
343 }
344}
345
346void fill_lights(bool with_lights, base::ObjectPtr obj, const float *bbox) {
347 if (with_lights) {
348 obj->car_light.brake_visible = bbox[0];
349 obj->car_light.brake_switch_on = bbox[1];
350 obj->car_light.left_turn_visible = bbox[2];
351 obj->car_light.left_turn_switch_on = bbox[3];
352 obj->car_light.right_turn_visible = bbox[4];
353 obj->car_light.right_turn_switch_on = bbox[5];
354 }
355}
356
357void fill_ratios(bool with_ratios, base::ObjectPtr obj, const float *bbox) {
358 if (with_ratios) {
359 // visible ratios of face a/b/c/d
360 obj->camera_supplement.visible_ratios[0] = bbox[0];
361 obj->camera_supplement.visible_ratios[1] = bbox[1];
362 obj->camera_supplement.visible_ratios[2] = bbox[2];
363 obj->camera_supplement.visible_ratios[3] = bbox[3];
364
365 // cut off on width and length (3D)
366 obj->camera_supplement.cut_off_ratios[0] = bbox[4];
367 obj->camera_supplement.cut_off_ratios[1] = bbox[5];
368 // cut off on left and right side (2D)
369 obj->camera_supplement.cut_off_ratios[2] = bbox[6];
370 obj->camera_supplement.cut_off_ratios[3] = bbox[7];
371 }
372}
373
374void fill_area_id(bool with_flag, base::ObjectPtr obj, const float *data) {
375 if (with_flag) {
376 obj->camera_supplement.area_id = static_cast<int>(data[0]);
377 }
378}
379
380int get_area_id(float visible_ratios[4]) {
381 int area_id = 0;
382 int max_face = 0;
383 for (int i = 1; i < 4; i++) {
384 if (visible_ratios[i] > visible_ratios[max_face]) {
385 max_face = i;
386 }
387 }
388 int left_face = (max_face + 1) % 4;
389 int right_face = (max_face + 3) % 4;
390 const float eps = 1e-3f;
391 float max_ratio = visible_ratios[max_face];
392 float left_ratio = visible_ratios[left_face];
393 float right_ratio = visible_ratios[right_face];
394 memset(visible_ratios, 0, 4 * sizeof(visible_ratios[0]));
395 if (left_ratio < eps && right_ratio < eps) {
396 area_id = (max_face * 2 + 1);
397 visible_ratios[max_face] = 1.f;
398 } else if (left_ratio > right_ratio) {
399 area_id = (max_face * 2 + 2);
400 auto &&sum_ratio = left_ratio + max_ratio;
401 visible_ratios[max_face] = max_ratio / sum_ratio;
402 visible_ratios[left_face] = left_ratio / sum_ratio;
403 } else {
404 area_id = (max_face * 2);
405 if (area_id == 0) {
406 area_id = 8;
407 }
408 auto &&sum_ratio = right_ratio + max_ratio;
409 visible_ratios[max_face] = max_ratio / sum_ratio;
410 visible_ratios[right_face] = right_ratio / sum_ratio;
411 }
412 return area_id;
413}
414
415const float *get_cpu_data(bool flag, const base::Blob<float> &blob) {
416 return flag ? blob.cpu_data() : nullptr;
417}
418
419void get_objects_cpu(const YoloBlobs &yolo_blobs, const cudaStream_t &stream,
420 const std::vector<base::ObjectSubType> &types,
421 const NMSParam &nms, const yolo::ModelParam &model_param,
422 float light_vis_conf_threshold,
423 float light_swt_conf_threshold,
424 base::Blob<bool> *overlapped, base::Blob<int> *idx_sm,
425 std::vector<base::ObjectPtr> *objects) {
426 std::map<base::ObjectSubType, std::vector<int>> indices;
427 std::map<base::ObjectSubType, std::vector<float>> conf_scores;
428 int num_kept = 0;
429 int num_classes = types.size();
430 num_kept = get_objects_gpu(yolo_blobs, stream, types, nms, model_param,
431 light_vis_conf_threshold, light_swt_conf_threshold,
432 overlapped, idx_sm, indices, conf_scores);
433 objects->clear();
434
435 if (num_kept == 0) {
436 return;
437 }
438
439 objects->reserve(num_kept + static_cast<int>(objects->size()));
440 const float *cpu_box_data = yolo_blobs.res_box_blob->cpu_data();
441
442 ObjectMaintainer maintainer;
443 for (auto it = indices.begin(); it != indices.end(); ++it) {
444 base::ObjectSubType label = it->first;
445 if (conf_scores.find(label) == conf_scores.end()) {
446 // Something bad happened if there are no predictions for current label.
447 continue;
448 }
449 const std::vector<float> &scores = conf_scores.find(label)->second;
450 std::vector<int> &indice = it->second;
451 for (size_t j = 0; j < indice.size(); ++j) {
452 int idx = indice[j];
453 const float *bbox = cpu_box_data + idx * kBoxBlockSize;
454 if (scores[idx] < model_param.confidence_threshold()) {
455 continue;
456 }
457
458 base::ObjectPtr obj = nullptr;
459 obj.reset(new base::Object);
460 obj->type = base::kSubType2TypeMap.at(label);
461 obj->sub_type = label;
462 obj->type_probs.assign(
463 static_cast<int>(base::ObjectType::MAX_OBJECT_TYPE), 0);
464 obj->sub_type_probs.assign(
465 static_cast<int>(base::ObjectSubType::MAX_OBJECT_TYPE), 0);
466 float total = 1e-5;
467 for (int k = 0; k < num_classes; ++k) {
468 auto &vis_type_k = types[k];
469 auto &obj_type_k = base::kSubType2TypeMap.at(vis_type_k);
470 auto &conf_score = conf_scores[vis_type_k][idx];
471 obj->type_probs[static_cast<int>(obj_type_k)] += conf_score;
472 obj->sub_type_probs[static_cast<int>(vis_type_k)] = conf_score;
473 total += conf_score;
474 }
475 obj->confidence = obj->type_probs[static_cast<int>(obj->type)];
476 for (size_t k = 0; k < obj->type_probs.size(); ++k) {
477 obj->type_probs[k] /= total;
478 }
479 fill_base(obj, bbox);
480 fill_bbox3d(model_param.with_box3d(), obj, bbox + 4);
481 fill_frbox(model_param.with_frbox(), obj, bbox + 8);
482 fill_lights(model_param.with_lights(), obj, bbox + 16);
483 fill_ratios(model_param.with_ratios(), obj, bbox + 22);
484 fill_area_id(model_param.num_areas() > 0, obj, bbox + 30);
485
486 // todo: maintainer just found?
487 if (maintainer.Add(idx, obj)) {
488 objects->push_back(obj);
489 }
490 }
491 }
492}
493
494} // namespace camera
495} // namespace perception
496} // namespace apollo
A wrapper around SyncedMemory holders serving as the basic computational unit for images,...
Definition blob.h:88
const Dtype * cpu_data() const
Definition blob.cc:137
bool Add(int idx, base::ObjectPtr obj)
Maintain a collection of objects that can be added based on the index.
#define AINFO
Definition log.h:42
Rect< float > RectF
Definition box.h:160
const std::map< ObjectSubType, ObjectType > kSubType2TypeMap
ObjectSubType mapping
std::shared_ptr< Object > ObjectPtr
Definition object.h:127
void get_max_score_index(const std::vector< float > &scores, const float threshold, const int top_k, std::vector< std::pair< float, int > > *score_index_vec)
Get the max score index object
void apply_softnms_fast(const std::vector< NormalizedBBox > &bboxes, std::vector< float > *scores, const float score_threshold, const float nms_threshold, const int top_k, std::vector< int > *indices, bool is_linear, const float sigma)
softnms for objects
void recover_bbox(int roi_w, int roi_h, int offset_y, std::vector< base::ObjectPtr > *objects)
recover detect bbox result to raw image
void apply_boxvoting_fast(std::vector< NormalizedBBox > *bboxes, std::vector< float > *scores, const float conf_threshold, const float nms_threshold, const float sigma, std::vector< int > *indices)
filter target detection results based on given thresholds and parameters.
const float * get_cpu_data(bool flag, const base::Blob< float > &blob)
float get_bbox_size(const NormalizedBBox &bbox)
int get_objects_gpu(const YoloBlobs &yolo_blobs, const cudaStream_t &stream, const std::vector< base::ObjectSubType > &types, const NMSParam &nms, const yolo::ModelParam &model_param, float light_vis_conf_threshold, float light_swt_conf_threshold, base::Blob< bool > *overlapped, base::Blob< int > *idx_sm, const std::map< base::ObjectSubType, std::vector< int > > &indices, const std::map< base::ObjectSubType, std::vector< float > > &conf_scores)
Get the objects gpu object
void fill_base(base::ObjectPtr obj, const float *bbox)
add bbox value to object
void fill_ratios(bool with_ratios, base::ObjectPtr obj, const float *bbox)
add ratio value to object
void fill_frbox(bool with_frbox, base::ObjectPtr obj, const float *bbox)
add car front and backward bbox value to object
int get_area_id(float visible_ratios[4])
calculate the area id based on the visible ratios
void get_intersect_bbox(const NormalizedBBox &bbox1, const NormalizedBBox &bbox2, NormalizedBBox *intersect_bbox)
Get the intersect bbox object
void fill_area_id(bool with_flag, base::ObjectPtr obj, const float *data)
add area id value to object
float get_jaccard_overlap(const NormalizedBBox &bbox1, const NormalizedBBox &bbox2)
Get the jaccard overlap object
void get_objects_cpu(const YoloBlobs &yolo_blobs, const cudaStream_t &stream, const std::vector< base::ObjectSubType > &types, const NMSParam &nms, const yolo::ModelParam &model_param, float light_vis_conf_threshold, float light_swt_conf_threshold, base::Blob< bool > *overlapped, base::Blob< int > *idx_sm, std::vector< base::ObjectPtr > *objects)
Get the objects cpu object
void fill_bbox3d(bool with_box3d, base::ObjectPtr obj, const float *bbox)
add alpha h w l to object
void filter_bbox(const MinDims &min_dims, std::vector< base::ObjectPtr > *objects)
filter out the objects in the object array based on the given minimum dimension conditions and retain...
void fill_lights(bool with_lights, base::ObjectPtr obj, const float *bbox)
add car lights value to object
void apply_nms_fast(const std::vector< NormalizedBBox > &bboxes, const std::vector< float > &scores, const float score_threshold, const float nms_threshold, const float eta, const int top_k, std::vector< int > *indices)
nms for objects
class register implement
Definition arena_queue.h:37
std::shared_ptr< base::Blob< float > > res_box_blob