Apollo 11.0
自动驾驶开放平台
track_object_similarity.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#include <limits>
20
23
24namespace {
25constexpr float kFloatEpsilon = std::numeric_limits<float>::epsilon();
26} // namespace
27
28namespace apollo {
29namespace perception {
30namespace fusion {
31
32// @brief: calculate the location similarity between cloud and camera box
33// @return the location similarity which belongs to [0, 1].
34// @key idea:
35// 1. calculate the mean x y pixel distance
36// 2. normalize mean pixel distance on the size of box and std of x/y
37// 3. generate location similarity from Chi-Squared distribution
38// @NOTE: original method name is compute_pts_box_dist_score
40 const ProjectionCacheObject* object,
41 const base::BBox2DF& camera_bbox) {
42 static const double min_p = 1e-6;
43 static const double max_p = 1 - 1e-6;
44 double x_std_dev = 0.4;
45 double y_std_dev = 0.5;
46 size_t check_augmented_iou_minimum_pts_num = 20;
47 float augmented_buffer = 25.0f;
48 if (object->Empty()) {
49 ADEBUG << "cache object is empty!";
50 return min_p;
51 }
52 Eigen::Vector2d mean_pixel_dist(0.0, 0.0);
53 // calculate mean x y pixel distance
54 const size_t start_ind = object->GetStartInd();
55 const size_t end_ind = object->GetEndInd();
56 if (end_ind - start_ind >= check_augmented_iou_minimum_pts_num) {
57 base::BBox2DF velo_bbox = object->GetBox();
58 float augmented_iou =
59 CalculateAugmentedIOUBBox(velo_bbox, camera_bbox, augmented_buffer);
60 if (augmented_iou < kFloatEpsilon) {
61 ADEBUG << "augmented iou is empty!";
62 return min_p;
63 }
64 }
65 for (size_t i = start_ind; i < end_ind; ++i) {
66 auto* velo_pt2d = cache->GetPoint2d(i);
67 if (velo_pt2d == nullptr) {
68 AERROR << "query pt from projection cache failed!";
69 continue;
70 }
71 if (velo_pt2d->x() >= camera_bbox.xmin &&
72 velo_pt2d->x() < camera_bbox.xmax &&
73 velo_pt2d->y() >= camera_bbox.ymin &&
74 velo_pt2d->y() < camera_bbox.ymax) {
75 continue;
76 }
77 Eigen::Vector2d diff;
78 diff.x() = std::max(0.0, camera_bbox.xmin - velo_pt2d->x());
79 diff.x() = std::max(diff.x(), velo_pt2d->x() - camera_bbox.xmax);
80 diff.y() = std::max(0.0, camera_bbox.ymin - velo_pt2d->y());
81 diff.y() = std::max(diff.y(), velo_pt2d->y() - camera_bbox.ymax);
82 mean_pixel_dist += diff;
83 }
84 mean_pixel_dist /= static_cast<double>(object->Size());
85 ADEBUG << "mean_pixel_dist is: " << mean_pixel_dist;
86 // normalize according to box size
87 Eigen::Vector2d box_size = Eigen::Vector2d(
88 camera_bbox.xmax - camera_bbox.xmin, camera_bbox.ymax - camera_bbox.ymin);
89 mean_pixel_dist.array() /= box_size.array();
90 // assuming the normalized distance obeys gauss distribution
91 double square_norm_mean_pixel_dist =
92 mean_pixel_dist.x() * mean_pixel_dist.x() / x_std_dev / x_std_dev +
93 mean_pixel_dist.y() * mean_pixel_dist.y() / y_std_dev / y_std_dev;
94 // use chi-square distribution. Cauchy may be more reasonable.
95 double location_similarity =
96 1 - ChiSquaredCdf2TableFun(square_norm_mean_pixel_dist);
97 // for numerical stability
98 location_similarity = std::max(min_p, std::min(max_p, location_similarity));
99 return location_similarity;
100}
101// @brief: calculate the shape similarity between cloud and camera box
102// @return the shape similarity which belongs to [0, 1].
103// @key idea:
104// 1. calculate box size diff between velo box and camera box
105// 2. normalize box size diff according to the std of x/y
106// 3. generate shape similarity from Chi-Squared distribution
107// @NOTE: original method name is compute_pts_box_shape_score
109 const ProjectionCacheObject* object,
110 const base::BBox2DF& camera_bbox) {
111 static const double min_p = 1e-3;
112 static const double max_p = 1 - 1e-3;
113 double x_std_dev = 0.3;
114 double y_std_dev = 0.4;
115 if (object->Empty()) {
116 return min_p;
117 }
118 // compute 2d bbox size of camera & velo
119 Eigen::Vector2d camera_box_size = Eigen::Vector2d(
120 camera_bbox.xmax - camera_bbox.xmin, camera_bbox.ymax - camera_bbox.ymin);
121 // handled one point case
122 base::BBox2DF velo_projection_bbox = object->GetBox();
123 Eigen::Vector2d velo_box_size = camera_box_size / 10;
124 velo_box_size.x() =
125 std::max(static_cast<float>(velo_box_size.x()),
126 velo_projection_bbox.xmax - velo_projection_bbox.xmin);
127 velo_box_size.y() =
128 std::max(static_cast<float>(velo_box_size.y()),
129 velo_projection_bbox.ymax - velo_projection_bbox.ymin);
130 // compute normalized box size diff
131 Eigen::Vector2d mean_box_size = (camera_box_size + velo_box_size) / 2;
132 Eigen::Vector2d box_size_diff =
133 (velo_box_size - camera_box_size).array() / mean_box_size.array();
134 // assuming the normalized distance obeys gauss distribution
135 double square_norm_box_size_diff =
136 box_size_diff.x() * box_size_diff.x() / x_std_dev / x_std_dev +
137 box_size_diff.y() * box_size_diff.y() / y_std_dev / y_std_dev;
138 ADEBUG << "camera_box_size@(" << camera_box_size(0) << ","
139 << camera_box_size(1) << "); "
140 << "velo_box_size@(" << velo_box_size.x() << "," << velo_box_size.y()
141 << "); "
142 << "box_size_diff@(" << box_size_diff.x() << "," << box_size_diff.y()
143 << "); "
144 << "square_norm_box_size_diff@" << square_norm_box_size_diff;
145 // use chi-square distribution. Cauchy may be more reasonable.
146 double shape_similarity =
147 1 - ChiSquaredCdf2TableFun(square_norm_box_size_diff);
148 // for numerical stability
149 shape_similarity = std::max(min_p, std::min(max_p, shape_similarity));
150 return shape_similarity;
151}
152// @brief: calculate the similarity between cloud and camera box
153// @return the similarity which belongs to [0, 1].
154// @key idea:
155// 1. compute location similarity and shape similarity
156// 2. fuse the two similarity above
157// @NOTE: original method name is compute_pts_box_score
159 const ProjectionCacheObject* object,
160 const base::BBox2DF& camera_bbox) {
161 double location_similarity =
162 ComputePtsBoxLocationSimilarity(cache, object, camera_bbox);
163 double shape_similarity =
164 ComputePtsBoxShapeSimilarity(cache, object, camera_bbox);
165 double fused_similarity =
166 FuseTwoProbabilities(location_similarity, shape_similarity);
167 ADEBUG << "fused_similarity@" << fused_similarity << ", location_similarity@"
168 << location_similarity << ", shape_similarity@" << shape_similarity;
169 return fused_similarity;
170}
171// @brief: calculate the x/y/h similarity between radar and camera
172// @return the similarity which belongs to [0, 1].
173// @key idea:
174// 1. compute the difference on x/y/h
175// 2. compute similarity according to the WelshVarLoss/ChiSquareProb
176// 3. scale the similarity above
177double ComputeRadarCameraXSimilarity(const double velo_ct_x,
178 const double camera_ct_x,
179 const double size_x,
180 const XSimilarityParams& params) {
181 double x_diff = std::abs(velo_ct_x - camera_ct_x) / size_x;
182 double x_similarity = WelshVarLossFun(x_diff, params.welsh_loss_thresh_,
183 params.welsh_loss_scale_);
184 x_similarity = ScalePositiveProbability(
185 x_similarity, params.scale_positive_max_p_, params.scale_positive_th_p_);
186 return x_similarity;
187}
188double ComputeRadarCameraYSimilarity(const double velo_ct_y,
189 const double camera_ct_y,
190 const double size_y,
191 const YSimilarityParams& params) {
192 // double y_diff =
193 // std::abs(velo_ct_y - camera_ct_y + size_y * params.smooth_factor_) /
194 // size_y;
195
196 double y_diff = std::max(std::abs(velo_ct_y - camera_ct_y) -
197 size_y * params.smooth_factor_,
198 0.0) /
199 size_y;
200
201 double normalized_y_diff =
202 y_diff * y_diff / params.diff_std_dev_ / params.diff_std_dev_;
203 double y_similarity = 1 - ChiSquaredCdf1TableFun(normalized_y_diff);
204 y_similarity = BoundedScalePositiveProbability(
205 y_similarity, params.bounded_scale_positive_max_p_,
207 return y_similarity;
208}
210 const SensorObjectConstPtr& radar, const SensorObjectConstPtr& camera,
211 const double size_y,
212 const EigenVector<Eigen::Vector2d>& radar_box2d_vertices,
213 const HSimilarityParams& params) {
214 const double camera_height = camera->GetBaseObject()->size(2);
215 double height_similarity = params.initial_similarity_;
216 if (camera_height > kFloatEpsilon) {
217 double min_height_diff = std::numeric_limits<double>::max();
218 for (size_t i = 0; i < 4; ++i) {
219 double img_car_height = std::abs(radar_box2d_vertices[i + 4].y() -
220 radar_box2d_vertices[i].y());
221 min_height_diff =
222 std::min(std::abs(img_car_height - size_y), min_height_diff);
223 }
224 min_height_diff /= size_y;
225 double normalized_min_height_diff = min_height_diff * min_height_diff /
226 params.diff_std_dev_ /
227 params.diff_std_dev_;
228 height_similarity = 1 - ChiSquaredCdf1TableFun(normalized_min_height_diff);
229 height_similarity = ScalePositiveProbability(height_similarity,
231 params.scale_positive_th_p_);
232 }
233 return height_similarity;
234}
236 const SensorObjectConstPtr& radar, const double width, const double size_x,
237 const EigenVector<Eigen::Vector2d>& radar_box2d_vertices,
238 const WSimilarityParams& params) {
239 std::vector<double> radar_box2d_xs = {
240 radar_box2d_vertices[0].x(), radar_box2d_vertices[1].x(),
241 radar_box2d_vertices[2].x(), radar_box2d_vertices[3].x()};
242 for (double& x : radar_box2d_xs) {
243 x = Bound(x, width, 0.0);
244 }
245 auto min_max_xs =
246 std::minmax_element(radar_box2d_xs.begin(), radar_box2d_xs.end());
247 double radar_box2d_width = *min_max_xs.second - *min_max_xs.first;
248 double width_diff = std::abs(radar_box2d_width - size_x) / size_x;
249 double normalized_width_diff =
250 width_diff * width_diff / params.diff_std_dev_ / params.diff_std_dev_;
251 double width_similarity = 1 - ChiSquaredCdf1TableFun(normalized_width_diff);
252 width_similarity = BoundedScalePositiveProbability(
253 width_similarity, params.bounded_scale_positive_max_p_,
255 return width_similarity;
256}
257double ComputeRadarCameraLocSimilarity(const Eigen::Vector3d& radar_ct,
258 const SensorObjectConstPtr& camera,
259 const Eigen::Matrix4d& world2camera_pose,
260 const LocSimilarityParams& params) {
261 Eigen::Vector3d camera_ct = camera->GetBaseObject()->center;
262 Eigen::Vector3d camera_ct_c =
263 (world2camera_pose * camera_ct.homogeneous()).head(3);
264 double ct_diff = (radar_ct - camera_ct).norm();
265 ct_diff = ct_diff / camera_ct_c.z();
266 double ct_similarity = WelshVarLossFun(ct_diff, params.welsh_loss_thresh_,
267 params.welsh_loss_scale_);
268 ct_similarity = ScalePositiveProbability(
269 ct_similarity, params.scale_positive_max_p_, params.scale_positive_th_p_);
270 return ct_similarity;
271}
272
274 const SensorObjectConstPtr& radar, const SensorObjectConstPtr& camera) {
275 Eigen::Vector3f radar_velocity = radar->GetBaseObject()->velocity;
276 Eigen::Vector3f camera_velocity = camera->GetBaseObject()->velocity;
277
278 float scalar_radar_velocity = radar_velocity.norm();
279 float scalar_camera_velocity = camera_velocity.norm();
280 if (std::max(scalar_radar_velocity, scalar_camera_velocity) > 2) {
281 float diff_velocity = (radar_velocity - camera_velocity).norm() / 2;
282 float diff_velocity_ratio =
283 diff_velocity / std::max(scalar_camera_velocity, scalar_radar_velocity);
284 const float velocity_std = 0.15f;
285 const float max_velocity_p = 0.9f;
286 const float th_velocity_p = 0.5f;
287 float velocity_score = static_cast<float>(
288 1 - ChiSquaredCdf1TableFun(diff_velocity_ratio * diff_velocity_ratio /
289 velocity_std / velocity_std));
290 velocity_score = static_cast<float>(ScalePositiveProbability(
291 velocity_score, max_velocity_p, th_velocity_p));
292 return velocity_score;
293 } else {
294 return 0.5;
295 }
296}
297
298} // namespace fusion
299} // namespace perception
300} // namespace apollo
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
T Bound(const T &value, const T &max_value, const T &min_value)
std::shared_ptr< const SensorObject > SensorObjectConstPtr
double BoundedScalePositiveProbability(double p, double max_p, double min_p)
double ScalePositiveProbability(double p, double max_p, double th_p)
double ComputePtsBoxSimilarity(const ProjectionCachePtr &cache, const ProjectionCacheObject *object, const base::BBox2DF &camera_bbox)
double ComputePtsBoxShapeSimilarity(const ProjectionCachePtr &cache, const ProjectionCacheObject *object, const base::BBox2DF &camera_bbox)
double ComputeRadarCameraWSimilarity(const SensorObjectConstPtr &radar, const double width, const double size_x, const EigenVector< Eigen::Vector2d > &radar_box2d_vertices, const WSimilarityParams &params)
calculate the w similarity between radar and camera
double ComputeRadarCameraYSimilarity(const double velo_ct_y, const double camera_ct_y, const double size_y, const YSimilarityParams &params)
calculate the y similarity between radar and camera
Type CalculateAugmentedIOUBBox(const base::BBox2D< Type > &box1, const base::BBox2D< Type > &box2, const Type &augmented_buffer)
Calculate augmented IOU BBox
Definition camera_util.h:66
double WelshVarLossFun(double dist, double th, double scale)
double ComputeRadarCameraXSimilarity(const double velo_ct_x, const double camera_ct_x, const double size_x, const XSimilarityParams &params)
double ComputeRadarCameraVelocitySimilarity(const SensorObjectConstPtr &radar, const SensorObjectConstPtr &camera)
calculate the velocity similarity between radar and camera
double FuseTwoProbabilities(double prob1, double prob2)
double ComputeRadarCameraLocSimilarity(const Eigen::Vector3d &radar_ct, const SensorObjectConstPtr &camera, const Eigen::Matrix4d &world2camera_pose, const LocSimilarityParams &params)
calculate the loc similarity between radar and camera
double ComputePtsBoxLocationSimilarity(const ProjectionCachePtr &cache, const ProjectionCacheObject *object, const base::BBox2DF &camera_bbox)
double ComputeRadarCameraHSimilarity(const SensorObjectConstPtr &radar, const SensorObjectConstPtr &camera, const double size_y, const EigenVector< Eigen::Vector2d > &radar_box2d_vertices, const HSimilarityParams &params)
calculate the h similarity between radar and camera
constexpr float kFloatEpsilon
Definition lane_object.h:32
class register implement
Definition arena_queue.h:37