depth_image.cpp
Go to the documentation of this file.
00001 #include <math.h>
00002 #include <assert.h>
00003 #include "depth_image.hpp"
00004 #include "frame.hpp"
00005 #include "feature_match.hpp"
00006 
00007 namespace fovis
00008 {
00009 
00010 DepthImage::DepthImage(const CameraIntrinsicsParameters& rgb_cam_params,
00011     int depth_width, int depth_height)
00012 {
00013   _rgb_width = rgb_cam_params.width;
00014   _rgb_height = rgb_cam_params.height;
00015 
00016   _depth_width = depth_width;
00017   _depth_height = depth_height;
00018   _x_scale = (float)_depth_width / (float)_rgb_width;
00019   _y_scale = (float)_depth_height / (float)_rgb_height;
00020 
00021   int num_depth_pixels = _depth_width * _depth_height;
00022   _depth_data = new float[num_depth_pixels];
00023 
00024   int num_rgb_pixels = _rgb_width * _rgb_height;
00025   _rays = new Eigen::Matrix<double, 3, Eigen::Dynamic>(3, num_rgb_pixels);
00026 
00027   _fx_inv = 1.0 / rgb_cam_params.fx;
00028   _fy_inv = 1.0 / rgb_cam_params.fy;
00029   _neg_cx_div_fx = - rgb_cam_params.cx * _fx_inv;
00030   _neg_cy_div_fy = - rgb_cam_params.cy * _fy_inv;
00031 
00032   // precompute RGB rays
00033   int rindex = 0;
00034   for(int v=0; v<_rgb_height; v++) {
00035     for(int u=0; u<_rgb_width; u++) {
00036       (*_rays)(0, rindex) = u * _fx_inv + _neg_cx_div_fx;
00037       (*_rays)(1, rindex) = v * _fy_inv + _neg_cy_div_fy;
00038       (*_rays)(2, rindex) = 1;
00039       rindex++;
00040     }
00041   }
00042 }
00043 
00044 DepthImage::~DepthImage()
00045 {
00046   delete[] _depth_data;
00047   delete _rays;
00048 }
00049 
00050 void 
00051 DepthImage::setDepthImage(const float* depth_image)
00052 {
00053   // copy depth image
00054   int num_depth_pixels = _depth_width * _depth_height;
00055   memcpy(_depth_data, depth_image, num_depth_pixels * sizeof(float));
00056 }
00057 
00058 bool
00059 DepthImage::haveXyz(int u, int v)
00060 {
00061   return !isnan(_depth_data[rgbToDepthIndex(u, v)]);
00062 }
00063 
00064 void
00065 DepthImage::getXyz(OdometryFrame * frame) 
00066 {
00067   int num_levels = frame->getNumLevels();
00068   for(int level_num=0; level_num < num_levels; ++level_num) {
00069     PyramidLevel* level = frame->getLevel(level_num);
00070 
00071     int num_kp = level->getNumKeypoints();
00072     for(int kp_ind=0; kp_ind < num_kp; ++kp_ind) {
00073 
00074       KeypointData* kpdata(level->getKeypointData(kp_ind));
00075 
00076       int u = (int)(kpdata->rect_base_uv(0)+0.5);
00077       int v = (int)(kpdata->rect_base_uv(1)+0.5);
00078 
00079       kpdata->disparity = NAN;
00080 
00081       float z = _depth_data[rgbToDepthIndex(u, v)];
00082       if(isnan(z)) {
00083         kpdata->has_depth = false;
00084         kpdata->xyzw = Eigen::Vector4d(NAN, NAN, NAN, NAN);
00085         kpdata->xyz = Eigen::Vector3d(NAN, NAN, NAN);
00086       } else {
00087         kpdata->has_depth = true;
00088         kpdata->xyz = z * _rays->col(v * _rgb_width + u);
00089         kpdata->xyzw.head<3>() = kpdata->xyz;
00090         kpdata->xyzw.w() = 1;
00091       }
00092     }
00093   }
00094 }
00095 
00096 void
00097 DepthImage::refineXyz(FeatureMatch * matches,
00098                            int num_matches,
00099                            OdometryFrame * frame)
00100 {
00101   for (int m_ind = 0; m_ind < num_matches; m_ind++) {
00102     FeatureMatch& match = matches[m_ind];
00103     if (match.status == MATCH_NEEDS_DEPTH_REFINEMENT) {
00104       if (getXyzInterp(&match.refined_target_keypoint)) {
00105         match.status = MATCH_OK;
00106       } else {
00107         match.status = MATCH_REFINEMENT_FAILED;
00108         match.inlier = false;
00109       }
00110     }
00111   }
00112 }
00113 
00114 
00115 bool
00116 DepthImage::getXyzInterp(KeypointData* kpdata)
00117 {
00118   float u_f = kpdata->rect_base_uv(0);
00119   float v_f = kpdata->rect_base_uv(1);
00120   float v_f_d = v_f * _y_scale;
00121   float u_f_d = u_f * _x_scale;
00122   int v = (int)v_f_d;
00123   int u = (int)u_f_d;
00124   float wright  = (u_f_d - u);
00125   float wbottom = (v_f_d - v);
00126 
00127   // can't handle borders
00128   assert(u >= 0 && v >= 0 && u < _depth_width - 1 && v < _depth_height - 1);
00129 
00130   float w[4] = { 
00131     (1 - wright) * (1 - wbottom),
00132     wright * (1 - wbottom),
00133     (1 - wright) * wbottom,
00134     wright * wbottom
00135   };
00136 
00137   int depth_index = v * _depth_width + u;
00138   double depths[4] = {
00139     _depth_data[depth_index + 0],
00140     _depth_data[depth_index + 1],
00141     _depth_data[depth_index + _depth_width],
00142     _depth_data[depth_index + _depth_width + 1]
00143   };
00144 
00145   // missing any depth data for surrounding pixels?
00146   int num_missing_data = 0;
00147   for(int i = 0; i<4; i++)
00148     if(isnan(depths[i]))
00149       num_missing_data++;
00150 
00151   if(num_missing_data == 4) {
00152     // missing all surrounding depth data.
00153     return false;
00154   }
00155 
00156   if(num_missing_data) {
00157     // if any of the surrounding depth data is missing, just clamp to the
00158     // nearest pixel.  interpolation gets messy if we try to do otherwise
00159     float wmax = -1;
00160     double z = NAN;
00161     for(int i=0; i<4; i++) {
00162       if(isnan(depths[i]) && w[i] > wmax) {
00163         z = depths[i];
00164         wmax = w[i];
00165       }
00166     }
00167     kpdata->xyz.x() = z * (u_f * _fx_inv + _neg_cx_div_fx);
00168     kpdata->xyz.y() = z * (v_f * _fy_inv + _neg_cy_div_fy);
00169     kpdata->xyz.z() = z;
00170   } else {
00171     double z = 0;
00172     for(int i=0; i<4; i++)
00173       z += depths[i] * w[i];
00174     kpdata->xyz.x() = z * (u_f * _fx_inv + _neg_cx_div_fx);
00175     kpdata->xyz.y() = z * (v_f * _fy_inv + _neg_cy_div_fy);
00176     kpdata->xyz.z() = z;
00177   }
00178   kpdata->xyzw.head<3>() = kpdata->xyz;
00179   kpdata->xyzw.w() = 1;
00180   return true;
00181 }
00182 
00183 }


libfovis
Author(s): Albert Huang, Maurice Fallon
autogenerated on Thu Jun 6 2019 20:16:12