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