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