Apollo 11.0
自动驾驶开放平台
camera_util.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
22
23#include <limits>
24
25namespace apollo {
26namespace perception {
27namespace fusion {
28
30
31void GetObjectEightVertices(std::shared_ptr<const base::Object> obj,
32 EigenVector<Eigen::Vector3d>* vertices) {
33 vertices->clear();
34 vertices->resize(8);
35 Eigen::Vector3d center = obj->center;
36 Eigen::Vector2d dir = obj->direction.head(2).cast<double>();
37 dir.normalize();
38 Eigen::Vector2d orth_dir(-dir.y(), dir.x());
39 Eigen::Vector2d delta_x = dir * obj->size(0) * 0.5;
40 Eigen::Vector2d delta_y = orth_dir * obj->size(1) * 0.5;
41
42 // lower four points
43 center.z() -= obj->size(2) * 0.5;
44 (*vertices)[0] = center, (*vertices)[0].head(2) += (-delta_x - delta_y);
45 (*vertices)[1] = center, (*vertices)[1].head(2) += (-delta_x + delta_y);
46 (*vertices)[2] = center, (*vertices)[2].head(2) += (delta_x + delta_y);
47 (*vertices)[3] = center, (*vertices)[3].head(2) += (delta_x - delta_y);
48 // upper four points
49 (*vertices)[4] = (*vertices)[0], (*vertices)[4].z() += obj->size(2);
50 (*vertices)[5] = (*vertices)[1], (*vertices)[5].z() += obj->size(2);
51 (*vertices)[6] = (*vertices)[2], (*vertices)[6].z() += obj->size(2);
52 (*vertices)[7] = (*vertices)[3], (*vertices)[7].z() += obj->size(2);
53}
54
55bool Pt3dToCamera2d(const Eigen::Vector3d& pt3d,
56 const Eigen::Matrix4d& world2camera_pose,
57 base::BaseCameraModelPtr camera_model,
58 Eigen::Vector2d* pt2d) {
59 Eigen::Vector4d local_pt = static_cast<Eigen::Matrix<double, 4, 1, 0, 4, 1>>(
60 world2camera_pose * Eigen::Vector4d(pt3d(0), pt3d(1), pt3d(2), 1));
61 if (local_pt[2] > 0) {
62 *pt2d =
63 (camera_model->Project(Eigen::Vector3f(
64 static_cast<float>(local_pt[0]), static_cast<float>(local_pt[1]),
65 static_cast<float>(local_pt[2]))))
66 .cast<double>();
67 return true;
68 }
69 return false;
70}
71
73 const std::shared_ptr<const base::Object>& obj,
74 const Eigen::Matrix4d& world2camera_pose,
75 base::BaseCameraModelPtr camera_model) {
76 EigenVector<Eigen::Vector3d> vertices(8);
77 GetObjectEightVertices(obj, &vertices);
78 Eigen::Vector2d pt2d;
79 for (const auto& vertice : vertices) {
80 if ((Pt3dToCamera2d(vertice, world2camera_pose, camera_model, &pt2d))) {
81 return false;
82 }
83 }
84 return true;
85}
86
88 base::BaseCameraModelPtr camera_model,
89 const Eigen::Affine3d& camera_sensor2world_pose,
90 double camera_ts, double camera_max_dist,
91 bool motion_compensation, bool all_in) {
92 constexpr float kFloatEpsilon = std::numeric_limits<float>::epsilon();
93 float in_view_ratio = 0.0f;
94 Eigen::Matrix4d world2sensor_pose =
95 camera_sensor2world_pose.matrix().inverse();
96 if (!world2sensor_pose.allFinite()) {
97 return in_view_ratio;
98 }
99 double width = static_cast<double>(camera_model->get_width());
100 double height = static_cast<double>(camera_model->get_height());
101
102 double time_diff =
103 camera_ts - sensor_object->GetBaseObject()->latest_tracked_time;
104 Eigen::Vector3f offset =
105 sensor_object->GetBaseObject()->velocity * static_cast<float>(time_diff);
106 if (!motion_compensation) {
107 offset.setZero();
108 }
109 // 2.compute distance
110 const auto& cloud =
111 sensor_object->GetBaseObject()->lidar_supplement.cloud_world;
112 Eigen::Vector3d center = sensor_object->GetBaseObject()->center;
113 Eigen::Vector2d center2d;
114 if (!Pt3dToCamera2d(center, world2sensor_pose, camera_model, &center2d)) {
115 return in_view_ratio;
116 }
117 double obj_length = sensor_object->GetBaseObject()->size(0);
118 double obj_width = sensor_object->GetBaseObject()->size(1);
119 double obj_height = sensor_object->GetBaseObject()->size(2);
120 if (cloud.size() > 0) {
121 // use point cloud
122 int point_num = static_cast<int>(cloud.size());
123 int in_view_point_num = 0;
124 for (int i = 0; i < point_num; ++i) {
125 const auto& pt = cloud.at(i);
126 Eigen::Vector3d pt3d(pt.x + offset[0], pt.y + offset[1],
127 pt.z + offset[2]);
128 Eigen::Vector2d pt2d;
129 bool flag = Pt3dToCamera2d(pt3d, world2sensor_pose, camera_model, &pt2d);
130 if (flag && IsPtInFrustum(pt2d, width, height)) {
131 ++in_view_point_num;
132 }
133 }
134 in_view_ratio = static_cast<float>(in_view_point_num / point_num);
135 if (all_in) {
136 in_view_ratio = (in_view_point_num == point_num) ? 1.0 : 0.0;
137 }
138 } else if (obj_width > kFloatEpsilon && obj_height > kFloatEpsilon &&
139 obj_length > kFloatEpsilon) {
140 // use object box
141 EigenVector<Eigen::Vector3d> box3d_vs(8);
142 GetObjectEightVertices(sensor_object->GetBaseObject(), &box3d_vs);
143 EigenVector<Eigen::Vector2f> box2d_vs;
144 box2d_vs.reserve(box3d_vs.size());
145 for (const auto& box3d_v : box3d_vs) {
146 Eigen::Vector2d pt2d;
147 bool flag = Pt3dToCamera2d(box3d_v + offset.cast<double>(),
148 world2sensor_pose, camera_model, &pt2d);
149 if (!flag) {
150 return in_view_ratio;
151 }
152 box2d_vs.push_back(pt2d.cast<float>());
153 }
154 Eigen::Vector2d top_left;
155 Eigen::Vector2d bottom_right;
156 top_left.setConstant(std::numeric_limits<double>::max());
157 bottom_right = -top_left;
158 for (const auto& box2d_v : box2d_vs) {
159 top_left = top_left.cwiseMin(box2d_v.cast<double>());
160 bottom_right = bottom_right.cwiseMax(box2d_v.cast<double>());
161 }
162 Eigen::Vector2d box_size = bottom_right - top_left;
163 Eigen::Vector2d bound_top_left =
164 top_left.cwiseMax(Eigen::Vector2d(0.0, 0.0));
165 Eigen::Vector2d bound_bottom_right =
166 bottom_right.cwiseMin(Eigen::Vector2d(width, height));
167 Eigen::Vector2d bound_box_size = bound_bottom_right - bound_top_left;
168 if ((bound_box_size.array() > 0.0).all()) {
169 in_view_ratio =
170 static_cast<float>(bound_box_size.prod() / box_size.prod());
171 } else {
172 in_view_ratio = 0.0;
173 }
174 if (all_in) {
175 in_view_ratio = std::abs(1.0 - in_view_ratio) <= 1e-6 ? 1.0 : 0.0;
176 }
177 } else { // use center point
178 if (!((center2d.array() > 0.0).all())) {
179 in_view_ratio = 0.0;
180 } else if (center2d.x() > width || center2d.y() > height) {
181 in_view_ratio = 0.0;
182 } else {
183 in_view_ratio = 1.0;
184 }
185 }
186 // compute distance score, when object is too far from camera
187 // the camera is hard to detect object
188 // maximum camera detection distance parameters
189 const double max_dist = camera_max_dist;
190 // 1 nearly 2m buffer
191 const double dist_slope = 0.25;
192 auto sigmoid_like_fun = [max_dist, dist_slope](double obj_dist) {
193 double x = obj_dist - max_dist;
194 return 0.5 - 0.5 * x * dist_slope /
195 std::sqrt(1 + x * x * dist_slope * dist_slope);
196 };
197 Eigen::Vector4d center3d_local = world2sensor_pose * center.homogeneous();
198 double dist_to_camera = center3d_local.z();
199 return static_cast<float>(in_view_ratio * sigmoid_like_fun(dist_to_camera));
200}
201
202} // namespace fusion
203} // namespace perception
204} // namespace apollo
std::vector< EigenType, Eigen::aligned_allocator< EigenType > > EigenVector
Definition eigen_defs.h:33
std::shared_ptr< BaseCameraModel > BaseCameraModelPtr
Definition camera.h:75
std::shared_ptr< const SensorObject > SensorObjectConstPtr
bool IsObjectEightVerticesAllBehindCamera(const std::shared_ptr< const base::Object > &obj, const Eigen::Matrix4d &world2camera_pose, base::BaseCameraModelPtr camera_model)
bool Pt3dToCamera2d(const Eigen::Vector3d &pt3d, const Eigen::Matrix4d &world2camera_pose, base::BaseCameraModelPtr camera_model, Eigen::Vector2d *pt2d)
float ObjectInCameraView(SensorObjectConstPtr sensor_object, base::BaseCameraModelPtr camera_model, const Eigen::Affine3d &camera_sensor2world_pose, double camera_ts, double camera_max_dist, bool motion_compensation, bool all_in)
void GetObjectEightVertices(std::shared_ptr< const base::Object > obj, EigenVector< Eigen::Vector3d > *vertices)
bool IsPtInFrustum(const VectorType &pt, double width, double height)
Is point lies in the frustum
Definition camera_util.h:49
constexpr float kFloatEpsilon
Definition lane_object.h:32
class register implement
Definition arena_queue.h:37