Apollo 11.0
自动驾驶开放平台
multi_camera_projection.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#include <numeric>
21
22#include "cyber/common/file.h"
23#include "cyber/common/log.h"
28
29namespace apollo {
30namespace perception {
31namespace trafficlight {
32
34
36 if (options.camera_names.empty()) {
37 AERROR << "no cameras to be projected";
38 return false;
39 }
40 algorithm::SensorManager* sensor_manager =
41 algorithm::SensorManager::Instance();
42 if (!sensor_manager->Init()) {
43 AERROR << "sensor_manager init failed";
44 }
45
46 for (size_t i = 0; i < options.camera_names.size(); ++i) {
47 const std::string& cur_camera_name = options.camera_names.at(i);
48 AINFO << "init camera " << cur_camera_name;
49
50 if (!sensor_manager->IsSensorExist(cur_camera_name)) {
51 AERROR << "sensor " << cur_camera_name << " do not exist";
52 return false;
53 }
54 camera_models_[cur_camera_name] =
55 std::dynamic_pointer_cast<base::BrownCameraDistortionModel>(
56 sensor_manager->GetDistortCameraModel(cur_camera_name));
57 if (!(camera_models_[cur_camera_name])) {
58 AERROR << "get null camera_model, camera_name: " << cur_camera_name;
59 return false;
60 }
61 camera_names_.push_back(cur_camera_name);
62 }
63 // sort camera_names_ by focal lengths (descending order)
64 std::sort(camera_names_.begin(), camera_names_.end(),
65 [&](const std::string& lhs, const std::string& rhs) {
66 const auto lhs_cam_intrinsics =
67 camera_models_[lhs]->get_intrinsic_params();
68 const auto rhs_cam_intrinsics =
69 camera_models_[rhs]->get_intrinsic_params();
70 auto lhs_focal_length =
71 0.5 * (lhs_cam_intrinsics(0, 0) + lhs_cam_intrinsics(1, 1));
72 auto rhs_focal_length =
73 0.5 * (rhs_cam_intrinsics(0, 0) + rhs_cam_intrinsics(1, 1));
74 return lhs_focal_length > rhs_focal_length;
75 });
76 AINFO << "camera_names sorted by descending focal lengths: "
77 << std::accumulate(camera_names_.begin(), camera_names_.end(),
78 std::string(""),
79 [](std::string& sum, const std::string& s) {
80 return sum + s + " ";
81 });
82
83 return true;
84}
85
87 const ProjectOption& option,
88 base::TrafficLight* light) const {
89 if (!HasCamera(option.camera_name)) {
90 AERROR << "no camera: " << option.camera_name;
91 return false;
92 }
93
94 Eigen::Matrix4d c2w_pose;
95
96 if (pose.c2w_poses_.find(option.camera_name) == pose.c2w_poses_.end()) {
97 return false;
98 }
99 c2w_pose = pose.c2w_poses_.at(option.camera_name);
100
101 bool ret = false;
102 AINFO << "project use camera_name: " << option.camera_name;
103 ret = BoundaryBasedProject(camera_models_.at(option.camera_name), c2w_pose,
104 light->region.points, light);
105
106 if (!ret) {
107 AWARN << "Projection failed projection the traffic light. "
108 << "camera_name: " << option.camera_name;
109 return false;
110 }
111 return true;
112}
113
114bool MultiCamerasProjection::HasCamera(const std::string& camera_name) const {
115 auto iter =
116 std::find(camera_names_.begin(), camera_names_.end(), camera_name);
117 return iter != camera_names_.end() &&
118 camera_models_.find(camera_name) != camera_models_.end();
119}
120
122 const std::string& camera_name) const {
123 if (!HasCamera(camera_name)) {
124 AERROR << "getImageWidth failed, camera_name: " << camera_name;
125 return -1;
126 }
127 return static_cast<int>(camera_models_.at(camera_name)->get_width());
128}
129
131 const std::string& camera_name) const {
132 if (!HasCamera(camera_name)) {
133 AERROR << "getImageHeight failed, camera_name: " << camera_name;
134 return -1;
135 }
136 return static_cast<int>(camera_models_.at(camera_name)->get_height());
137}
138
139bool MultiCamerasProjection::BoundaryBasedProject(
140 const base::BrownCameraDistortionModelPtr camera_model,
141 const Eigen::Matrix4d& c2w_pose,
142 const std::vector<base::PointXYZID>& points,
143 base::TrafficLight* light) const {
144 if (camera_model.get() == nullptr) {
145 AERROR << "camera_model is not available.";
146 return false;
147 }
148 int width = static_cast<int>(camera_model->get_width());
149 int height = static_cast<int>(camera_model->get_height());
150 int bound_size = static_cast<int>(points.size());
151 if (bound_size < 4) {
152 AERROR << "invalid bound_size " << bound_size;
153 return false;
154 }
155 EigenVector<Eigen::Vector2i> pts2d(bound_size);
156 auto c2w_pose_inverse = c2w_pose.inverse();
157
158 for (int i = 0; i < bound_size; ++i) {
159 const auto& pt3d_world = points.at(i);
160 Eigen::Vector3d pt3d_cam =
161 (c2w_pose_inverse *
162 Eigen::Vector4d(pt3d_world.x, pt3d_world.y, pt3d_world.z, 1.0))
163 .head(3);
164 if (std::islessequal(pt3d_cam[2], 0.0)) {
165 AWARN << "light bound point behind the car: " << pt3d_cam;
166 return false;
167 }
168 pts2d[i] = camera_model->Project(pt3d_cam.cast<float>()).cast<int>();
169 }
170
171 int min_x = std::numeric_limits<int>::max();
172 int max_x = std::numeric_limits<int>::min();
173 int min_y = std::numeric_limits<int>::max();
174 int max_y = std::numeric_limits<int>::min();
175 for (const auto& pt : pts2d) {
176 min_x = std::min(pt[0], min_x);
177 max_x = std::max(pt[0], max_x);
178 min_y = std::min(pt[1], min_y);
179 max_y = std::max(pt[1], max_y);
180 }
181
182 base::BBox2DI roi(min_x, min_y, max_x, max_y);
183 if (camera::OutOfValidRegion(roi, width, height) || roi.Area() == 0) {
184 AWARN << "Projection get ROI outside the image. ";
185 return false;
186 }
187 light->region.projection_roi = base::RectI(roi);
188 return true;
189}
190
191} // namespace trafficlight
192} // namespace perception
193} // namespace apollo
bool IsSensorExist(const std::string &name) const
std::shared_ptr< BaseCameraDistortionModel > GetDistortCameraModel(const std::string &name) const
EigenMap< std::string, Eigen::Matrix4d > c2w_poses_
Definition pose.h:57
bool Project(const camera::CarPose &pose, const ProjectOption &option, base::TrafficLight *light) const
Boundary projection based on vehicle position and traffic lights.
bool Init(const MultiCamerasInitOption &options)
multicamera project initialization parameters.
bool HasCamera(const std::string &camera_name) const
Determine whether the camera exists.
int getImageWidth(const std::string &camera_name) const
Get the image width object.
int getImageHeight(const std::string &camera_name) const
Get the image height object.
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
#define AWARN
Definition log.h:43
std::vector< EigenType, Eigen::aligned_allocator< EigenType > > EigenVector
Definition eigen_defs.h:33
Rect< int > RectI
Definition box.h:159
std::shared_ptr< BrownCameraDistortionModel > BrownCameraDistortionModelPtr
BBox2D< int > BBox2DI
Definition box.h:163
bool OutOfValidRegion(const base::BBox2D< T > box, const T width, const T height, const T border_size=0)
Definition util.h:74
class register implement
Definition arena_queue.h:37
std::vector< base::PointXYZID > points