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
00033
00034
00035
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
00053 std::copy(disparity, disparity+_ir_width * _ir_height, _disparity);
00054
00055
00056 std::fill(_rgb_to_disparity_map,
00057 _rgb_to_disparity_map+(_ir_width * _ir_height)+1,
00058 (_ir_width * _ir_height));
00059
00060
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
00075 Eigen::Vector4d uvd_depth(u_disp, v_disp, disparity, 1);
00076 Eigen::Vector3d uvd_rgb = depth_to_rgb_uvd * uvd_depth;
00077
00078
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
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) {
00174 return false;
00175 }
00176
00177 int u_disp = disparity_index % _ir_width;
00178 int v_disp = disparity_index / _ir_width;
00179
00180
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) {
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
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
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
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
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
00272
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 }