00001 /* 00002 * feature_utils.cpp 00003 * 00004 * Created on: Oct 17, 2010 00005 * Author: ethan 00006 */ 00007 00008 #include <pano_core/feature_utils.h> 00009 #include <iostream> 00010 using namespace cv; 00011 using namespace std; 00012 namespace pano 00013 { 00014 00015 00016 void GriddedDynamicDetectorAdaptor::detectImpl(const Mat &image, vector<KeyPoint> &keypoints, const Mat &mask) const 00017 { 00018 keypoints.clear(); 00019 keypoints.reserve(maxTotalKeypoints); 00020 00021 for (int i = 0; i < gridRows; ++i) 00022 { 00023 Range row_range((i * image.rows) / gridRows, ((i + 1) * image.rows) / gridRows); 00024 for (int j = 0; j < gridCols; ++j) 00025 { 00026 Range col_range((j * image.cols) / gridCols, ((j + 1) * image.cols) / gridCols); 00027 Mat sub_image = image(row_range, col_range); 00028 Mat sub_mask; 00029 if (!mask.empty()) 00030 sub_mask = mask(row_range, col_range); 00031 00032 vector<KeyPoint> sub_keypoints; 00033 detectors_[i * gridCols + j]->detect(sub_image, sub_keypoints, sub_mask); 00034 00035 for (std::vector<cv::KeyPoint>::iterator it = sub_keypoints.begin(), end = sub_keypoints.end(); it != end; ++it) 00036 { 00037 it->pt.x += col_range.start; 00038 it->pt.y += row_range.start; 00039 } 00040 00041 keypoints.insert(keypoints.end(), sub_keypoints.begin(), sub_keypoints.end()); 00042 } 00043 } 00044 } 00045 00046 void KeyPointsToPoints(const KeypointVector& keypts, std::vector<cv::Point2f>& pts) 00047 { 00048 pts.clear(); 00049 pts.reserve(keypts.size()); 00050 for (size_t i = 0; i < keypts.size(); i++) 00051 { 00052 pts.push_back(keypts[i].pt); 00053 } 00054 } 00055 00056 void PointsToKeyPoints(const std::vector<cv::Point2f>& pts, KeypointVector& kpts) 00057 { 00058 kpts.clear(); 00059 kpts.reserve(pts.size()); 00060 for (size_t i = 0; i < pts.size(); i++) 00061 { 00062 kpts.push_back(KeyPoint(pts[i], 6.0)); 00063 } 00064 } 00065 00066 void matches2points(const KeypointVector& train, const KeypointVector& query, const MatchesVector& matches, 00067 std::vector<cv::Point2f>& pts_train, std::vector<Point2f>& pts_query) 00068 { 00069 00070 pts_train.clear(); 00071 pts_query.clear(); 00072 pts_train.reserve(matches.size()); 00073 pts_query.reserve(matches.size()); 00074 00075 size_t i = 0; 00076 00077 for (; i < matches.size(); i++) 00078 { 00079 00080 const DMatch & dmatch = matches[i]; 00081 00082 if(dmatch.queryIdx > int( query.size()) || dmatch.trainIdx < 0){ 00083 std::cerr << "bad index , query:" << dmatch.queryIdx << std::endl; 00084 continue; 00085 } 00086 if(dmatch.trainIdx > int( train.size()) || dmatch.trainIdx < 0){ 00087 std::cerr << "bad index ,train:" << dmatch.trainIdx << std::endl; 00088 continue; 00089 } 00090 pts_query.push_back(query[dmatch.queryIdx].pt); 00091 pts_train.push_back(train[dmatch.trainIdx].pt); 00092 00093 } 00094 00095 } 00096 00097 } 00098 00099 00101 // * shift params to get desired number of features 00102 // */ 00103 //template<typename Adjuster> 00104 //class DynamicDetectorAdaptor: public cv::FeatureDetector { 00105 //public: 00106 // 00107 // DynamicDetectorAdaptor(int min_features = 400, int max_features = 600, 00108 // int max_iters = 4, const Adjuster& a = Adjuster()) : 00109 // escape_iters_(max_iters), min_features_(min_features), max_features_( 00110 // max_features), adjuster_(a) { 00111 // } 00112 //protected: 00113 // virtual void detectImpl(const cv::Mat& image, 00114 // std::vector<cv::KeyPoint>& keypoints, const cv::Mat& mask = 00115 // cv::Mat()) const { 00116 // //for oscillation testing 00117 // bool down = false; 00118 // bool up = false; 00119 // 00120 // //flag for whether the correct threshhold has been reached 00121 // bool thresh_good = false; 00122 // 00123 // //this is bad but adjuster should persist from detection to detection 00124 // Adjuster& adjuster = const_cast<Adjuster&> (adjuster_); 00125 // 00126 // //break if the desired number hasn't been reached. 00127 // int iter_count = escape_iters_; 00128 // 00129 // do { 00130 // keypoints.clear(); 00131 // 00132 // //the adjuster takes care of calling the detector with updated parameters 00133 // adjuster.detect(image, mask, keypoints); 00134 // 00135 // if (int(keypoints.size()) < min_features_) { 00136 // down = true; 00137 // adjuster.tooFew(min_features_, keypoints.size()); 00138 // } else if (int(keypoints.size()) > max_features_) { 00139 // up = true; 00140 // adjuster.tooMany(max_features_, keypoints.size()); 00141 // } else 00142 // thresh_good = true; 00143 // } while (--iter_count >= 0 && !(down && up) && !thresh_good 00144 // && adjuster.good()); 00145 // } 00146 // 00147 //private: 00148 // int escape_iters_; 00149 // int min_features_, max_features_; 00150 // Adjuster adjuster_; 00151 //}; 00152 // 00153 //struct FastAdjuster { 00154 // FastAdjuster() : 00155 // thresh_(20) { 00156 // } 00157 // void detect(const cv::Mat& img, const cv::Mat& mask, std::vector< 00158 // cv::KeyPoint>& keypoints) const { 00159 // cv::FastFeatureDetector(thresh_, true).detect(img, keypoints, mask); 00160 // } 00161 // void tooFew(int min, int n_detected) { 00162 // //fast is easy to adjust 00163 // thresh_--; 00164 // } 00165 // void tooMany(int max, int n_detected) { 00166 // //fast is easy to adjust 00167 // thresh_++; 00168 // } 00169 // 00170 // //return whether or not the threshhold is beyond 00171 // //a useful point 00172 // bool good() const { 00173 // return (thresh_ > 1) && (thresh_ < 200); 00174 // } 00175 // int thresh_; 00176 //}; 00177 // 00178 //struct StarAdjuster { 00179 // StarAdjuster() : 00180 // thresh_(30) { 00181 // } 00182 // void detect(const cv::Mat& img, const cv::Mat& mask, std::vector< 00183 // cv::KeyPoint>& keypoints) const { 00184 // cv::StarFeatureDetector detector_tmp(16, thresh_, 10, 8, 3); 00185 // detector_tmp.detect(img, keypoints, mask); 00186 // } 00187 // void tooFew(int min, int n_detected) { 00188 // thresh_ *= 0.9; 00189 // if (thresh_ < 1.1) 00190 // thresh_ = 1.1; 00191 // } 00192 // void tooMany(int max, int n_detected) { 00193 // thresh_ *= 1.1; 00194 // } 00195 // 00196 // //return whether or not the threshhold is beyond 00197 // //a useful point 00198 // bool good() const { 00199 // return (thresh_ > 2) && (thresh_ < 200); 00200 // } 00201 // double thresh_; 00202 //}; 00203 // 00204 //struct SurfAdjuster { 00205 // SurfAdjuster() : 00206 // thresh_(400.0) { 00207 // } 00208 // void detect(const cv::Mat& img, const cv::Mat& mask, std::vector< 00209 // cv::KeyPoint>& keypoints) const { 00210 // cv::SurfFeatureDetector detector_tmp(thresh_); 00211 // detector_tmp.detect(img, keypoints, mask); 00212 // } 00213 // void tooFew(int min, int n_detected) { 00214 // thresh_ *= 0.9; 00215 // if (thresh_ < 1.1) 00216 // thresh_ = 1.1; 00217 // } 00218 // void tooMany(int max, int n_detected) { 00219 // thresh_ *= 1.1; 00220 // } 00221 // 00222 // //return whether or not the threshhold is beyond 00223 // //a useful point 00224 // bool good() const { 00225 // return (thresh_ > 2) && (thresh_ < 1000); 00226 // } 00227 // double thresh_; 00228 //}; 00229 // 00230 //typedef DynamicDetectorAdaptor<FastAdjuster> FASTDynamicDetector; 00231 //typedef DynamicDetectorAdaptor<StarAdjuster> StarDynamicDetector; 00232 //typedef DynamicDetectorAdaptor<SurfAdjuster> SurfDynamicDetector;