Go to the documentation of this file.00001
00002
00003 #include "stereo_disparity.hpp"
00004 #include "feature_match.hpp"
00005
00006 #define MIN_DISPARITY 0
00007
00008 namespace fovis
00009 {
00010
00011 StereoDisparity::StereoDisparity(const StereoCalibration* calib) :
00012 _calib(calib),
00013 _width(calib->getWidth()),
00014 _height(calib->getHeight())
00015 {
00016 _disparity_data = new float[ _width* _height];
00017 _uvd1_to_xyz = new Eigen::Matrix4d(calib->getUvdToXyz());
00018 }
00019
00020 StereoDisparity::~StereoDisparity()
00021 {
00022 delete[] _disparity_data;
00023 delete _uvd1_to_xyz;
00024 }
00025
00026 void
00027 StereoDisparity::setDisparityData(const float* disparity_data)
00028 {
00029
00030 int num_disparity_pixels = _width * _height;
00031 memcpy(_disparity_data, disparity_data, num_disparity_pixels * sizeof(float));
00032 }
00033
00034 bool
00035 StereoDisparity::haveXyz(int u, int v)
00036 {
00037 float disp = _disparity_data[(int) v*_width + (int) u] ;
00038
00039
00040
00041 if (disp == MIN_DISPARITY){
00042 return false;
00043 }
00044 return true;
00045 }
00046
00047 Eigen::Vector3d
00048 StereoDisparity::getXyzValues(int u, int v, float disparity)
00049 {
00050 Eigen::Vector4d uvd1((double) u, (double) v, disparity, 1);
00051 Eigen::Vector4d xyzw = (*_uvd1_to_xyz) * uvd1;
00052 return xyzw.head<3>() / xyzw.w();
00053 }
00054
00055
00056 void
00057 StereoDisparity::getXyz(OdometryFrame * odom_frame)
00058 {
00059 int num_levels = odom_frame->getNumLevels();
00060 for(int level_num=0; level_num < num_levels; ++level_num) {
00061 PyramidLevel* level = odom_frame->getLevel(level_num);
00062 int num_kp = level->getNumKeypoints();
00063
00064
00065 for(int kp_ind=0; kp_ind < num_kp; ++kp_ind) {
00066 KeypointData* kpdata(level->getKeypointData(kp_ind));
00067
00068 int u = (int)(kpdata->rect_base_uv(0)+0.5);
00069 int v = (int)(kpdata->rect_base_uv(1)+0.5);
00070
00071 kpdata->disparity = _disparity_data[(int) v*_width + (int) u];
00072 if (kpdata->disparity == MIN_DISPARITY){
00073 kpdata->disparity = NAN;
00074 kpdata->has_depth = false;
00075 kpdata->xyzw = Eigen::Vector4d(NAN, NAN, NAN, NAN);
00076 kpdata->xyz = Eigen::Vector3d(NAN, NAN, NAN);
00077 } else {
00078 kpdata->has_depth = true;
00079 kpdata->xyz = getXyzValues(u, v, kpdata->disparity);
00080 kpdata->xyzw.head<3>() = kpdata->xyz;
00081 kpdata->xyzw.w() = 1;
00082 }
00083 }
00084 }
00085 }
00086
00087 void
00088 StereoDisparity::refineXyz(FeatureMatch * matches,
00089 int num_matches,
00090 OdometryFrame * odom_frame)
00091 {
00092 for (int m_ind = 0; m_ind < num_matches; m_ind++) {
00093 FeatureMatch& match = matches[m_ind];
00094 if (match.status == MATCH_NEEDS_DEPTH_REFINEMENT) {
00095 if (getXyzInterp(&match.refined_target_keypoint)) {
00096 match.status = MATCH_OK;
00097 } else {
00098 match.status = MATCH_REFINEMENT_FAILED;
00099 match.inlier = false;
00100 }
00101 }
00102 }
00103 }
00104
00105 bool
00106 StereoDisparity::getXyzInterp(KeypointData* kpdata)
00107 {
00108
00109
00110 double _x_scale =1;
00111 double _y_scale =1;
00112 float u_f = kpdata->rect_base_uv(0);
00113 float v_f = kpdata->rect_base_uv(1);
00114 float v_f_d = v_f * _y_scale;
00115 float u_f_d = u_f * _x_scale;
00116 int v = (int)v_f_d;
00117 int u = (int)u_f_d;
00118 float wright = (u_f_d - u);
00119 float wbottom = (v_f_d - v);
00120
00121
00122 assert(u >= 0 && v >= 0 && u < _width - 1 && v < _height - 1);
00123
00124 float w[4] = {
00125 (1 - wright) * (1 - wbottom),
00126 wright * (1 - wbottom),
00127 (1 - wright) * wbottom,
00128 wright * wbottom
00129 };
00130
00131
00132 int index = v * _width + u;
00133 double disparities[4] = {
00134 _disparity_data[index ],
00135 _disparity_data[index + 1],
00136 _disparity_data[index + _width ],
00137 _disparity_data[index + _width + 1]
00138 };
00139 for(int i = 0; i<4; i++){
00140 if( (disparities[i]==MIN_DISPARITY) ){
00141 disparities[i] = NAN;
00142 }
00143 }
00144 int u_vals[4] = {u, u+1, u, u+1};
00145 int v_vals[4] = {v, v, v+1, v+1};
00146
00147
00148 int num_missing_data = 0;
00149 for(int i = 0; i<4; i++)
00150 if(isnan(disparities[i]))
00151 num_missing_data++;
00152
00153 if(num_missing_data == 4) {
00154 return false;
00155 }
00156
00157
00158 if(num_missing_data) {
00159
00160
00161 float wmax = -1;
00162 for(int i=0; i<4; i++) {
00163 if(isnan(disparities[i]) && w[i] > wmax) {
00164 kpdata->xyz = getXyzValues(u_vals[i] , v_vals[i] , disparities[i]);
00165 wmax = w[i];
00166 }
00167 }
00168 } else {
00169 Eigen::Vector3d xyz_combined = Eigen::Vector3d (0.,0.,0.);
00170
00171
00172 for(int i=0; i<4; i++){
00173 Eigen::Vector3d xyz = getXyzValues(u_vals[i] , v_vals[i] , disparities[i]);
00174 xyz_combined= xyz_combined + xyz * w[i];
00175 }
00176 kpdata->xyz = xyz_combined;
00177 }
00178 kpdata->xyzw.head<3>() = kpdata->xyz;
00179 kpdata->xyzw.w() = 1;
00180 return true;
00181 }
00182
00183 }