Apollo 10.0
自动驾驶开放平台
common_functions.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 *****************************************************************************/
17
18#include <algorithm>
19
20namespace apollo {
21namespace perception {
22namespace camera {
23
25// add a new element, which is a subset by itself;
27 int cur_size = static_cast<int>(disjoint_array_.size());
28 disjoint_array_.push_back(cur_size);
29 ++subset_num_;
30 return cur_size;
31}
32
34 if (disjoint_array_[x] == x) {
35 return x;
36 }
37
38 int y = x;
39 while (y != disjoint_array_[y]) {
40 y = disjoint_array_[y];
41 }
42 while (true) {
43 const int z = disjoint_array_[x];
44 if (z == x) {
45 break;
46 }
47 disjoint_array_[x] = y;
48 x = z;
49 }
50 return y;
51}
52
53// point the x and y to smaller root of the two
54void DisjointSet::Unite(int x, int y) {
55 if (x == y) {
56 return;
57 }
58 int x_root = Find(x);
59 int y_root = Find(y);
60 if (x_root == y_root) {
61 return;
62 } else if (x_root < y_root) {
63 disjoint_array_[y_root] = x_root;
64 } else {
65 disjoint_array_[x_root] = y_root;
66 }
67 --subset_num_;
68}
69
71void ConnectedComponent::AddPixel(int x, int y) {
72 base::Point2DI point;
73 point.x = x;
74 point.y = y;
75 pixels_.push_back(point);
76 bbox_.xmin = std::min(x, bbox_.xmin);
77 bbox_.xmax = std::max(x, bbox_.xmax);
78 bbox_.ymin = std::min(y, bbox_.ymin);
79 bbox_.ymax = std::max(y, bbox_.ymax);
80 pixel_count_++;
81}
82
83bool FindCC(const std::vector<unsigned char>& src, int width, int height,
84 const base::RectI& roi, std::vector<ConnectedComponent>* cc) {
85 if (src.empty()) {
86 AERROR << "input image is empty";
87 return false;
88 }
89
90 cc->clear();
91 int x_min = roi.x;
92 int y_min = roi.y;
93 int x_max = x_min + roi.width - 1;
94 int y_max = y_min + roi.height - 1;
95 if (x_min < 0) {
96 AERROR << "x_min is less than zero: " << x_min;
97 return false;
98 }
99 if (y_min < 0) {
100 AERROR << "y_min is less than zero: " << y_min;
101 return false;
102 }
103 if (x_max >= width) {
104 AERROR << "x_max is larger than image width: " << x_max << "|" << width;
105 return false;
106 }
107 if (y_max >= height) {
108 AERROR << "y_max is larger than image height: " << y_max << "|" << height;
109 return false;
110 }
111 if (roi.width <= 1 && roi.height <= 1) {
112 AERROR << "too small roi range";
113 return false;
114 }
115
116 size_t total_pix = static_cast<size_t>(roi.width * roi.height);
117 std::vector<int> frame_label(total_pix);
118 DisjointSet labels(total_pix);
119 std::vector<int> root_map;
120 root_map.reserve(total_pix);
121
122 int x = 0;
123 int y = 0;
124 int left_val = 0;
125 int up_val = 0;
126 int cur_idx = 0;
127 int left_idx = 0;
128 int up_idx = 0;
129
130 // first loop logic
131 for (y = y_min; y <= y_max; y++) {
132 int row_start = y * width;
133 for (x = x_min; x <= x_max; x++, cur_idx++) {
134 left_idx = cur_idx - 1;
135 up_idx = cur_idx - width;
136
137 if (x == x_min) {
138 left_val = 0;
139 } else {
140 left_val = src[row_start + x - 1];
141 }
142
143 if (y == y_min) {
144 up_val = 0;
145 } else {
146 up_val = src[row_start - width + x];
147 }
148
149 if (src[row_start + x] > 0) {
150 if (left_val == 0 && up_val == 0) {
151 // current pixel is foreground and has no connected neighbors
152 frame_label[cur_idx] = labels.Add();
153 root_map.push_back(-1);
154 } else if (left_val != 0 && up_val == 0) {
155 // current pixel is foreground and has left neighbor connected
156 frame_label[cur_idx] = frame_label[left_idx];
157 } else if (left_val == 0 && up_val != 0) {
158 // current pixel is foreground and has up neighbor connect
159 frame_label[cur_idx] = frame_label[up_idx];
160 } else {
161 // current pixel is foreground
162 // and is connected to left and up neighbors
163 frame_label[cur_idx] = (frame_label[left_idx] > frame_label[up_idx])
164 ? frame_label[up_idx]
165 : frame_label[left_idx];
166 labels.Unite(frame_label[left_idx], frame_label[up_idx]);
167 }
168 } else {
169 frame_label[cur_idx] = -1;
170 }
171 } // end for x
172 } // end for y
173 AINFO << "subset number = " << labels.Size();
174
175 // second loop logic
176 cur_idx = 0;
177 int curt_label = 0;
178 int cc_count = 0;
179 for (y = y_min; y <= y_max; y++) {
180 for (x = x_min; x <= x_max; x++, cur_idx++) {
181 curt_label = frame_label[cur_idx];
182 if (curt_label >= 0 && curt_label < static_cast<int>(labels.Num())) {
183 curt_label = labels.Find(curt_label);
184 if (curt_label >= static_cast<int>(root_map.size())) {
185 AERROR << "curt_label should be smaller than root_map.size() "
186 << curt_label << " vs. " << root_map.size();
187 return false;
188 }
189 if (root_map.at(curt_label) != -1) {
190 (*cc)[root_map.at(curt_label)].AddPixel(x, y);
191 } else {
192 cc->push_back(ConnectedComponent(x, y));
193 root_map.at(curt_label) = cc_count++;
194 }
195 }
196 } // end for x
197 } // end for y
198 AINFO << "cc number = " << cc_count;
199
200 return true;
201}
202
203bool ImagePoint2Camera(const base::Point2DF& img_point, float pitch_angle,
204 float camera_ground_height,
205 const Eigen::Matrix3f& intrinsic_params_inverse,
206 Eigen::Vector3d* camera_point) {
207 Eigen::MatrixXf pt_m(3, 1);
208 pt_m << img_point.x, img_point.y, 1;
209 const Eigen::MatrixXf& org_camera_point = intrinsic_params_inverse * pt_m;
210 //
211 float cos_pitch = static_cast<float>(cos(pitch_angle));
212 float sin_pitch = static_cast<float>(sin(pitch_angle));
213 Eigen::Matrix3f pitch_matrix;
214 pitch_matrix << 1, 0, 0, 0, cos_pitch, sin_pitch, 0, -sin_pitch, cos_pitch;
215 const Eigen::MatrixXf& rotate_point = pitch_matrix * org_camera_point;
216 if (fabs(rotate_point(1, 0)) < lane_eps_value) {
217 return false;
218 }
219 float scale = camera_ground_height / rotate_point(1, 0);
220 (*camera_point)(0) = scale * org_camera_point(0, 0);
221 (*camera_point)(1) = scale * org_camera_point(1, 0);
222 (*camera_point)(2) = scale * org_camera_point(2, 0);
223 return true;
224}
225
226bool CameraPoint2Image(const Eigen::Vector3d& camera_point,
227 const Eigen::Matrix3f& intrinsic_params,
228 base::Point2DF* img_point) {
229 Eigen::Vector3f camera_point3f;
230 camera_point3f(0, 0) = static_cast<float>(camera_point(0, 0));
231 camera_point3f(1, 0) = static_cast<float>(camera_point(1, 0));
232 camera_point3f(2, 0) = static_cast<float>(camera_point(2, 0));
233 Eigen::MatrixXf img_point3f = intrinsic_params * camera_point3f;
234 if (fabs(img_point3f(2, 0)) < lane_eps_value) {
235 return false;
236 }
237 img_point->x = img_point3f(0, 0) / img_point3f(2, 0);
238 img_point->y = img_point3f(1, 0) / img_point3f(2, 0);
239 return true;
240}
242 const base::Point2DF& point2) {
243 return point1.y < point2.y;
244}
245
246bool FindKSmallValue(const float* distance, int dim, int k, int* index) {
247 if (dim < k) {
248 AWARN << "dim is smaller than k";
249 return false;
250 }
251 if (k <= 0) {
252 AWARN << "k is smaller than 0";
253 return false;
254 }
255 std::vector<float> small_value(k);
256 // sort the small value vector
257 QuickSort(index, distance, k);
258 for (int i = 0; i < k; i++) {
259 small_value[i] = distance[index[i]];
260 }
261
262 for (int i = k; i < dim; i++) {
263 float max_value = small_value[k - 1];
264 if (distance[i] >= max_value) {
265 continue;
266 }
267 int locate_index = -1;
268 if (distance[i] < small_value[0]) {
269 locate_index = 0;
270 } else {
271 for (int j = 0; j < k - 1; j++) {
272 if (distance[i] >= small_value[j] &&
273 distance[i] <= small_value[j + 1]) {
274 locate_index = j + 1;
275 break;
276 } // if
277 } // for
278 } // else
279 if (locate_index == -1) {
280 return false;
281 }
282 for (int j = k - 2; j >= locate_index; j--) {
283 small_value[j + 1] = small_value[j];
284 index[j + 1] = index[j];
285 }
286 small_value[locate_index] = distance[i];
287 index[locate_index] = i;
288 }
289 return true;
290}
291
292bool FindKLargeValue(const float* distance, int dim, int k, int* index) {
293 if (dim < k) {
294 AWARN << "dim is smaller than k";
295 return false;
296 }
297 if (k <= 0) {
298 AWARN << "k is smaller than 0";
299 return false;
300 }
301 std::vector<float> large_value(k);
302 std::vector<int> large_index(k);
303 // sort the large value vector
304 QuickSort(&(large_index[0]), distance, k);
305 for (int i = 0; i < k; i++) {
306 index[i] = large_index[k - 1 - i];
307 large_value[i] = distance[index[i]];
308 }
309
310 for (int i = k; i < dim; i++) {
311 float min_value = large_value[k - 1];
312 if (distance[i] <= min_value) {
313 continue;
314 }
315 int locate_index = -1;
316 if (distance[i] > large_value[0]) {
317 locate_index = 0;
318 } else {
319 for (int j = 0; j < k - 1; j++) {
320 if (distance[i] <= large_value[j] &&
321 distance[i] >= large_value[j + 1]) {
322 locate_index = j + 1;
323 break;
324 } // if
325 } // for
326 } // else
327 if (locate_index == -1) {
328 return false;
329 }
330 for (int j = k - 2; j >= locate_index; j--) {
331 large_value[j + 1] = large_value[j];
332 index[j + 1] = index[j];
333 }
334 large_value[locate_index] = distance[i];
335 index[locate_index] = i;
336 }
337 return true;
338}
339} // namespace camera
340} // namespace perception
341} // namespace apollo
void AddPixel(int x, int y)
ConnectedComponent
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
void QuickSort(int *index, const T *values, int start, int end)
bool ComparePoint2DY(const base::Point2DF &point1, const base::Point2DF &point2)
bool FindKLargeValue(const float *distance, int dim, int k, int *index)
bool ImagePoint2Camera(const base::Point2DF &img_point, float pitch_angle, float camera_ground_height, const Eigen::Matrix3f &intrinsic_params_inverse, Eigen::Vector3d *camera_point)
bool FindCC(const std::vector< unsigned char > &src, int width, int height, const base::RectI &roi, std::vector< ConnectedComponent > *cc)
bool CameraPoint2Image(const Eigen::Vector3d &camera_point, const Eigen::Matrix3f &intrinsic_params, base::Point2DF *img_point)
bool FindKSmallValue(const float *distance, int dim, int k, int *index)
class register implement
Definition arena_queue.h:37