rgbd_util.cpp
Go to the documentation of this file.
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 //    Right-handed coordinate system (NED: north-east-down) X forward (along default motion of robot) Y right Z down
00055 
00056 //    Rotations are represented using standard Euler angles yaw pitch roll
00057 //    Note that Euler angles transform objects from the global into the local frame of the vehicle: First yaw rotates around Z (changing X and Y axes to X' and Y'), then pitch around the new Y' axis, and finally roll around the new X' axis.
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   // Eigen intr_rect_rgb (3x3)
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   // Eigen rgb2ir_eigen (3x4)
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   // Eigen intr_rect_ir_inv (4x4)
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   // multiply into single (3x4) matrix
00237   Eigen::Matrix<double, 3, 4> H_eigen = 
00238     intr_rect_rgb_eigen * (ir2rgb_eigen * intr_rect_ir_inv_eigen);
00239 
00240   // *** reproject  
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       // skip outside of image 
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       // z buffering
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   // extract translation
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   // extract rotation
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   // extract translation
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   // extract rotation
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   // last row
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   // NOTE: This is slightly faster (5ms vs 4ms)
00406   // BUT images need to be passed as CV_64FC1 or CV_32FC1
00407   // currently the conversion to float messes up 0 <-> nan values
00408   // Alternatively, coeff0 needs to be 0
00409   
00410   cv::Mat temp;
00411   depth_img.convertTo(temp, CV_64FC1);
00412   temp = coeff0 + temp.mul(coeff1 + temp.mul(coeff2));   
00413   temp.convertTo(depth_img, CV_16UC1);
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 } // namespace rgbdtools
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends


lib_rgbdtools
Author(s): Ivan Dryanovski
autogenerated on Tue Aug 27 2013 10:33:54