基于OpenCV的BOW特征提取
来源:互联网 发布:python jenkins api 编辑:程序博客网 时间:2024/05/17 22:49
1. 前言
在OpenCV中使用SIFT特征提取算子进行特征提取是跟简单的事情了,通过调用API也就下面几行代码的事情
cv::SiftFeatureDetector detector;std::vector<cv::KeyPoint> keypoint;detector.detect(image, keypoint); //image是需要进行特征提取的图像std::cout << "\ndetected SIFT feature point size: " << keypoint.size() << "\n";//获得每个特征点的128维特征向量cv::SiftDescriptorExtractor extractor;cv::Mat des1; //descriptorextractor.compute(image, keypoint, des1);
但是在进行诸如匹配的时候由于提取出来的SIFT特征样本的数目是不同的,这就需要进行映射抽取,这就讲到了今天说到的BOW特征,抽取到BOW特征之后可以简单得进行欧式距离的比较,或是放入后面的分类器进行训练。
2. 实现原理
BOW模型的处理过程:
1. SIFT特征提取。SIFT 特征提取是求出图像的关键点信息,包括角度,大小以及强度。关键点,也就是能够代表图像关键信息的部分,这也是Bag of words中单词的组成。一个图像通常有很多的关键点。
2. 聚类。我们将每幅图像中的关键点信息添加到词袋中,并定义聚类中心的数量N。然后将词袋中的关键点通过Kmeans算法聚类到N个类中。同时得到这N个类的中心点组成N*128的dictionary,每个中心都可以代表这个类。
3. 求图像的直方图。将图像的关键点信息重新放到词包中,根据落在每个类中关键点的数量来得到图像的直方图,大小为1*N。将每幅图像进行处理,得到图像在BOW模型下的特征。
4. 图像匹配。将测试图像进行相同的处理,同样也得到1*N的特征。根据测试图像与训练图像特征之间的距离,并将距离较小的图像作为检索的结果。
3. 代码解析
在生成BOW特征过程中主要涉及到特征聚类和产生BOW特征描述(归一化直方图)。
首先来看聚类,聚类使用到的是BOWKMeansTrainer 这个类,
class BOWKMeansTrainer : public BOWTrainer{public: BOWKMeansTrainer( int clusterCount, const TermCriteria& termcrit=TermCriteria(), int attempts=3, int flags=KMEANS_PP_CENTERS ); virtual ~BOWKMeansTrainer(){} // Returns trained vocabulary (i.e. cluster centers). virtual Mat cluster() const; virtual Mat cluster( const Mat& descriptors ) const;protected: ...};
这里主要使用的是它的构造函数,调用的时候定好需要分出的类数目,其它的参数默认就好。第二个是成员函数cluster(const Mat& descriptors)。
之后是生成BOW特征,使用到的类是BOWImgDescriptorExtractor,基于视觉词典包算法来计算一个图像的特征描述子的类。算法步骤如下:
1. 给定一幅图像及其图像特征检测子(关键点)集,计算特征描述子。
2. 给定每一个图像特征检测子对应的特征描述子,从视觉词典中寻找最近的词。
3. 计算视觉词典包图像特征描述子.该结果为一个归一化后的直方图.直方图向量中第i
个 值是视觉词典中的第i
个词在给定图像中的频率。
该类的接口定义为:
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> >* pointIdxsOfClusters=0, Mat* descriptors=0 ); int descriptorSize() const; int descriptorType() const;protected: ...};
这里主要调用compute成员函数
4. Demo代码
cv::initModule_nonfree();cv::BOWKMeansTrainer bowTraining(feature_num); //定义一个对象,生成聚类中心cluster_num(聚类的数目)个,其余的默认参数cv::Mat dictionary = bowTraining.cluster(feature_discriptor); //按照设置好的聚类数目进行聚类,生成字典集,也就是聚类中心 ,feature_discriptor是SIFT生成的特征描述//聚类中心的映射初始化cv::Ptr<cv::DescriptorExtractor> extractor = cv::DescriptorExtractor::create("SIFT"); //引号里面修改特征种类。 cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create("BruteForce"); //引号里面修改匹配类型; cv::BOWImgDescriptorExtractor bowDE(extractor, matcher); //直方图统计bowDE.setVocabulary(dictionary); //dictionary是通过前面聚类得到的词典std::vector<cv::KeyPoint> keypoints;cv::SiftFeatureDetector detector;cv::Mat descriptors;detector.detect(img, keypoints); //SIFT提取图像的特征点bowDE.compute(img, keypoints, descriptors); //提取该图像的BOW特征描述
5. 参考资料
- opencv 中关于BOW模型的实现以及相关的函数解释
- 物体目标分类
- 学习OpenCV——BOW特征提取函数(特征点篇)