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
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
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
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
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
00153 return false;
00154 }
00155
00156 if(num_missing_data) {
00157
00158
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 }