RobotsIO
Loading...
Searching...
No Matches
iCubCameraDepth.cpp
1/*
2 * Copyright (C) 2019 Istituto Italiano di Tecnologia (IIT)
3 *
4 * This software may be modified and distributed under the terms of the
5 * BSD 3-Clause license. See the accompanying LICENSE file for details.
6 */
7
8// #ifdef _OPENMP
9// #include <omp.h>
10// #endif
11
12#include <RobotsIO/Camera/iCubCameraDepth.h>
13
14#include <limits>
15#include <opencv2/calib3d.hpp>
16#include <opencv2/core/eigen.hpp>
17#include <opencv2/imgproc.hpp>
18
19using namespace Eigen;
20using namespace RobotsIO::Camera;
21
22
23iCubCameraDepth::iCubCameraDepth
24(
25 const std::string& robot_name,
26 const std::string& port_prefix,
27 const bool& use_calibration,
28 const std::string& calibration_path
29) :
30 iCubCameraRelative(robot_name, port_prefix, use_calibration, calibration_path)
31{
32 configure_sgbm();
33}
34
35
36iCubCameraDepth::iCubCameraDepth
37(
38 const std::string& data_path_left,
39 const std::string& data_path_right,
40 const std::size_t& width,
41 const std::size_t& height,
42 const double& fx_l,
43 const double& cx_l,
44 const double& fy_l,
45 const double& cy_l,
46 const double& fx_r,
47 const double& cx_r,
48 const double& fy_r,
49 const double& cy_r,
50 const bool& load_encoders_data,
51 const bool& use_calibration,
52 const std::string& calibration_path
53) :
54 iCubCameraRelative(data_path_left, data_path_right, width, height, fx_l, cx_l, fy_l, cy_l, fx_r, cx_r, fy_r, cy_r, load_encoders_data, use_calibration, calibration_path)
55{
56 configure_sgbm();
57}
58
59
60iCubCameraDepth::~iCubCameraDepth()
61{}
62
63
64std::pair<bool, Eigen::MatrixXd> iCubCameraDepth::deprojection_matrix() const
65{
66 /* Since the depth is aligned with left camera, the left camera parameters are returned here. */
67 return get_relative_camera().deprojection_matrix();
68}
69
70
71std::pair<bool, Eigen::MatrixXf> iCubCameraDepth::depth(const bool& blocking)
72{
73 /* Get the images. */
74 bool valid_rgb = false;
75 cv::Mat rgb_left;
76 cv::Mat rgb_right;
77 std::tie(valid_rgb, rgb_left) = get_relative_camera().rgb(blocking);
78 if (!valid_rgb)
79 return std::make_pair(false, MatrixXf());
80
81 valid_rgb = false;
82 std::tie(valid_rgb, rgb_right) = iCubCameraRelative::rgb(blocking);
83 if (!valid_rgb)
84 return std::make_pair(false, MatrixXf());
85
86 /* Get the extrinsic matrix. */
87 bool valid_pose = false;
88 Transform<double, 3, Affine> pose;
89 std::tie(valid_pose, pose) = iCubCameraRelative::pose(blocking);
90 if (!valid_pose)
91 return std::make_pair(false, MatrixXf());
92 /* As required by SGBM. */
93 pose = pose.inverse();
94
95 /* Set the extrinsic matrix in OpenCV format. */
96 MatrixXd translation = pose.translation();
97 cv::Mat R;
98 cv::Mat t;
99 cv::eigen2cv(translation, t);
100 cv::eigen2cv(pose.rotation(), R);
101
102 /* Perform rectification. */
103 cv::Mat R1;
104 cv::Mat R2;
105 cv::Mat P1;
106 cv::Mat P2;
107 cv::Mat Q;
108 cv::stereoRectify(intrinsic_left_, distortion_left_,
109 intrinsic_right_, distortion_right_,
110 rgb_left.size(),
111 R, t,
112 R1, R2, P1, P2, Q, -1);
113
114 cv::Mat mapl0;
115 cv::Mat mapl1;
116 cv::Mat mapr0;
117 cv::Mat mapr1;
118 cv::initUndistortRectifyMap(intrinsic_left_, distortion_left_, R1, P1, rgb_left.size(), CV_32FC1, mapl0, mapl1);
119 cv::initUndistortRectifyMap(intrinsic_right_, distortion_right_, R2, P2, rgb_left.size(), CV_32FC1, mapr0, mapr1);
120
121 cv::Mat rgb_left_rect;
122 cv::Mat rgb_right_rect;
123 cv::remap(rgb_left, rgb_left_rect, mapl0, mapl1, cv::INTER_LINEAR);
124 cv::remap(rgb_right, rgb_right_rect, mapr0, mapr1, cv::INTER_LINEAR);
125
126 /* Compute disparity. */
127 cv::Mat disparity;
128 sgbm_->compute(rgb_left_rect, rgb_right_rect, disparity);
129
130 /* Compute mapping from coordinates in the original left image to coordinates in the rectified left image. */
131 cv::Mat map(disparity.rows * disparity.cols, 1, CV_32FC2);
132 for (int v = 0; v < disparity.rows; v++)
133 {
134 for (int u = 0; u < disparity.cols; u++)
135 {
136 map.ptr<float>(v * disparity.cols + u)[0] = float(u);
137 map.ptr<float>(v * disparity.cols + u)[1] = float(v);
138 }
139 }
140 cv::undistortPoints(map, map, intrinsic_left_, distortion_left_, R1, P1);
141
142 /* Store some values required for the next computation. */
143 float q_00 = float(Q.at<double>(0, 0));
144 float q_03 = float(Q.at<double>(0, 3));
145 float q_11 = float(Q.at<double>(1, 1));
146 float q_13 = float(Q.at<double>(1, 3));
147 float q_23 = float(Q.at<double>(2, 3));
148 float q_32 = float(Q.at<double>(3, 2));
149 float q_33 = float(Q.at<double>(3, 3));
150 float r_02 = float(R1.at<double>(0, 2));
151 float r_12 = float(R1.at<double>(1, 2));
152 float r_22 = float(R1.at<double>(2, 2));
153
154 /* Compute depth. */
155 MatrixXf depth(rgb_left.rows, rgb_left.cols);
156// #pragma omp parallel for collapse(2)
157 for (int v = 0; v < rgb_left.rows; v++)
158 for (int u = 0; u < rgb_left.cols; u++)
159 {
160 /* Take coordinates in the rectified image. */
161 float u_map = map.ptr<float>(v * disparity.cols + u)[0];
162 float v_map = map.ptr<float>(v * disparity.cols + u)[1];
163
164 /* Convert to int. */
165 int u_r = cvRound(u_map);
166 int v_r = cvRound(v_map);
167
168 if ((u_r < 0) || (u_r >= disparity.cols) || (v_r < 0) || ( v_r >= disparity.rows))
169 {
170 depth(v, u) = std::numeric_limits<double>::infinity();
171 continue;
172 }
173
174 /* Get disparity. */
175 float disparity_value = disparity.at<short>(v_r, u_r) / 16.0;
176
177 /* Evaluate depth. */
178 depth(v, u) = (r_02 * (float(u_r) * q_00 + q_03) + r_12 * (float(v_r) * q_11 + q_13) + r_22 * q_23) / (disparity_value * q_32 + q_33);
179 }
180
181 return std::make_pair(true, depth);
182}
183
184
185std::pair<bool, Eigen::Transform<double, 3, Eigen::Affine>> iCubCameraDepth::pose(const bool& blocking)
186{
187 /* Since the depth is aligned with left camera, the left camera pose is returned here. */
188 return get_relative_camera().pose(blocking);
189}
190
191
192std::pair<bool, cv::Mat> iCubCameraDepth::rgb(const bool& blocking)
193{
194 /* Since the depth is aligned with left camera, the left image is returned here. */
195 return get_relative_camera().rgb(blocking);
196}
197
198
199void iCubCameraDepth::configure_sgbm()
200{
201 /* Get intrinsic parameters of both cameras .*/
202 bool valid_parameters = false;
203 CameraParameters parameters_left;
204 std::tie(valid_parameters, parameters_left) = get_relative_camera().parameters();
205 if (!valid_parameters)
206 {
207 throw(std::runtime_error(log_name_ + "::configure_sgbm. Error: cannot get intrinsic parameters of left camera."));
208 }
209
210 valid_parameters = false;
211 CameraParameters parameters_right;
212 std::tie(valid_parameters, parameters_right) = parameters();
213 if (!valid_parameters)
214 {
215 throw(std::runtime_error(log_name_ + "::configure_sgbm. Error: cannot get intrinsic parameters of right camera."));
216 }
217
218 /* Configure intrinsics for OpenCV. */
219
220 intrinsic_left_ = cv::Mat::eye(3,3,CV_64FC1);
221 intrinsic_left_.at<double>(0,0) = parameters_left.fx();
222 intrinsic_left_.at<double>(0,2) = parameters_left.cx();
223 intrinsic_left_.at<double>(1,1) = parameters_left.fy();
224 intrinsic_left_.at<double>(1,2) = parameters_left.cy();
225
226 intrinsic_right_ = cv::Mat::eye(3,3,CV_64FC1);
227 intrinsic_right_.at<double>(0,0) = parameters_right.fx();
228 intrinsic_right_.at<double>(0,2) = parameters_right.cx();
229 intrinsic_right_.at<double>(1,1) = parameters_right.fy();
230 intrinsic_right_.at<double>(1,2) = parameters_right.cy();
231
232 /* Configure distortion for OpenCV.
233 We expect that the images are already undistorted. */
234 distortion_left_ = cv::Mat::zeros(1,8,CV_64FC1);
235 distortion_left_.at<double>(0,0) = 0.0;
236 distortion_left_.at<double>(0,1) = 0.0;
237 distortion_left_.at<double>(0,2) = 0.0;
238 distortion_left_.at<double>(0,3) = 0.0;
239
240 distortion_right_ = cv::Mat::zeros(1,8,CV_64FC1);
241 distortion_right_.at<double>(0,0) = 0.0;
242 distortion_right_.at<double>(0,1) = 0.0;
243 distortion_right_.at<double>(0,2) = 0.0;
244 distortion_right_.at<double>(0,3) = 0.0;
245
246 /* Initialize OpenCV SGBM. */
247 sgbm_ = cv::StereoSGBM::create(min_disparity_, number_of_disparities_, block_size_, 8 * 3 * block_size_ * block_size_, 32 * 3 * block_size_ * block_size_, disp_12_max_diff_, pre_filter_cap_, uniqueness_ratio_, speckle_window_size_, speckle_range_, cv::StereoSGBM::MODE_HH);
248}
virtual std::pair< bool, Eigen::MatrixXd > deprojection_matrix() const
Definition: Camera.cpp:53
std::pair< bool, Eigen::MatrixXd > deprojection_matrix() const override
std::pair< bool, Eigen::MatrixXf > depth(const bool &blocking) override
std::pair< bool, Eigen::Transform< double, 3, Eigen::Affine > > pose(const bool &blocking) override