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
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
00056 kp_.clear();
00057 desc_.release();
00058 id_ = id;
00059
00060
00061 Mat img_gs;
00062 cvtColor(img, img_gs, CV_BGR2GRAY);
00063 equalizeHist(img_gs, img_gs);
00064
00065
00066 vector<KeyPoint> kp;
00067 haloc::Utils::keypointDetector(img_gs, kp, params_.desc_type);
00068
00069
00070 if (kp.size() < params_.min_matches)
00071 return false;
00072
00073
00074 desc_.release();
00075 haloc::Utils::descriptorExtraction(img_gs, kp, desc_, params_.desc_type);
00076
00077
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
00093 kp_.clear();
00094 desc_.release();
00095 points_3d_.clear();
00096 id_ = id;
00097
00098
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
00106 vector<KeyPoint> kp_l;
00107 haloc::Utils::keypointDetector(img_l_gs, kp_l, params_.desc_type);
00108
00109
00110 Mat desc_l;
00111 haloc::Utils::descriptorExtraction(img_l_gs, kp_l, desc_l, params_.desc_type);
00112
00113
00114 vector<KeyPoint> kp_r;
00115 haloc::Utils::keypointDetector(img_r_gs, kp_r, params_.desc_type);
00116
00117
00118 Mat desc_r;
00119 haloc::Utils::descriptorExtraction(img_r_gs, kp_r, desc_r, params_.desc_type);
00120
00121
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
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
00149 matches_filtered = bucketFeatures(matches_filtered, kp_l);
00150
00151
00152 if (matches_filtered.size() < params_.min_matches)
00153 return false;
00154
00155
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
00179 desc_ = matched_desc_l;
00180
00181
00182 kp_.clear();
00183 kp_ = matched_kp_l;
00184
00185
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
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
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
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
00225 vector<DMatch> output;
00226 for (int i=0; i<bucket_cols*bucket_rows; i++)
00227 {
00228
00229 sort(buckets[i].begin(), buckets[i].end(), haloc::Utils::sortDescByDistance);
00230
00231
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 }