00001
00024 #include "rgbdtools/rgbd_util.h"
00025
00026 namespace rgbdtools {
00027
00028 void removeInvalidMeans(
00029 const Vector3fVector& means,
00030 const BoolVector& valid,
00031 Vector3fVector& means_f)
00032 {
00033 unsigned int size = valid.size();
00034 for(unsigned int i = 0; i < size; ++i)
00035 {
00036 if (valid[i])
00037 {
00038 const Vector3f& mean = means[i];
00039 means_f.push_back(mean);
00040 }
00041 }
00042 }
00043 Eigen::Matrix4d m4dfromPose(Pose pose)
00044 {
00045 Eigen::Matrix4d pose_;
00046 pose_ << pose(0,0),pose(0,1),pose(0,2),pose(0,3),
00047 pose(1,0),pose(1,1),pose(1,2),pose(1,3),
00048 pose(2,0),pose(2,1),pose(2,2),pose(2,3),
00049 pose(3,0),pose(3,1),pose(3,2),pose(3,3);
00050 return pose_;
00051 }
00052 Pose AffineFromTRPY(double xoffset,double yoffset,double zoffset, double roll,double pitch,double yaw )
00053 {
00054
00055
00056
00057
00058 Pose Tout;
00059 Tout.setIdentity();
00060 Tout = Eigen::Translation<float,3>(xoffset,yoffset,zoffset)*
00061 Eigen::AngleAxis<float>(yaw,Eigen::Vector3f::UnitZ()) *
00062 Eigen::AngleAxis<float>(pitch,Eigen::Vector3f::UnitY()) *
00063 Eigen::AngleAxis<float>(roll,Eigen::Vector3f::UnitX());
00064 return Tout;
00065 }
00066 void removeInvalidDistributions(
00067 const Vector3fVector& means,
00068 const Matrix3fVector& covariances,
00069 const BoolVector& valid,
00070 Vector3fVector& means_f,
00071 Matrix3fVector& covariances_f)
00072 {
00073 unsigned int size = valid.size();
00074 for(unsigned int i = 0; i < size; ++i)
00075 {
00076 if (valid[i])
00077 {
00078 const Vector3f& mean = means[i];
00079 const Matrix3f& cov = covariances[i];
00080
00081 means_f.push_back(mean);
00082 covariances_f.push_back(cov);
00083 }
00084 }
00085 }
00086
00087 void pointCloudFromMeans(
00088 const Vector3fVector& means,
00089 PointCloudFeature& cloud)
00090 {
00091 unsigned int size = means.size();
00092 cloud.points.resize(size);
00093 for(unsigned int i = 0; i < size; ++i)
00094 {
00095 const Vector3f& m = means[i];
00096 PointFeature& p = cloud.points[i];
00097
00098 p.x = m(0,0);
00099 p.y = m(1,0);
00100 p.z = m(2,0);
00101 }
00102
00103 cloud.height = 1;
00104 cloud.width = size;
00105 cloud.is_dense = true;
00106 }
00107
00108
00109 void buildPointCloud(
00110 const cv::Mat& depth_img_rect,
00111 const cv::Mat& intr_rect_ir,
00112 PointCloudT& cloud)
00113 {
00114 int w = depth_img_rect.cols;
00115 int h = depth_img_rect.rows;
00116
00117 double cx = intr_rect_ir.at<double>(0,2);
00118 double cy = intr_rect_ir.at<double>(1,2);
00119 double fx_inv = 1.0 / intr_rect_ir.at<double>(0,0);
00120 double fy_inv = 1.0 / intr_rect_ir.at<double>(1,1);
00121
00122 cloud.resize(w*h);
00123
00124 for (int u = 0; u < w; ++u)
00125 for (int v = 0; v < h; ++v)
00126 {
00127 uint16_t z = depth_img_rect.at<uint16_t>(v, u);
00128 PointT& pt = cloud.points[v*w + u];
00129
00130 if (z != 0)
00131 {
00132 double z_metric = z * 0.001;
00133
00134 pt.x = z_metric * ((u - cx) * fx_inv);
00135 pt.y = z_metric * ((v - cy) * fy_inv);
00136 pt.z = z_metric;
00137 }
00138 else
00139 {
00140 pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN();
00141 }
00142 }
00143
00144 cloud.width = w;
00145 cloud.height = h;
00146 cloud.is_dense = true;
00147 }
00148
00149 void buildPointCloud(
00150 const cv::Mat& depth_img_rect_reg,
00151 const cv::Mat& rgb_img_rect,
00152 const cv::Mat& intr_rect_rgb,
00153 PointCloudT& cloud)
00154 {
00155 int w = rgb_img_rect.cols;
00156 int h = rgb_img_rect.rows;
00157
00158 double cx = intr_rect_rgb.at<double>(0,2);
00159 double cy = intr_rect_rgb.at<double>(1,2);
00160 double fx_inv = 1.0 / intr_rect_rgb.at<double>(0,0);
00161 double fy_inv = 1.0 / intr_rect_rgb.at<double>(1,1);
00162
00163 cloud.resize(w*h);
00164
00165 for (int u = 0; u < w; ++u)
00166 for (int v = 0; v < h; ++v)
00167 {
00168 uint16_t z = depth_img_rect_reg.at<uint16_t>(v, u);
00169 const cv::Vec3b& c = rgb_img_rect.at<cv::Vec3b>(v, u);
00170
00171 PointT& pt = cloud.points[v*w + u];
00172
00173 if (z != 0)
00174 {
00175 double z_metric = z * 0.001;
00176
00177 pt.x = z_metric * ((u - cx) * fx_inv);
00178 pt.y = z_metric * ((v - cy) * fy_inv);
00179 pt.z = z_metric;
00180
00181 pt.r = c[2];
00182 pt.g = c[1];
00183 pt.b = c[0];
00184 }
00185 else
00186 {
00187 pt.x = pt.y = pt.z = std::numeric_limits<float>::quiet_NaN();
00188 }
00189 }
00190
00191 cloud.width = w;
00192 cloud.height = h;
00193 cloud.is_dense = true;
00194 }
00195
00196 void buildRegisteredDepthImage(
00197 const cv::Mat& intr_rect_ir,
00198 const cv::Mat& intr_rect_rgb,
00199 const cv::Mat& ir2rgb,
00200 const cv::Mat& depth_img_rect,
00201 cv::Mat& depth_img_rect_reg)
00202 {
00203 int w = depth_img_rect.cols;
00204 int h = depth_img_rect.rows;
00205
00206 depth_img_rect_reg = cv::Mat::zeros(h, w, CV_16UC1);
00207
00208 cv::Mat intr_rect_ir_inv = intr_rect_ir.inv();
00209
00210
00211 Eigen::Matrix<double, 3, 3> intr_rect_rgb_eigen;
00212 for (int u = 0; u < 3; ++u)
00213 for (int v = 0; v < 3; ++v)
00214 intr_rect_rgb_eigen(v,u) = intr_rect_rgb.at<double>(v, u);
00215
00216
00217 Eigen::Matrix<double, 3, 4> ir2rgb_eigen;
00218 for (int u = 0; u < 4; ++u)
00219 for (int v = 0; v < 3; ++v)
00220 ir2rgb_eigen(v,u) = ir2rgb.at<double>(v, u);
00221
00222
00223 Eigen::Matrix4d intr_rect_ir_inv_eigen;
00224 for (int v = 0; v < 3; ++v)
00225 for (int u = 0; u < 3; ++u)
00226 intr_rect_ir_inv_eigen(v,u) = intr_rect_ir_inv.at<double>(v,u);
00227
00228 intr_rect_ir_inv_eigen(0, 3) = 0;
00229 intr_rect_ir_inv_eigen(1, 3) = 0;
00230 intr_rect_ir_inv_eigen(2, 3) = 0;
00231 intr_rect_ir_inv_eigen(3, 0) = 0;
00232 intr_rect_ir_inv_eigen(3, 1) = 0;
00233 intr_rect_ir_inv_eigen(3, 2) = 0;
00234 intr_rect_ir_inv_eigen(3, 3) = 1;
00235
00236
00237 Eigen::Matrix<double, 3, 4> H_eigen =
00238 intr_rect_rgb_eigen * (ir2rgb_eigen * intr_rect_ir_inv_eigen);
00239
00240
00241
00242 Eigen::Vector3d p_rgb;
00243 Eigen::Vector4d p_depth;
00244
00245 for (int v = 0; v < h; ++v)
00246 for (int u = 0; u < w; ++u)
00247 {
00248 uint16_t z = depth_img_rect.at<uint16_t>(v,u);
00249
00250 if (z != 0)
00251 {
00252 p_depth(0,0) = u * z;
00253 p_depth(1,0) = v * z;
00254 p_depth(2,0) = z;
00255 p_depth(3,0) = 1.0;
00256 p_rgb = H_eigen * p_depth;
00257
00258 double px = p_rgb(0,0);
00259 double py = p_rgb(1,0);
00260 double pz = p_rgb(2,0);
00261
00262 int qu = (int)(px / pz);
00263 int qv = (int)(py / pz);
00264
00265
00266 if (qu < 0 || qu >= w || qv < 0 || qv >= h) continue;
00267
00268 uint16_t& val = depth_img_rect_reg.at<uint16_t>(qv, qu);
00269
00270
00271 if (val == 0 || val > pz) val = pz;
00272 }
00273 }
00274 }
00275
00276 void depthImageFloatTo16bit(
00277 const cv::Mat& depth_image_in,
00278 cv::Mat& depth_image_out)
00279 {
00280 depth_image_in.convertTo(depth_image_out, CV_16UC1, 1000.0);
00281 }
00282
00283 void eigenAffineToOpenCVRt(
00284 const AffineTransform& transform,
00285 cv::Mat& R,
00286 cv::Mat& t)
00287 {
00288
00289 t = cv::Mat(3, 1, CV_64F);
00290 t.at<double>(0,0) = transform(0,3);
00291 t.at<double>(1,0) = transform(1,3);
00292 t.at<double>(2,0) = transform(2,3);
00293
00294
00295 R = cv::Mat(3, 3, CV_64F);
00296 for(int i = 0; i < 3; ++i)
00297 for(int j = 0; j < 3; ++j)
00298 R.at<double>(j,i) = transform(j,i);
00299 }
00300
00301 void openCVRtToEigenAffine(
00302 const cv::Mat& R,
00303 const cv::Mat& t,
00304 AffineTransform& transform)
00305 {
00306
00307 transform(0,3) = t.at<double>(0,0);
00308 transform(1,3) = t.at<double>(1,0);
00309 transform(2,3) = t.at<double>(2,0);
00310
00311
00312 for(int i = 0; i < 3; ++i)
00313 for(int j = 0; j < 3; ++j)
00314 transform(j,i) = R.at<double>(j,i);
00315
00316
00317 transform(3,0) = 0.0;
00318 transform(3,1) = 0.0;
00319 transform(3,2) = 0.0;
00320 transform(3,3) = 1.0;
00321 }
00322
00323 void eigenAffineToXYZRPY(
00324 const AffineTransform& transform,
00325 float& x, float& y, float& z,
00326 float& roll, float& pitch, float& yaw)
00327 {
00328 x = transform(0,3);
00329 y = transform(1,3);
00330 z = transform(2,3);
00331
00332 roll = atan2f(transform(2,1), transform(2,2));
00333 pitch = asinf(-transform(2,0));
00334 yaw = atan2f(transform(1,0), transform(0,0));
00335 }
00336
00337 void XYZRPYToEigenAffine(
00338 float x, float y, float z,
00339 float roll, float pitch, float yaw,
00340 AffineTransform& t)
00341 {
00342 float A=cosf(yaw), B=sinf(yaw), C=cosf(pitch), D=sinf(pitch),
00343 E=cosf(roll), F=sinf(roll), DE=D*E, DF=D*F;
00344 t(0,0) = A*C; t(0,1) = A*DF - B*E; t(0,2) = B*F + A*DE; t(0,3) = x;
00345 t(1,0) = B*C; t(1,1) = A*E + B*DF; t(1,2) = B*DE - A*F; t(1,3) = y;
00346 t(2,0) = -D; t(2,1) = C*F; t(2,2) = C*E; t(2,3) = z;
00347 t(3,0) = 0; t(3,1) = 0; t(3,2) = 0; t(3,3) = 1;
00348 }
00349
00350 void transformMeans(
00351 Vector3fVector& means,
00352 const AffineTransform& transform)
00353 {
00354 Matrix3f R = transform.rotation();
00355 Vector3f t = transform.translation();
00356
00357 unsigned int size = means.size();
00358 for(unsigned int i = 0; i < size; ++i)
00359 {
00360 Vector3f& m = means[i];
00361 m = R * m + t;
00362 }
00363 }
00364
00365 void transformDistributions(
00366 Vector3fVector& means,
00367 Matrix3fVector& covariances,
00368 const AffineTransform& transform)
00369 {
00370 Matrix3f R = transform.rotation();
00371 Vector3f t = transform.translation();
00372 Matrix3f R_T = R.transpose();
00373
00374 unsigned int size = means.size();
00375 for(unsigned int i = 0; i < size; ++i)
00376 {
00377 Vector3f& m = means[i];
00378 Matrix3f& c = covariances[i];
00379 m = R * m + t;
00380 c = R * c * R_T;
00381 }
00382 }
00383
00384 void getTfDifference(
00385 const AffineTransform& transform,
00386 double& dist, double& angle)
00387 {
00388 Matrix3f R = transform.rotation();
00389 Vector3f t = transform.translation();
00390
00391 dist = sqrt(t(0,0)*t(0,0) + t(1,0)*t(1,0) + t(2,0)*t(2,0));
00392
00393 double trace = R(0,0) + R(1,1) + R(2,2);
00394 angle = acos(std::min(1.0, std::max(-1.0, (trace - 1.0)/2.0)));
00395 }
00396
00397 void unwarpDepthImage(
00398 cv::Mat& depth_img,
00399 const cv::Mat& coeff0,
00400 const cv::Mat& coeff1,
00401 const cv::Mat& coeff2,
00402 int fit_mode)
00403 {
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 if (fit_mode == DEPTH_FIT_QUADRATIC)
00417 {
00418 for (int u = 0; u < depth_img.cols; ++u)
00419 for (int v = 0; v < depth_img.rows; ++v)
00420 {
00421 uint16_t d = depth_img.at<uint16_t>(v, u);
00422 if (d != 0)
00423 {
00424 double c0 = coeff0.at<double>(v, u);
00425 double c1 = coeff1.at<double>(v, u);
00426 double c2 = coeff2.at<double>(v, u);
00427
00428 uint16_t res = (int)(c0 + d*(c1 + d*c2));
00429 depth_img.at<uint16_t>(v, u) = res;
00430 }
00431 }
00432 }
00433 else if(fit_mode == DEPTH_FIT_LINEAR)
00434 {
00435 for (int u = 0; u < depth_img.cols; ++u)
00436 for (int v = 0; v < depth_img.rows; ++v)
00437 {
00438 uint16_t d = depth_img.at<uint16_t>(v, u);
00439 if (d != 0)
00440 {
00441 double c0 = coeff0.at<double>(v, u);
00442 double c1 = coeff1.at<double>(v, u);
00443
00444 uint16_t res = (int)(c0 + d*c1);
00445 depth_img.at<uint16_t>(v, u) = res;
00446 }
00447 }
00448 }
00449 else if (fit_mode == DEPTH_FIT_LINEAR_ZERO)
00450 {
00451 cv::Mat temp;
00452 depth_img.convertTo(temp, CV_64FC1);
00453 temp = temp.mul(coeff1);
00454 temp.convertTo(depth_img, CV_16UC1);
00455 }
00456 else if (fit_mode == DEPTH_FIT_QUADRATIC_ZERO)
00457 {
00458 cv::Mat temp;
00459 depth_img.convertTo(temp, CV_64FC1);
00460 temp = temp.mul(coeff1 + temp.mul(coeff2));
00461 temp.convertTo(depth_img, CV_16UC1);
00462 }
00463 }
00464
00465 void setRPY(
00466 float roll, float pitch, float yaw,
00467 Eigen::Matrix3f& m)
00468 {
00469 m = Eigen::AngleAxisf(roll, Eigen::Vector3f::UnitX()) *
00470 Eigen::AngleAxisf(pitch, Eigen::Vector3f::UnitY()) *
00471 Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitZ());
00472 }
00473
00474 }