OpenCV应用----BOW篇

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

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

      class BOWTrainer

      {

      public:

            BOWTrainer(){}

            virtual ~BOWTrainer(){}

 

            void add( const Mat &descriptors);

            const vector<Mat> &getDescriptors() const;

            int descriptorsCount() const;

 

            virtual void clear();

 

            virtual Mat cluster() const = 0;

            virtual Mat cluster( const Mat &descriptors );

      protected:

            …

      }

 

      第二个类别是我们在应用的时候真正的BOW训练的接口类别叫做BOWKmeansTrainer, 此类继承来自 BOWTrainer类别(不知道这么说对不对,C++还在学习中)

      class BOWKmeansTrainer : public BOWTrainer   

      {

      public:

            BOWKmeansTrainer( int clusterCount, const TermCriteria &termcrit = TermCriteria(),

                              int attempts = 3, int flags = KMEANS_PP_CENTERS);

            virtual ~BOWKmeansTrainer(){};

            virtual Mat cluster() const;

            virtual Mat cluster( const Mat &descriptors ) const;

 

      protected:

            …

      }

      利用此类先定义一个 bowTraining;

      BOWKmeansTrainer bowTraining(1000);   //定义聚类中心1000个,其余的默认参数;

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

      for(int i=0; i<numOfPictures; i++)

            bowTraining.add( descriptors( i ) );

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

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

 

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

      int descCount = 0;
      for( size_t i = 0; i < descriptors.size(); i++ )
            descCount += descriptors[i].rows;

      Mat mergedDescriptors( descCount, descriptors[0].cols, descriptors[0].type() );
      for( size_t i = 0, start = 0; i < descriptors.size(); i++ )
      {
            Mat submut = mergedDescriptors.rowRange((int)start, (int)(start +                                                                          descriptors[i].rows));
            descriptors[i].copyTo(submut);
            start += descriptors[i].rows;
      }

      同样:Mat dictionary = bowTraining.cluster( mergedDescriptors );

 

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

      class BOWImgDescriptorExtractor

      {

      public:

      BOWImgDescriptorExtractor( const Ptr<DescriptorExtractor> &dextractor,                                                        const Ptr<DescriptorMatcher> & dmatcher );

      virtual ~BOWImgDescriptorExtractor(){}

      void setVocabulary( const Mat& vocabulary );

      const Mat& getVocabulary() const;

      void compute( const Mat& image, vector<KeyPoint> & keypoints,

                    Mat& imgDescriptor,

                    vector<vector<int> >* pointIdxOfClusters = 0,

                    Mat* descriptors = 0 );

      int descriptorSize() const;

      int descriptorType() const;

 

      protected:

      …

      }

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

      Ptr<DescriptorExtractor> extractor = DescriptorMatcher::create("SIFT"); //引号里面修改特征种类。

      Ptr<DescriptorMatcher>  matcher = DescriptorExtractor::create("BruteForce"); //引号里面修改匹配类型;

      BOWImgDescriptorExtractor bowDE(extractor, matcher);

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

      bowDE.setVocabulary(dictionary); //dictionary是通过前面聚类得到的词典;

      for(int i=0; i<numOfPictures; i++)

      {

            vector<KeyPoint> keypoints;

            SiftFeatureDetector detector;

            detector.detect(pictures[i], keypoints);

            bowDE.compute(pictures[i], keypoints, descriptors); 

      }

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

你可能感兴趣的:(opencv)