Apollo 11.0
自动驾驶开放平台
obj_postprocessor.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 <limits>
19
20// TODO(Xun & Yucheng): code completion
21namespace apollo {
22namespace perception {
23namespace camera {
24
26 max_nr_iter = 5;
27 sampling_ratio_low = 0.1f;
28 weight_iou = 3.0f;
29 learning_r = 0.2f;
30 learning_r_decay = 0.9f;
31 dist_far = 15.0f;
32 shrink_ratio_iou = 0.9f;
33 iou_good = 0.5f;
34}
35
37 const ObjPostProcessorOptions &options, float center[3], float hwl[3],
38 float *ry) {
39 memcpy(hwl, options.hwl, sizeof(float) * 3);
40 float bbox[4] = {0};
41 memcpy(bbox, options.bbox, sizeof(float) * 4);
42 *ry = options.ry;
43
44 // soft constraints
45 bool adjust_soft =
46 AdjustCenterWithGround(bbox, hwl, *ry, options.plane, center);
47 if (center[2] > params_.dist_far) {
48 return adjust_soft;
49 }
50
51 // hard constraints
52 bool adjust_hard = PostRefineCenterWithGroundBoundary(
53 bbox, hwl, *ry, options.plane, options.line_segs, center,
54 options.check_lowerbound);
55
56 return adjust_soft || adjust_hard;
57}
58
60 const ObjPostProcessorOptions &options, float center[3], float hwl[3],
61 float *ry) {
62 return true;
63}
64
65bool ObjPostProcessor::AdjustCenterWithGround(const float *bbox,
66 const float *hwl, float ry,
67 const float *plane,
68 float *center) const {
69 float iou_ini = GetProjectionScore(ry, bbox, hwl, center);
70 if (iou_ini < params_.iou_good) { // ini pos is not good enough
71 return false;
72 }
73 const float MIN_COST = hwl[2] * params_.sampling_ratio_low;
74 const float EPS_COST_DELTA = 1e-1f;
75 const float WEIGHT_IOU = params_.weight_iou;
76 const int MAX_ITERATION = params_.max_nr_iter;
77
78 float lr = params_.learning_r;
79 float cost_pre = std::numeric_limits<float>::max();
80 float cost_delta = 0.0f;
81 float center_input[3] = {center[0], center[1], center[2]};
82 float center_test[3] = {0};
83 float x[3] = {0};
84 int iter = 1;
85 bool stop = false;
86
87 // std::cout << "start to update the center..." << std::endl;
88 while (!stop) {
89 algorithm::IProjectThroughIntrinsic(k_mat_, center, x);
90 x[0] *= algorithm::IRec(x[2]);
91 x[1] *= algorithm::IRec(x[2]);
93 x, k_mat_, plane, center_test);
94 if (!in_front) {
95 memcpy(center, center_input, sizeof(float) * 3);
96 return false;
97 }
98 float iou_cur = GetProjectionScore(ry, bbox, hwl, center);
99 float iou_test = GetProjectionScore(ry, bbox, hwl, center_test);
100 float dist = algorithm::ISqrt(algorithm::ISqr(center[0] - center_test[0]) +
101 algorithm::ISqr(center[2] - center_test[2]));
102 float cost_cur = dist + WEIGHT_IOU * (1.0f - (iou_cur + iou_test) / 2);
103 // std::cout << "cost___ " << cost_cur << "@" << iter << std::endl;
104 if (cost_cur >= cost_pre) {
105 stop = true;
106 } else {
107 cost_delta = (cost_pre - cost_cur) / cost_pre;
108 cost_pre = cost_cur;
109 center[0] += (center_test[0] - center[0]) * lr;
110 center[2] += (center_test[2] - center[2]) * lr;
111 ++iter;
112 stop = iter >= MAX_ITERATION || cost_delta < EPS_COST_DELTA ||
113 cost_pre < MIN_COST;
114 }
115 lr *= params_.learning_r_decay;
116 }
117 float iou_res = GetProjectionScore(ry, bbox, hwl, center);
118 if (iou_res < iou_ini * params_.shrink_ratio_iou) {
119 memcpy(center, center_input, sizeof(float) * 3);
120 return false;
121 }
122 return true;
123}
124
125bool ObjPostProcessor::PostRefineCenterWithGroundBoundary(
126 const float *bbox, const float *hwl, float ry, const float *plane,
127 const std::vector<LineSegment2D<float>> &line_seg_limits, float *center,
128 bool check_lowerbound) const {
129 bool truncated_on_bottom =
130 bbox[3] >= static_cast<float>(height_) -
131 (bbox[3] - bbox[1]) * params_.sampling_ratio_low;
132 if (truncated_on_bottom) {
133 return false;
134 }
135
136 float iou_before = GetProjectionScore(ry, bbox, hwl, center);
137 int nr_line_segs = static_cast<int>(line_seg_limits.size());
138 float depth_pts[4] = {0};
139 float pts_c[12] = {0};
140 int x_pts[4] = {0};
141
142 GetDepthXPair(bbox, hwl, center, ry, depth_pts, x_pts, &pts_c[0]);
143
144 float dxdz_acc[2] = {0};
145 float ratio_x_over_z = center[0] * algorithm::IRec(center[2]);
146 for (int i = 0; i < nr_line_segs; ++i) {
147 float dxdz[2] = {0};
148 GetDxDzForCenterFromGroundLineSeg(line_seg_limits[i], plane, pts_c, k_mat_,
149 width_, height_, ratio_x_over_z, dxdz,
150 check_lowerbound);
151 dxdz_acc[0] += dxdz[0];
152 dxdz_acc[1] += dxdz[1];
153 }
154 center[0] += dxdz_acc[0];
155 center[2] += dxdz_acc[1];
156
157 float iou_after = GetProjectionScore(ry, bbox, hwl, center);
158 if (iou_after < iou_before * params_.shrink_ratio_iou) {
159 center[0] -= dxdz_acc[0];
160 center[2] -= dxdz_acc[1];
161 return false;
162 }
163 return true;
164}
165
166int ObjPostProcessor::GetDepthXPair(const float *bbox, const float *hwl,
167 const float *center, float ry,
168 float *depth_pts, int *x_pts,
169 float *pts_c) const {
170 int y_min = height_;
171 float w_half = hwl[1] / 2;
172 float l_half = hwl[2] / 2;
173 float x_cor[4] = {l_half, l_half, -l_half, -l_half};
174 float z_cor[4] = {w_half, -w_half, -w_half, w_half};
175 float pts[12] = {x_cor[0], 0.0f, z_cor[0], x_cor[1], 0.0f, z_cor[1],
176 x_cor[2], 0.0f, z_cor[2], x_cor[3], 0.0f, z_cor[3]};
177 float rot[9] = {0};
178 GenRotMatrix(ry, rot);
179 float pt_proj[3] = {0};
180 float pt_c[3] = {0};
181 float *pt = pts;
182 bool save_pts_c = pts_c != nullptr;
183 for (int i = 0; i < 4; ++i) {
184 algorithm::IProjectThroughExtrinsic(rot, center, pt, pt_c);
185 algorithm::IProjectThroughIntrinsic(k_mat_, pt_c, pt_proj);
186 depth_pts[i] = pt_c[2];
187 x_pts[i] = algorithm::IRound(pt_proj[0] * algorithm::IRec(pt_proj[2]));
188 int y_proj = algorithm::IRound(pt_proj[1] * algorithm::IRec(pt_proj[2]));
189 if (y_proj < y_min) {
190 y_min = y_proj;
191 }
192 if (save_pts_c) {
193 int i3 = i * 3;
194 pts_c[i3] = pt_c[0];
195 pts_c[i3 + 1] = pt_c[1];
196 pts_c[i3 + 2] = pt_c[2];
197 }
198 pt += 3;
199 }
200 return y_min;
201}
202} // namespace camera
203} // namespace perception
204} // namespace apollo
bool PostProcessObjWithGround(const ObjPostProcessorOptions &options, float center[3], float hwl[3], float *ry)
init params
bool PostProcessObjWithDispmap(const ObjPostProcessorOptions &options, float center[3], float hwl[3], float *ry)
none
void IProjectThroughExtrinsic(const T *R, const T *t, const T *X, T *x)
Definition i_util.h:103
bool IBackprojectPlaneIntersectionCanonical(const T *x, const T *K, const T *pi, T *X)
Definition i_util.h:197
void IProjectThroughIntrinsic(const T *K, const T *X, T *x)
Definition i_util.h:111
void GenRotMatrix(const T &ry, T *rot)
void GetDxDzForCenterFromGroundLineSeg(const LineSegment2D< T > &ls, const T *plane, const T *pts_c, const T *k_mat, int width, int height, T ratio_x_over_z, T *dx_dz, bool check_lowerbound=true)
class register implement
Definition arena_queue.h:37
std::vector< LineSegment2D< float > > line_segs