109 {
110 ADEBUG <<
"Begin to Process2D.";
111 frame->lane_objects.clear();
112 auto start = std::chrono::high_resolution_clock::now();
113
114 cv::Mat lane_map(lane_map_height_, lane_map_width_, CV_32FC1);
115 memcpy(lane_map.data, frame->lane_detected_blob->cpu_data(),
116 lane_map_width_ * lane_map_height_ * sizeof(float));
117
118
119
120
121
122
123
124
125
126 int y = static_cast<int>(lane_map.rows * 0.9 - 1);
127
128 int step_y = (y - 40) * (y - 40) / 6400 + 1;
129
130 xy_points.clear();
131 xy_points.resize(lane_type_num_);
132 uv_points.clear();
133 uv_points.resize(lane_type_num_);
134
135 while (y > 0) {
136 for (int x = 1; x < lane_map.cols - 1; ++x) {
137 int value = static_cast<int>(round(lane_map.at<float>(y, x)));
138
139
140 if ((value > 0 && value < 5) || value == 11) {
141
142 if (value != static_cast<int>(round(lane_map.at<float>(y, x + 1)))) {
143 Eigen::Matrix<float, 3, 1> img_point(
144 static_cast<float>(x * roi_width_ / lane_map.cols),
145 static_cast<float>(y * roi_height_ / lane_map.rows + roi_start_),
146 1.0);
147 Eigen::Matrix<float, 3, 1> xy_p;
148 xy_p = trans_mat_ * img_point;
149 Eigen::Matrix<float, 2, 1> xy_point;
150 Eigen::Matrix<float, 2, 1> uv_point;
151 if (std::fabs(xy_p(2)) < 1e-6) continue;
152 xy_point << xy_p(0) / xy_p(2), xy_p(1) / xy_p(2);
153
154
155 if (xy_point(0) < 0.0 ||
156 xy_point(0) > max_longitudinal_distance_ ||
157 std::abs(xy_point(1)) > 30.0) {
158 continue;
159 }
160 uv_point << static_cast<float>(x * roi_width_ / lane_map.cols),
161 static_cast<float>(y * roi_height_ / lane_map.rows + roi_start_);
162 if (xy_points[value].size() < minNumPoints_ || xy_point(0) < 50.0f ||
163 std::fabs(xy_point(1) - xy_points[value].back()(1)) < 1.0f) {
164 xy_points[value].push_back(xy_point);
165 uv_points[value].push_back(uv_point);
166 }
167 }
168 } else if (value >= 5 && value < lane_type_num_) {
169
170 if (value != static_cast<int>(round(lane_map.at<float>(y, x - 1)))) {
171 Eigen::Matrix<float, 3, 1> img_point(
172 static_cast<float>(x * roi_width_ / lane_map.cols),
173 static_cast<float>(y * roi_height_ / lane_map.rows + roi_start_),
174 1.0);
175 Eigen::Matrix<float, 3, 1> xy_p;
176 xy_p = trans_mat_ * img_point;
177 Eigen::Matrix<float, 2, 1> xy_point;
178 Eigen::Matrix<float, 2, 1> uv_point;
179 if (std::fabs(xy_p(2)) < 1e-6) continue;
180 xy_point << xy_p(0) / xy_p(2), xy_p(1) / xy_p(2);
181
182 if (xy_point(0) < 0.0 ||
183 xy_point(0) > max_longitudinal_distance_ ||
184 std::abs(xy_point(1)) > 30.0) {
185 continue;
186 }
187 uv_point << static_cast<float>(x * roi_width_ / lane_map.cols),
188 static_cast<float>(y * roi_height_ / lane_map.rows + roi_start_);
189 if (xy_points[value].size() < minNumPoints_ || xy_point(0) < 50.0f ||
190 std::fabs(xy_point(1) - xy_points[value].back()(1)) < 1.0f) {
191 xy_points[value].push_back(xy_point);
192 uv_points[value].push_back(uv_point);
193 }
194 } else if (value >= lane_type_num_) {
195 AWARN <<
"Lane line value shouldn't be equal or more than: "
196 << lane_type_num_;
197 }
198 }
199 }
200 step_y = (y - 45) * (y - 45) / 6400 + 1;
201 y -= step_y;
202 }
203
204 auto elapsed_1 = std::chrono::high_resolution_clock::now() - start;
205 int64_t microseconds_1 =
206 std::chrono::duration_cast<std::chrono::microseconds>(elapsed_1).count();
207 time_1 += microseconds_1;
208
209
210 EigenVector<Eigen::Matrix<float, 4, 1>> coeffs;
211 EigenVector<Eigen::Matrix<float, 4, 1>> img_coeffs;
212 EigenVector<Eigen::Matrix<float, 2, 1>> selected_xy_points;
213 coeffs.resize(lane_type_num_);
214 img_coeffs.resize(lane_type_num_);
215 for (int i = 1; i < lane_type_num_; ++i) {
216 coeffs[i] << 0, 0, 0, 0;
217 if (xy_points[i].size() < minNumPoints_) continue;
218 Eigen::Matrix<float, 4, 1> coeff;
219
220 if (RansacFitting<float>(xy_points[i], &selected_xy_points, &coeff, 200,
221 static_cast<int>(minNumPoints_), 0.1f)) {
222 coeffs[i] = coeff;
223
224 xy_points[i].clear();
225 xy_points[i] = selected_xy_points;
226 } else {
227 xy_points[i].clear();
228 }
229 }
230
231 auto elapsed_2 = std::chrono::high_resolution_clock::now() - start;
232 int64_t microseconds_2 =
233 std::chrono::duration_cast<std::chrono::microseconds>(elapsed_2).count();
234 time_2 += microseconds_2 - microseconds_1;
235
236
237 std::vector<float> c0s(lane_type_num_, 0);
238 for (int i = 1; i < lane_type_num_; ++i) {
239 if (xy_points[i].size() < minNumPoints_) continue;
241 static_cast<float>(coeffs[i](3)), static_cast<float>(coeffs[i](2)),
242 static_cast<float>(coeffs[i](1)), static_cast<float>(coeffs[i](0)),
243 static_cast<float>(3.0));
244 }
245
246 if (xy_points[4].size() < minNumPoints_ &&
247 xy_points[5].size() >= minNumPoints_) {
248 std::swap(xy_points[4], xy_points[5]);
249 std::swap(uv_points[4], uv_points[5]);
250 std::swap(coeffs[4], coeffs[5]);
251 std::swap(c0s[4], c0s[5]);
252 } else if (xy_points[6].size() < minNumPoints_ &&
253 xy_points[5].size() >= minNumPoints_) {
254 std::swap(xy_points[6], xy_points[5]);
255 std::swap(uv_points[6], uv_points[5]);
256 std::swap(coeffs[6], coeffs[5]);
257 std::swap(c0s[6], c0s[5]);
258 }
259
260 if (xy_points[4].size() < minNumPoints_ &&
261 xy_points[11].size() >= minNumPoints_) {
262
263 bool use_boundary = true;
264 for (int k = 3; k >= 1; --k) {
265 if (xy_points[k].size() >= minNumPoints_) {
266 use_boundary = false;
267 break;
268 }
269 }
270 if (use_boundary) {
271 std::swap(xy_points[4], xy_points[11]);
272 std::swap(uv_points[4], uv_points[11]);
273 std::swap(coeffs[4], coeffs[11]);
274 std::swap(c0s[4], c0s[11]);
275 }
276 }
277
278 if (xy_points[6].size() < minNumPoints_ &&
279 xy_points[12].size() >= minNumPoints_) {
280
281 bool use_boundary = true;
282 for (int k = 7; k <= 9; ++k) {
283 if (xy_points[k].size() >= minNumPoints_) {
284 use_boundary = false;
285 break;
286 }
287 }
288 if (use_boundary) {
289 std::swap(xy_points[6], xy_points[12]);
290 std::swap(uv_points[6], uv_points[12]);
291 std::swap(coeffs[6], coeffs[12]);
292 std::swap(c0s[6], c0s[12]);
293 }
294 }
295
296 for (int i = 1; i < lane_type_num_; ++i) {
297 base::LaneLine cur_object;
298 if (xy_points[i].size() < minNumPoints_) {
299 continue;
300 }
301
302
304
305
306 if ((i < 5 && c0s[i] < c0s[i + 1]) ||
307 (i > 5 && i < 10 && c0s[i] > c0s[i - 1])) {
308 continue;
309 }
310 if (i == 11 || i == 12) {
311 std::sort(c0s.begin(), c0s.begin() + 10);
312 if ((c0s[i] > c0s[0] && i == 12) || (c0s[i] < c0s[9] && i == 11)) {
313 continue;
314 }
315 }
316
317 cur_object.curve_car_coord.x_start =
318 static_cast<float>(xy_points[i].front()(0));
319 cur_object.curve_car_coord.x_end =
320 static_cast<float>(xy_points[i].back()(0));
321 cur_object.curve_car_coord.a = static_cast<float>(coeffs[i](3));
322 cur_object.curve_car_coord.b = static_cast<float>(coeffs[i](2));
323 cur_object.curve_car_coord.c = static_cast<float>(coeffs[i](1));
324 cur_object.curve_car_coord.d = static_cast<float>(coeffs[i](0));
325
326
327
328 cur_object.curve_car_coord_point_set.clear();
329 for (size_t j = 0; j < xy_points[i].size(); ++j) {
331 p_j.
x =
static_cast<float>(xy_points[i][j](0));
332 p_j.y = static_cast<float>(xy_points[i][j](1));
333 cur_object.curve_car_coord_point_set.push_back(p_j);
334 }
335
336 cur_object.curve_image_point_set.clear();
337 for (size_t j = 0; j < uv_points[i].size(); ++j) {
339 p_j.
x =
static_cast<float>(uv_points[i][j](0));
340 p_j.y = static_cast<float>(uv_points[i][j](1));
341 cur_object.curve_image_point_set.push_back(p_j);
342 }
343
344
345 cur_object.confidence = 1.0f;
346 frame->lane_objects.push_back(cur_object);
347 }
348
349
350
351 int has_center_ = 0;
352 for (auto lane_ : frame->lane_objects) {
354 if (lane_.curve_car_coord.d >= 0) {
355 has_center_ = 1;
356 } else if (lane_.curve_car_coord.d < 0) {
357 has_center_ = 2;
358 }
359 break;
360 }
361 }
362
363 if (has_center_ == 1) {
364 for (auto& lane_ : frame->lane_objects) {
366 if (spatial_id >= 1 && spatial_id <= 5) {
368 }
369 }
370 } else if (has_center_ == 2) {
371 for (auto& lane_ : frame->lane_objects) {
373 if (spatial_id >= 5 && spatial_id <= 9) {
375 }
376 }
377 }
378
379 auto elapsed = std::chrono::high_resolution_clock::now() - start;
380 int64_t microseconds =
381 std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count();
382
383 time_3 += microseconds - microseconds_2;
384 ++time_num;
385
386 ADEBUG <<
"frame->lane_objects.size(): " << frame->lane_objects.size();
387
388 ADEBUG <<
"Avg sampling time: " << time_1 / time_num
389 << " Avg fitting time: " << time_2 / time_num
390 << " Avg writing time: " << time_3 / time_num;
391 ADEBUG <<
"darkSCNN lane_postprocess done!";
392 return true;
393}
@ EGO_CENTER
center lane marking of the ego lane, changing lane
Point2D< float > Point2DF
T GetPolyValue(T a, T b, T c, T d, T x)
std::vector< base::LaneLinePositionType > spatialLUT({base::LaneLinePositionType::UNKNOWN, base::LaneLinePositionType::FOURTH_LEFT, base::LaneLinePositionType::THIRD_LEFT, base::LaneLinePositionType::ADJACENT_LEFT, base::LaneLinePositionType::EGO_LEFT, base::LaneLinePositionType::EGO_CENTER, base::LaneLinePositionType::EGO_RIGHT, base::LaneLinePositionType::ADJACENT_RIGHT, base::LaneLinePositionType::THIRD_RIGHT, base::LaneLinePositionType::FOURTH_RIGHT, base::LaneLinePositionType::OTHER, base::LaneLinePositionType::CURB_LEFT, base::LaneLinePositionType::CURB_RIGHT})