primesense_depth.cpp
Go to the documentation of this file.
00001 #include <assert.h>
00002 
00003 #include "primesense_depth.hpp"
00004 
00005 #include "frame.hpp"
00006 #include "pyramid_level.hpp"
00007 
00008 namespace fovis
00009 {
00010 
00011 PrimeSenseCalibration::PrimeSenseCalibration(const PrimeSenseCalibrationParameters& params) :
00012   params(params)
00013 {
00014   rgb_rectification = new Rectification(params.rgb_params);
00015 }
00016 
00017 PrimeSenseCalibration::~PrimeSenseCalibration()
00018 {
00019   delete rgb_rectification;
00020 }
00021 
00022 PrimeSenseDepth::PrimeSenseDepth(const PrimeSenseCalibration* calib)
00023 {
00024   _calib = calib;
00025   _ir_width = _calib->getParameters().depth_params.width;
00026   _ir_height = _calib->getParameters().depth_params.height;
00027 
00028   assert(_ir_width >= 0 && _ir_height >= 0 && _ir_width < 100000 && _ir_height < 100000);
00029 
00030   _disparity_map_max_index = _ir_width * _ir_height - 1;
00031   _disparity = (uint16_t*) malloc(_ir_width * _ir_height * sizeof(uint16_t) + 2);
00032   // The entry at the end of the disparity buffer
00033   // is a placeholder for uninitialized disparity values.
00034   // It should be greater than any possible disparity so
00035   // that it will get replaced.
00036   _disparity[_disparity_map_max_index+1] = 10000;
00037   _rgb_to_disparity_map = (uint32_t*) malloc(_ir_width * _ir_height * sizeof(uint32_t));
00038   _uvd1_d_to_xyz_c = new Eigen::Matrix4d(_calib->getDepthUvdToRgbXyz());
00039 
00040 }
00041 
00042 PrimeSenseDepth::~PrimeSenseDepth()
00043 {
00044   delete _uvd1_d_to_xyz_c;
00045   free(_disparity);
00046   free(_rgb_to_disparity_map);
00047 }
00048 
00049 void
00050 PrimeSenseDepth::setDisparityData(const uint16_t* disparity)
00051 {
00052   // copy disparity image
00053   std::copy(disparity, disparity+_ir_width * _ir_height, _disparity);
00054 
00055   // initialize the rgb->disparity map
00056   std::fill(_rgb_to_disparity_map,
00057             _rgb_to_disparity_map+(_ir_width * _ir_height)+1,
00058             (_ir_width * _ir_height));
00059 
00060   // == compute RGB pixel coordinates for every pixel in the depth image ==
00061 
00062   Eigen::Matrix<double, 3, 4> depth_to_rgb_uvd = _calib->getDepthUvdToRgbUvw();
00063   uint16_t min_disparity = 0;
00064   uint16_t max_disparity = 2046;
00065 
00066   for(int v_disp=0; v_disp<_ir_height; v_disp++) {
00067     for(int u_disp=0; u_disp<_ir_width; u_disp++) {
00068       int disparity_index = v_disp * _ir_width + u_disp;
00069       uint16_t disparity = _disparity[disparity_index];
00070 
00071       if(disparity > max_disparity || disparity < min_disparity)
00072         continue;
00073 
00074       // compute homogeneous coordinates of matching RGB pixel
00075       Eigen::Vector4d uvd_depth(u_disp, v_disp, disparity, 1);
00076       Eigen::Vector3d uvd_rgb = depth_to_rgb_uvd * uvd_depth;
00077 
00078       // normalize to Euclidean coordinates and round off to the nearest pixel.
00079       if (uvd_rgb[0] < 0 || uvd_rgb[1] < 0 || uvd_rgb[2] <= 0)
00080         continue ;
00081 
00082       int u_rgb = uvd_rgb[0] / uvd_rgb[2] + 0.5;
00083       if(u_rgb >= _ir_width)
00084           continue;
00085 
00086       int v_rgb = uvd_rgb[1] / uvd_rgb[2] + 0.5;
00087       if(v_rgb >= _ir_height)
00088           continue;
00089 
00090       int rgb_index = v_rgb * _ir_width + u_rgb;
00091       uint32_t disparity_index_old = _rgb_to_disparity_map[rgb_index];
00092       if(disparity < _disparity[disparity_index_old]) {
00093         _rgb_to_disparity_map[rgb_index] = disparity_index;
00094       }
00095     }
00096   }
00097 }
00098 
00099 void
00100 PrimeSenseDepth::getXyz(OdometryFrame * frame)
00101 {
00102   int num_levels = frame->getNumLevels();
00103   for(int level_num=0; level_num < num_levels; ++level_num) {
00104     PyramidLevel* level = frame->getLevel(level_num);
00105 
00106     int num_kp = level->getNumKeypoints();
00107     for(int kp_ind=0; kp_ind < num_kp; ++kp_ind) {
00108 
00109       KeypointData* kpdata(level->getKeypointData(kp_ind));
00110       getXyzFast(kpdata);
00111     }
00112   }
00113 }
00114 
00115 void
00116 PrimeSenseDepth::refineXyz(FeatureMatch * matches,
00117                            int num_matches,
00118                            OdometryFrame * frame)
00119 {
00120   for (int m_ind = 0; m_ind < num_matches; m_ind++) {
00121     FeatureMatch& match = matches[m_ind];
00122     if (match.status == MATCH_NEEDS_DEPTH_REFINEMENT) {
00123       if (getXyzInterp(&match.refined_target_keypoint)) {
00124         match.status = MATCH_OK;
00125       } else {
00126         match.status = MATCH_REFINEMENT_FAILED;
00127         match.inlier = false;
00128       }
00129     }
00130   }
00131 }
00132 
00133 #if 0
00134 bool
00135 PrimeSenseDepth::haveXyz(float u_f, float v_f)
00136 {
00137   int v = (int)v_f;
00138   int u = (int)u_f;
00139 
00140   if(u < 0 || v < 0 || u >= _ir_width - 1 || v >= _ir_height - 1)
00141     return false;
00142 
00143   int ra_index = v * _ir_width + u;
00144   uint32_t neighbor_disparity_indices[4] = {
00145     _rgb_to_disparity_map[ra_index],
00146     _rgb_to_disparity_map[ra_index + 1],
00147     _rgb_to_disparity_map[ra_index + _ir_width],
00148     _rgb_to_disparity_map[ra_index + _ir_width + 1]
00149   };
00150 
00151   // depth data for surrounding pixels?
00152   for(int i = 0; i<4; i++)
00153     if(neighbor_disparity_indices[i] < _disparity_map_max_index)
00154       return true;
00155 
00156   return false;
00157 }
00158 #endif
00159 
00160 bool
00161 PrimeSenseDepth::getXyz(int u, int v, Eigen::Vector3d & xyz)
00162 {
00163   u = (int)(u+0.5);
00164   v = (int)(v+0.5);
00165 
00166   int rgb_index = v * _ir_width + u;
00167   uint32_t disparity_index = _rgb_to_disparity_map[rgb_index];
00168   if(disparity_index > _disparity_map_max_index) {
00169     return false;
00170   }
00171 
00172   uint16_t disparity = _disparity[disparity_index];
00173   if(disparity > 2046) { // TODO account for shadow values?
00174     return false;
00175   }
00176 
00177   int u_disp = disparity_index % _ir_width;
00178   int v_disp = disparity_index / _ir_width;
00179 
00180   // compute feature Cartesian coordinates
00181   Eigen::Vector4d xyzw = (*_uvd1_d_to_xyz_c) * Eigen::Vector4d(u_disp, v_disp, disparity, 1);
00182   xyz = xyzw.head<3>() / xyzw.w();
00183 
00184   assert(!isnan(xyz(0)) && !isnan(xyz(1)) && !isnan(xyz(2)));
00185 
00186   return true;
00187 }
00188 
00189 bool
00190 PrimeSenseDepth::getXyzFast(KeypointData* kpdata)
00191 {
00192   int u = (int)(kpdata->rect_base_uv(0)+0.5);
00193   int v = (int)(kpdata->rect_base_uv(1)+0.5);
00194 
00195   int rgb_index = v * _ir_width + u;
00196   uint32_t disparity_index = _rgb_to_disparity_map[rgb_index];
00197   if(disparity_index > _disparity_map_max_index) {
00198     kpdata->has_depth = false;
00199     kpdata->xyzw = Eigen::Vector4d(NAN, NAN, NAN, NAN);
00200     kpdata->xyz = Eigen::Vector3d(NAN, NAN, NAN);
00201     kpdata->disparity = NAN;
00202     return false;
00203   }
00204 
00205   uint16_t disparity = _disparity[disparity_index];
00206   if(disparity > 2046) { // TODO account for shadow values?
00207     kpdata->has_depth = false;
00208     kpdata->xyzw = Eigen::Vector4d(NAN, NAN, NAN, NAN);
00209     kpdata->xyz = Eigen::Vector3d(NAN, NAN, NAN);
00210     kpdata->disparity = NAN;
00211     return false;
00212   }
00213 
00214   int u_disp = disparity_index % _ir_width;
00215   int v_disp = disparity_index / _ir_width;
00216 
00217   // compute feature Cartesian coordinates
00218   Eigen::Vector4d uvd_depth(u_disp, v_disp, disparity, 1);
00219   kpdata->xyzw = (*_uvd1_d_to_xyz_c) * uvd_depth;
00220   kpdata->xyz = kpdata->xyzw.head<3>() / kpdata->xyzw.w();
00221   kpdata->has_depth = true;
00222   kpdata->disparity = disparity;
00223 
00224   assert(!isnan(kpdata->xyz(0)) && !isnan(kpdata->xyz(1)) && !isnan(kpdata->xyz(2)));
00225 
00226   return true;
00227 }
00228 
00229 bool
00230 PrimeSenseDepth::getXyzInterp(KeypointData* kpdata)
00231 {
00232   float u_f = kpdata->rect_base_uv(0);
00233   float v_f = kpdata->rect_base_uv(1);
00234   int v = (int)v_f;
00235   int u = (int)u_f;
00236   float wright  = (u_f - u);
00237   float wbottom = (v_f - v);
00238 
00239   // can't handle borders
00240   assert(u >= 0 && v >= 0 && u < _ir_width - 1 && v < _ir_height - 1);
00241 
00242   float w[4] = {
00243     (1 - wright) * (1 - wbottom),
00244     wright * (1 - wbottom),
00245     (1 - wright) * wbottom,
00246     wright * wbottom
00247   };
00248 
00249   int ra_index = v * _ir_width + u;
00250   uint32_t neighbor_disparity_indices[4] = {
00251     _rgb_to_disparity_map[ra_index],
00252     _rgb_to_disparity_map[ra_index + 1],
00253     _rgb_to_disparity_map[ra_index + _ir_width],
00254     _rgb_to_disparity_map[ra_index + _ir_width + 1]
00255   };
00256 
00257   // missing any depth data for surrounding pixels?
00258   int num_missing_data = 0;
00259   for(int i = 0; i<4; i++)
00260     if(neighbor_disparity_indices[i] >= _disparity_map_max_index)
00261       num_missing_data++;
00262 
00263   if(num_missing_data == 4) {
00264     // missing all surrounding depth data.
00265     kpdata->xyzw = Eigen::Vector4d(NAN, NAN, NAN, NAN);
00266     kpdata->xyz = Eigen::Vector3d(NAN, NAN, NAN);
00267     kpdata->disparity = NAN;
00268     return false;
00269   }
00270 
00271   // if any of the surrounding depth data is missing, just clamp to the
00272   // nearest pixel.  interpolation gets messy if we try to do otherwise
00273   if(num_missing_data) {
00274     float wmax = -1;
00275     int wmax_disparity_ind = -1;
00276     for(int i=0; i<4; i++) {
00277       if(neighbor_disparity_indices[i] < _disparity_map_max_index &&
00278           w[i] > wmax) {
00279         wmax_disparity_ind = i;
00280         wmax = w[i];
00281       }
00282     }
00283     int v = wmax_disparity_ind / _ir_width;
00284     int u = wmax_disparity_ind % _ir_width;
00285     uint16_t disparity = _disparity[wmax_disparity_ind];
00286     Eigen::Vector4d uvd1_d(u, v, disparity, 1);
00287     kpdata->xyzw = (*_uvd1_d_to_xyz_c) * uvd1_d;
00288     kpdata->disparity = disparity;
00289   } else {
00290     Eigen::Vector4d uvd1(0, 0, 0, 1);
00291     for(int i=0; i<4; i++) {
00292       int nu = neighbor_disparity_indices[i] % _ir_width;
00293       int nv = neighbor_disparity_indices[i] / _ir_width;
00294       int ndisparity = _disparity[neighbor_disparity_indices[i]];
00295       uvd1(0) += w[i] * nu;
00296       uvd1(1) += w[i] * nv;
00297       uvd1(2) += w[i] * ndisparity;
00298     }
00299     kpdata->xyzw = (*_uvd1_d_to_xyz_c) * uvd1;
00300     kpdata->disparity = uvd1(2);
00301   }
00302   kpdata->xyz = kpdata->xyzw.head<3>() / kpdata->xyzw.w();
00303   return true;
00304 }
00305 
00306 }


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