Apollo 11.0
自动驾驶开放平台
spp_seg_cc_2d.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 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 *****************************************************************************/
16#include <algorithm>
17
21
22namespace apollo {
23namespace perception {
24namespace lidar {
25
26void SppCCDetector::SetData(const float* const* prob_map,
27 const float* offset_map, float scale,
28 float objectness_threshold) {
29 prob_map_ = prob_map;
30 offset_map_ = offset_map;
31 scale_ = scale;
32 objectness_threshold_ = objectness_threshold;
33 worker_.Bind(std::bind(&SppCCDetector::CleanNodes, this));
34 worker_.Start();
35}
36
37bool SppCCDetector::BuildNodes(int start_row_index, int end_row_index) {
38 const float* offset_row_ptr = offset_map_ + start_row_index * cols_;
39 const float* offset_col_ptr = offset_map_ + (rows_ + start_row_index) * cols_;
40 const float* prob_map_ptr = prob_map_[0] + start_row_index * cols_;
41 Node* node_ptr = nodes_[0] + start_row_index * cols_;
42 for (int row = start_row_index; row < end_row_index; ++row) {
43 for (int col = 0; col < cols_; ++col) {
44 node_ptr->set_is_object(*prob_map_ptr++ >= objectness_threshold_);
45 int center_row = static_cast<int>(*offset_row_ptr++ * scale_ +
46 static_cast<float>(row) + 0.5f);
47 int center_col = static_cast<int>(*offset_col_ptr++ * scale_ +
48 static_cast<float>(col) + 0.5f);
49 center_row = std::max(0, std::min(rows_ - 1, center_row));
50 center_col = std::max(0, std::min(cols_ - 1, center_col));
51 (node_ptr++)->center_node = center_row * cols_ + center_col;
52 }
53 }
54 return true;
55}
56
57bool SppCCDetector::CleanNodes() {
58 memset(nodes_[0], 0, sizeof(Node) * rows_ * cols_);
59 uint32_t node_idx = 0;
60 for (int row = 0; row < rows_; ++row) {
61 for (int col = 0; col < cols_; ++col) {
62 nodes_[row][col].parent = node_idx++;
63 }
64 }
65 return true;
66}
67
69 Timer timer;
70 if (!first_process_) {
71 worker_.Join(); // sync for cleaning nodes
72 }
73 first_process_ = false;
74 BuildNodes(0, rows_);
75 double init_time = timer.toc(true);
76
77 double sync_time = timer.toc(true);
78
79 TraverseNodes();
80 double traverse_time = timer.toc(true);
81
82 UnionNodes();
83 double union_time = timer.toc(true);
84
85 size_t num = ToLabelMap(labels);
86 worker_.WakeUp(); // for next use
87 double collect_time = timer.toc(true);
88
89 AINFO << "SppSegCC2D: init: " << init_time << "\tsync: " << sync_time
90 << "\ttraverse: " << traverse_time << "\tunion: " << union_time
91 << "\tcollect: " << collect_time << "\t#obj: " << num;
92
93 return num;
94}
95
96void SppCCDetector::TraverseNodes() {
97 for (int row = 0; row < rows_; row++) {
98 for (int col = 0; col < cols_; col++) {
99 Node& node = nodes_[row][col];
100 if (node.is_object() && node.get_traversed() == 0) {
101 Traverse(&node);
102 }
103 }
104 }
105}
106
107void SppCCDetector::UnionNodes() {
108 for (int row = 0; row < rows_; ++row) {
109 for (int col = 0; col < cols_; ++col) {
110 Node* node = &nodes_[row][col];
111 if (!node->is_center()) {
112 continue;
113 }
114 Node* node_neighbor = nullptr;
115 // right
116 if (col < cols_ - 1) {
117 node_neighbor = &nodes_[row][col + 1];
118 if (node_neighbor->is_center()) {
119 DisjointSetUnion(node, node_neighbor);
120 }
121 }
122 // down
123 if (row < rows_ - 1) {
124 node_neighbor = &nodes_[row + 1][col];
125 if (node_neighbor->is_center()) {
126 DisjointSetUnion(node, node_neighbor);
127 }
128 }
129 // right down
130 if (row < rows_ - 1 && col < cols_ - 1) {
131 node_neighbor = &nodes_[row + 1][col + 1];
132 if (node_neighbor->is_center()) {
133 DisjointSetUnion(node, node_neighbor);
134 }
135 }
136 // left down
137 if (row < rows_ - 1 && col > 0) {
138 node_neighbor = &nodes_[row + 1][col - 1];
139 if (node_neighbor->is_center()) {
140 DisjointSetUnion(node, node_neighbor);
141 }
142 }
143 }
144 }
145}
146
147size_t SppCCDetector::ToLabelMap(SppLabelImage* labels) {
148 uint16_t id = 0;
149 uint32_t pixel_id = 0;
150 labels->ResetClusters(kDefaultReserveSize);
151 for (int row = 0; row < rows_; ++row) {
152 for (int col = 0; col < cols_; ++col, ++pixel_id) {
153 Node* node = &nodes_[row][col];
154 if (!node->is_object()) {
155 (*labels)[row][col] = 0;
156 continue;
157 }
158 Node* root = DisjointSetFind(node);
159 // note label in label image started from 1,
160 // zero is reserved from non-object
161 if (!root->id) {
162 root->id = ++id;
163 }
164 (*labels)[row][col] = root->id;
165 labels->AddPixelSample(root->id - 1, pixel_id);
166 }
167 }
168 labels->ResizeClusters(id);
169 return id;
170}
171
172void SppCCDetector::Traverse(SppCCDetector::Node* x) {
173 std::vector<SppCCDetector::Node*> p;
174 p.clear();
175 while (x->get_traversed() == 0) {
176 p.push_back(x);
177 x->set_traversed(2);
178 x = nodes_[0] + x->center_node;
179 }
180 if (x->get_traversed() == 2) {
181 for (int i = static_cast<int>(p.size()) - 1; i >= 0 && p[i] != x; i--) {
182 p[i]->set_is_center(true);
183 }
184 x->set_is_center(true);
185 }
186 for (size_t i = 0; i < p.size(); i++) {
187 Node* y = p[i];
188 y->set_traversed(1);
189 y->parent = x->parent;
190 }
191}
192
193SppCCDetector::Node* SppCCDetector::DisjointSetFindLoop(Node* x) {
194 Node* root = x;
195 while (nodes_[0] + root->parent != root) {
196 root = nodes_[0] + root->parent;
197 }
198 Node* w = x;
199 while (nodes_[0] + w->parent != w) {
200 Node* temp = nodes_[0] + w->parent;
201 w->parent = root->parent;
202 w = temp;
203 }
204 return root;
205}
206
207SppCCDetector::Node* SppCCDetector::DisjointSetFind(Node* x) {
208 Node* y = nodes_[0] + x->parent;
209 if (y == x || nodes_[0] + y->parent == y) {
210 return y;
211 }
212 Node* root = DisjointSetFindLoop(nodes_[0] + y->parent);
213 x->parent = root->parent;
214 y->parent = root->parent;
215 return root;
216}
217
218void SppCCDetector::DisjointSetUnion(Node* x, Node* y) {
219 x = DisjointSetFind(x);
220 y = DisjointSetFind(y);
221 if (x == y) {
222 return;
223 }
224 uint16_t x_node_rank = x->get_node_rank();
225 uint16_t y_node_rank = y->get_node_rank();
226 if (x_node_rank < y_node_rank) {
227 x->parent = y->parent;
228 } else if (y_node_rank < x_node_rank) {
229 y->parent = x->parent;
230 } else {
231 y->parent = x->parent;
232 x->set_node_rank(static_cast<uint16_t>(x_node_rank + 1));
233 }
234}
235
236} // namespace lidar
237} // namespace perception
238} // namespace apollo
Definition node.h:31
void Bind(const std::function< bool()> &func)
void SetData(const float *const *prob_map, const float *offset_map, float scale, float objectness_threshold)
size_t Detect(SppLabelImage *labels)
double toc(bool reset=false)
Definition lidar_timer.h:28
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37