image.cpp
Go to the documentation of this file.
00001 #include "libhaloc/image.h"
00002 #include "libhaloc/utils.h"
00003 
00006 haloc::Image::Params::Params() :
00007   desc_type("SIFT"),
00008   desc_matching_type("CROSSCHECK"),
00009   desc_thresh_ratio(DEFAULT_DESC_THRESH_RATIO),
00010   min_matches(DEFAULT_MIN_MATCHES),
00011   epipolar_thresh(DEFAULT_EPIPOLAR_THRESH),
00012   b_width(DEFAULT_B_WIDTH),
00013   b_height(DEFAULT_B_HEIGHT),
00014   b_max_features(DEFAULT_B_MAX_FEATURES)
00015 {}
00016 
00019 haloc::Image::Image() {}
00020 
00024 void haloc::Image::setParams(const Params& params)
00025 {
00026   params_ = params;
00027 }
00028 
00029 // Access specifiers
00030 int haloc::Image::getId() { return id_; }
00031 void haloc::Image::setId(int id) { id_ = id; }
00032 vector<KeyPoint> haloc::Image::getKp() { return kp_; }
00033 void haloc::Image::setKp(vector<KeyPoint> kp) { kp_ = kp; }
00034 Mat haloc::Image::getDesc() { return desc_; }
00035 void haloc::Image::setDesc(Mat desc) { desc_ = desc; }
00036 vector<Point3f> haloc::Image::get3D() { return points_3d_; };
00037 void haloc::Image::set3D(vector<Point3f> points_3d) { points_3d_ = points_3d; };
00038 
00039 
00043 void haloc::Image::setCameraModel(image_geometry::StereoCameraModel stereo_camera_model)
00044 {
00045   stereo_camera_model_ = stereo_camera_model;
00046 }
00047 
00053 bool haloc::Image::setMono(int id, const Mat& img)
00054 {
00055   // Reset
00056   kp_.clear();
00057   desc_.release();
00058   id_ = id;
00059 
00060   // Equalize image
00061   Mat img_gs;
00062   cvtColor(img, img_gs, CV_BGR2GRAY);
00063   equalizeHist(img_gs, img_gs);
00064 
00065   // Extract keypoints
00066   vector<KeyPoint> kp;
00067   haloc::Utils::keypointDetector(img_gs, kp, params_.desc_type);
00068 
00069   // Check if the number of kp is enough for the computation of the 3D
00070   if (kp.size() < params_.min_matches)
00071     return false;
00072 
00073   // Extract descriptors
00074   desc_.release();
00075   haloc::Utils::descriptorExtraction(img_gs, kp, desc_, params_.desc_type);
00076 
00077   // Convert kp
00078   kp_.clear();
00079   kp_ = kp;
00080 
00081   return true;
00082 }
00083 
00090 bool haloc::Image::setStereo(int id, const Mat& img_l, const Mat& img_r)
00091 {
00092   // Reset
00093   kp_.clear();
00094   desc_.release();
00095   points_3d_.clear();
00096   id_ = id;
00097 
00098   // Equalize image
00099   Mat img_l_gs, img_r_gs;
00100   cvtColor(img_l, img_l_gs, CV_BGR2GRAY);
00101   cvtColor(img_r, img_r_gs, CV_BGR2GRAY);
00102   equalizeHist(img_l_gs, img_l_gs);
00103   equalizeHist(img_r_gs, img_r_gs);
00104 
00105   // Extract keypoints (left)
00106   vector<KeyPoint> kp_l;
00107   haloc::Utils::keypointDetector(img_l_gs, kp_l, params_.desc_type);
00108 
00109   // Extract descriptors (left)
00110   Mat desc_l;
00111   haloc::Utils::descriptorExtraction(img_l_gs, kp_l, desc_l, params_.desc_type);
00112 
00113   // Extract keypoints (right)
00114   vector<KeyPoint> kp_r;
00115   haloc::Utils::keypointDetector(img_r_gs, kp_r, params_.desc_type);
00116 
00117   // Extract descriptors (right)
00118   Mat desc_r;
00119   haloc::Utils::descriptorExtraction(img_r_gs, kp_r, desc_r, params_.desc_type);
00120 
00121   // Find matches between left and right images
00122   Mat match_mask;
00123   vector<DMatch> matches, matches_filtered;
00124 
00125   if(params_.desc_matching_type == "CROSSCHECK")
00126   {
00127     haloc::Utils::crossCheckThresholdMatching(desc_l,
00128         desc_r, params_.desc_thresh_ratio, match_mask, matches);
00129   }
00130   else if (params_.desc_matching_type == "RATIO")
00131   {
00132     haloc::Utils::ratioMatching(desc_l,
00133         desc_r, params_.desc_thresh_ratio, match_mask, matches);
00134   }
00135   else
00136   {
00137     ROS_ERROR("[Haloc:] ERROR -> desc_matching_type must be 'CROSSCHECK' or 'RATIO'");
00138   }
00139 
00140   // Filter matches by epipolar
00141   for (size_t i = 0; i < matches.size(); ++i)
00142   {
00143     if (abs(kp_l[matches[i].queryIdx].pt.y - kp_r[matches[i].trainIdx].pt.y)
00144         < params_.epipolar_thresh)
00145       matches_filtered.push_back(matches[i]);
00146   }
00147 
00148   // Bucket features
00149   matches_filtered = bucketFeatures(matches_filtered, kp_l);
00150 
00151   // Check if the number of matches is enough for the computation of the 3D
00152   if (matches_filtered.size() < params_.min_matches)
00153     return false;
00154 
00155   // Compute 3D points
00156   vector<KeyPoint> matched_kp_l;
00157   vector<Point3f> matched_3d_points;
00158   Mat matched_desc_l;
00159   for (size_t i=0; i<matches_filtered.size(); ++i)
00160   {
00161     int index_left = matches_filtered[i].queryIdx;
00162     int index_right = matches_filtered[i].trainIdx;
00163     Point3d world_point;
00164     bool valid = haloc::Utils::calculate3DPoint(stereo_camera_model_,
00165                                                 kp_l[index_left].pt,
00166                                                 kp_r[index_right].pt,
00167                                                 0.002,
00168                                                 world_point);
00169 
00170     if (valid)
00171     {
00172       matched_kp_l.push_back(kp_l[index_left]);
00173       matched_desc_l.push_back(desc_l.row(index_left));
00174       matched_3d_points.push_back(world_point);
00175     }
00176   }
00177 
00178   // Save descriptors
00179   desc_ = matched_desc_l;
00180 
00181   // Convert keypoints
00182   kp_.clear();
00183   kp_ = matched_kp_l;
00184 
00185   // Save 3D
00186   points_3d_ = matched_3d_points;
00187 
00188   return true;
00189 }
00190 
00199 vector<DMatch> haloc::Image::bucketFeatures(vector<DMatch> matches,
00200                                             vector<KeyPoint> kp)
00201 {
00202   // Find max values
00203   float x_max = 0;
00204   float y_max = 0;
00205   for (vector<DMatch>::iterator it = matches.begin(); it!=matches.end(); it++)
00206   {
00207     if (kp[it->queryIdx].pt.x > x_max) x_max = kp[it->queryIdx].pt.x;
00208     if (kp[it->queryIdx].pt.y > y_max) y_max = kp[it->queryIdx].pt.y;
00209   }
00210 
00211   // Allocate number of buckets needed
00212   int bucket_cols = (int)floor(x_max/params_.b_width) + 1;
00213   int bucket_rows = (int)floor(y_max/params_.b_height) + 1;
00214   vector<DMatch> *buckets = new vector<DMatch>[bucket_cols*bucket_rows];
00215 
00216   // Assign matches to their buckets
00217   for (vector<DMatch>::iterator it=matches.begin(); it!=matches.end(); it++)
00218   {
00219     int u = (int)floor(kp[it->queryIdx].pt.x/params_.b_width);
00220     int v = (int)floor(kp[it->queryIdx].pt.y/params_.b_height);
00221     buckets[v*bucket_cols+u].push_back(*it);
00222   }
00223 
00224   // Refill matches from buckets
00225   vector<DMatch> output;
00226   for (int i=0; i<bucket_cols*bucket_rows; i++)
00227   {
00228     // Sort descriptors matched by distance
00229     sort(buckets[i].begin(), buckets[i].end(), haloc::Utils::sortDescByDistance);
00230 
00231     // Add up to max_features features from this bucket to output
00232     int k=0;
00233     for (vector<cv::DMatch>::iterator it=buckets[i].begin(); it!=buckets[i].end(); it++)
00234     {
00235       output.push_back(*it);
00236       k++;
00237       if (k >= params_.b_max_features)
00238         break;
00239     }
00240   }
00241   return output;
00242 }


libhaloc
Author(s): Pep Lluis Negre
autogenerated on Thu Jun 6 2019 21:25:00