Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 #ifndef sift_des_h_DEFINED
00036 #define sift_des_h_DEFINED
00037 
00038 #include <opencv2/core/core.hpp>
00039 #include <opencv2/imgproc/imgproc.hpp>
00040 #include <opencv2/features2d/features2d.hpp>
00041 #include <opencv2/nonfree/features2d.hpp>
00042 #include <opencv2/ml/ml.hpp>
00043 #include "abstract_feature.h"
00044 #include <vector>
00045 #include <iostream>
00046 #include <sstream>
00047 #include <fstream>
00048 
00049 namespace cpl_visual_features
00050 {
00051 
00052 typedef std::vector<float> SIFTFeature;
00053 typedef std::vector<SIFTFeature> SIFTFeatures;
00054 
00055 template <int x_stride, int y_stride, int n_scales, bool extract_keypoints> class SIFTDes
00056     : public AbstractFeature<std::vector<float> >
00057 {
00058  public:
00059   SIFTDes() : sift_()
00060   {
00061   }
00062 
00063   virtual void operator()(cv::Mat& img, cv::Rect& window)
00064   {
00065     cv::Mat img_bw(img.size(), CV_8UC1);
00066     cv::cvtColor(img, img_bw, CV_RGB2GRAY);
00067     SIFTFeatures raw_feats = extractRawFeatures(img_bw);
00068     descriptor_.clear();
00069     std::vector<float> desc(centers_.size(), 0);
00070     for (unsigned int i = 0; i < raw_feats.size(); ++i)
00071     {
00072       int label = quantizeFeature(raw_feats[i]);
00073       if (label < 0 || label > (int)desc.size())
00074       {
00075         std::cerr << "Quantized label " << label << " out of allowed range!"
00076                   << std::endl;
00077       }
00078       desc[label] += 1.0;
00079     }
00080     descriptor_ = desc;
00081   }
00082 
00083   virtual std::vector<float> getDescriptor() const
00084   {
00085     return descriptor_;
00086   }
00087 
00088   SIFTFeatures getCenters() const
00089   {
00090     return centers_;
00091   }
00092 
00093   SIFTFeatures extractRawFeatures(cv::Mat& frame)
00094   {
00095     SIFTFeatures feats;
00096     for (int s = 0; s < n_scales; ++s)
00097     {
00098       cv::Mat tmp = frame;
00099       if (s > 0)
00100       {
00101         cv::Size down_size;
00102         down_size.width = frame.cols/2;
00103         down_size.height = frame.rows/2;
00104         cv::pyrDown(tmp, frame, down_size);
00105       }
00106       cv::Mat raw_descriptor;
00107 
00108       if (extract_keypoints)
00109       {
00110         std::vector<cv::KeyPoint> cur_keypoints;
00111         sift_(frame, cv::Mat(), cur_keypoints, raw_descriptor, false);
00112       }
00113       else
00114       {
00115         std::vector<cv::KeyPoint> keypoint_locs;
00116         for (int x = 0; x < frame.cols; x += x_stride)
00117         {
00118           for (int y = 0; y < frame.rows; y += y_stride)
00119           {
00120             keypoint_locs.push_back(cv::KeyPoint(x,y,1));
00121           }
00122         }
00123         sift_(frame, cv::Mat(), keypoint_locs, raw_descriptor, true);
00124       }
00125 
00126       for (int r = 0; r < raw_descriptor.rows; ++r)
00127       {
00128         SIFTFeature f;
00129         for (int c = 0; c < raw_descriptor.cols; ++c)
00130         {
00131           f.push_back(raw_descriptor.at<float>(r,c));
00132         }
00133         feats.push_back(f);
00134       }
00135     }
00136     return feats;
00137   }
00138 
00139   SIFTFeatures clusterFeatures(SIFTFeatures samples, int k, int attempts)
00140   {
00141 
00142     
00143     int num_rows = samples.size();
00144     cv::Mat row_samples(num_rows, 128, CV_32FC1);
00145 
00146     for (unsigned int i = 0; i < samples.size(); ++i)
00147     {
00148       for (unsigned int j = 0; j < samples[i].size(); ++j)
00149       {
00150         row_samples.at<float>(i,j) = samples[i][j];
00151       }
00152     }
00153 
00154     
00155     cv::Mat labels;
00156     cv::Mat centers(k, 128, CV_32FC1);
00157     float epsilon = 0.01;
00158     int kmeans_max_iter = 100000;
00159 
00160     double compactness = cv::kmeans(row_samples, k, labels,
00161                                     cv::TermCriteria(CV_TERMCRIT_EPS +
00162                                                      CV_TERMCRIT_ITER,
00163                                                      kmeans_max_iter, epsilon),
00164                                     attempts, cv::KMEANS_PP_CENTERS, centers);
00165 
00166     SIFTFeatures sift_centers;
00167     for (int r = 0; r < centers.rows; ++r)
00168     {
00169       SIFTFeature feat;
00170       for (int c = 0; c < centers.cols; ++c)
00171       {
00172         feat.push_back(centers.at<float>(r,c));
00173       }
00174       sift_centers.push_back(feat);
00175     }
00176 
00177     return sift_centers;
00178   }
00179 
00180   void saveClusterCenters(SIFTFeatures centers, std::string file_name)
00181   {
00182     ROS_INFO_STREAM("Saving SIFT cluster centers to " << file_name.c_str());
00183 
00184     std::ofstream output(file_name.c_str());
00185     for (unsigned int i = 0; i < centers.size(); ++i)
00186     {
00187       for (unsigned int j = 0; j < centers[i].size(); ++j)
00188       {
00189         output << centers[i][j];
00190         if (j < centers[i].size() - 1)
00191           output << " ";
00192       }
00193       output << std::endl;
00194     }
00195 
00196     output.close();
00197   }
00198 
00199   bool loadClusterCenters(std::string file_name)
00200   {
00201     std::ifstream input(file_name.c_str());
00202     if (!input.good())
00203     {
00204       std::cerr << "Failed to open file" << file_name << std::endl;
00205       return false;
00206     }
00207 
00208     
00209     centers_.clear();
00210 
00211     char line[1536];
00212 
00213     
00214     while( input.good() )
00215     {
00216       std::stringstream input_line(std::stringstream::in |
00217                                    std::stringstream::out);
00218       input.getline(line, 1536); 
00219       input_line << line;
00220 
00221       SIFTFeature center;
00222 
00223       
00224       for(int i = 0; i < 128 && !input.eof(); ++i)
00225       {
00226         float val;
00227         input_line >> val;
00228         center.push_back(val);
00229       }
00230       centers_.push_back(center);
00231     }
00232     input.close();
00233 
00234     
00235     
00236     if( centers_.back().size() != centers_[0].size() )
00237     {
00238       centers_.pop_back();
00239     }
00240     return true;
00241   }
00242 
00243   int quantizeFeature(SIFTFeature feat)
00244   {
00245     
00246     float min_val = FLT_MAX;
00247     int min_idx = -1;
00248     for (unsigned int i = 0; i < centers_.size(); ++i)
00249     {
00250       float dist = featureDist(feat, centers_[i]);
00251       if (dist < min_val)
00252       {
00253         min_val = dist;
00254         min_idx = i;
00255       }
00256     }
00257 
00258     return min_idx;
00259   }
00260 
00261   float featureDist(SIFTFeature f1, SIFTFeature f2)
00262   {
00263     
00264     
00265     
00266     float dist = 0.0;
00267 
00268     for (unsigned int i = 0; i < f1.size(); ++i)
00269     {
00270       dist += std::abs(f1[i]-f2[i]);
00271     }
00272 
00273     return dist;
00274   }
00275 
00276  public:
00277   cv::SIFT sift_;
00278 
00279  protected:
00280   std::vector<float> descriptor_;
00281   SIFTFeatures centers_;
00282 };
00283 }
00284 #endif // sift_des_h_DEFINED