【机器学习 Opencv】Opencv之Bag of Word模型(三/应用)

BOW其实就是bag of word的缩写,在OpenCV中关于此框架的有3个类。

第一个是一个基类,算是BOW训练的类型,

[cpp]  view plain  copy
  1. class BOWTrainer  
  2. {  
  3. public:  
  4.       BOWTrainer(){}  
  5.       virtual ~BOWTrainer(){}  
  6.   
  7.       void add( const Mat &descriptors);  
  8.       const vector<Mat> &getDescriptors() const;  
  9.       int descriptorsCount() const;  
  10.   
  11.       virtual void clear();  
  12.   
  13.       virtual Mat cluster() const = 0;  
  14.       virtual Mat cluster( const Mat &descriptors );  
  15. protected:  
  16.       …  
  17.  }  

      第二个类别是我们在应用的时候真正的BOW训练的接口类别叫做BOWKmeansTrainer, 此类继承来自BOWTrainer类别

[cpp]  view plain  copy
  1. class BOWKmeansTrainer : public BOWTrainer     
  2. {  
  3. public:  
  4.       BOWKmeansTrainer( int clusterCount, const TermCriteria &termcrit = TermCriteria(),  
  5.                         int attempts = 3, int flags = KMEANS_PP_CENTERS);  
  6.       virtual ~BOWKmeansTrainer(){};  
  7.       virtual Mat cluster() const;  
  8.       virtual Mat cluster( const Mat &descriptors ) const;  
  9.   
  10. protected:  
  11.       …  
  12. }  

      利用此类先定义一个 bowTraining;

[cpp]  view plain  copy
  1. BOWKmeansTrainer bowTraining(1000);   //定义聚类中心1000个,其余的默认参数;  

      然后,将得到的特征,例如SIFT特征,将每一副图的SIFT特征利用add函数加入到bowTraining中去。

[cpp]  view plain  copy
  1. for(int i=0; i<numOfPictures; i++)  
  2.       bowTraining.add( descriptors( i ) );  

      将所有的特征加进去后,就可以进行聚类训练了:

[cpp]  view plain  copy
  1. Mat dictionary = bowTraining.cluster();  //这一步的时间根据特征的维度以及定义的词典中心的个数相关。  

      或者,将得到的特征合并成一个矩阵,这里贴出OpenCVBOW内部合成矩阵的代码

[cpp]  view plain  copy
  1. int descCount = 0;  
  2. forsize_t i = 0; i < descriptors.size(); i++ )  
  3.       descCount += descriptors[i].rows;  
  4. Mat mergedDescriptors( descCount, descriptors[0].cols, descriptors[0].type() );  
  5. forsize_t i = 0, start = 0; i < descriptors.size(); i++ )  
  6. {  
  7.       Mat submut = mergedDescriptors.rowRange((int)start, (int)(start + descriptors[i].rows));  
  8.       descriptors[i].copyTo(submut);  
  9.       start += descriptors[i].rows;  
  10. }  

      同样:

[cpp]  view plain  copy
  1. Mat dictionary = bowTraining.cluster( mergedDescriptors );  

      得到词典后,就要利用另一个类来进行图像BOW特征的提取----BOWImgDescriptorExtractor

[cpp]  view plain  copy
  1. class BOWImgDescriptorExtractor  
  2. {  
  3. public:  
  4.       BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor> &dextractor,   
  5.                                  const Ptr<DescriptorMatcher> & dmatcher );  
  6.       virtual ~BOWImgDescriptorExtractor(){}  
  7.       void setVocabulary( const Mat& vocabulary );  
  8.       const Mat& getVocabulary() const;  
  9.       void compute( const Mat& image, vector<KeyPoint> & keypoints,  
  10.                     Mat& imgDescriptor,  
  11.                     vector<vector<int> >* pointIdxOfClusters = 0,  
  12.                     Mat* descriptors = 0 );  
  13.       int descriptorSize() const;  
  14.       int descriptorType() const;  
  15.   
  16. protected:  
  17.       …  
  18. }  

      利用上面这BOW的第三个类别定义一个变量;

[cpp]  view plain  copy
  1. Ptr<DescriptorExtractor> extractor = DescriptorMatcher::create("SIFT"); //引号里面修改特征种类。  
  2. Ptr<DescriptorMatcher>  matcher = DescriptorExtractor::create("BruteForce"); //引号里面修改匹配类型;  
  3. BOWImgDescriptorExtractor bowDE(extractor, matcher);  

      前面两个定义是为了方便初始化类的定义,在BOW图像特征定义完成后,便可以对每一副图片提取BOW的特征。

[cpp]  view plain  copy
  1. bowDE.setVocabulary(dictionary); //dictionary是通过前面聚类得到的词典;  
  2. for(int i=0; i<numOfPictures; i++)  
  3. {  
  4.       vector<KeyPoint> keypoints;  
  5.       SiftFeatureDetector detector;  
  6.       detector.detect(pictures[i], keypoints);  
  7.       bowDE.compute(pictures[i], keypoints, descriptors);   
  8. }  

      这样,整个BOW特征提取过程就结束了。

猜你喜欢

转载自blog.csdn.net/summer_and_opencv/article/details/74080190