opencv 中关于BOW模型的实现以及相关的函数解释

       这两天在做关于图像的局部特征提取的内容,使用工具是VS2013+OpenCV。通过看论文知道一般采用SIFT+BOW来进行实现。关于SIFT特征提取的介绍很多,一般都比较复杂难懂,尤其是对我这种数学不怎么好的人。看了几天还是很朦胧。OpenCV中有对图像SIFT特征提取的函数,下面给出提取的过程:

     image = imread(path);
	//sift关键点检测
	SiftFeatureDetector detector;
	detector.detect(image, keyPoints);
	//sift关键点描述,角度,强度等
	SiftDescriptorExtractor extractor;
	extractor.compute(image, keyPoints, descriptor);

      另外函数的头文件是:#include <opencv2/nonfree/features2d.hpp>,之前的版本是放在#include "opencv2/features2d/features2d.hpp"中的。还是多注意一下吧。

实现原理:

BOW模型的处理过程:

        1.SIFT特征提取。SIFT 特征提取是求出图像的关键点信息,包括角度,大小以及强度。关键点,也就是能够代表图像关键信息的部分,这也是Bag of words中单词的组成。一个图像通常有很多的关键点。

        2.聚类。我们将每幅图像中的关键点信息添加到词袋中,并定义聚类中心的数量N。然后将词袋中的关键点通过Kmeans算法聚类到N个类中。同时得到这N个类的中心点组成N*128的dictionary,每个中心都可以代表这个类。

        3.求图像的直方图。将图像的关键点信息重新放到词包中,根据落在每个类中关键点的数量来得到图像的直方图,大小为1*N。将每幅图像进行处理,得到图像在BOW模型下的特征。

        4.图像匹配。将测试图像进行相同的处理,同样也得到1*N的特征。根据测试图像与训练图像特征之间的距离,并将距离较小的图像作为检索的结果。

实现过程:

          OpenCV中已经对步骤中的过程进行了封装,我们只需要简单的调用就可以。上面的代码中我们已经完成了第一步。

          第二步和第三步BOW模型的实现,我们可以采用调用函数BOWKmeansTrainer进行实现。

       int clusterNum =260;
	//clusterNum代表有多少词
	BOWKMeansTrainer trainer(clusterNum);

          同时需要将提取到的SIFT特征描述添加到trainer中

      //descriptor是每幅图像的sift关键点描述
        trainer.add(descriptor);

        所有图像的descriptor添加完成后,进行聚类得到dictionary,也就是聚类的中心。

      Mat dictionary = trainer.cluster();

        接下来需要得到每幅图像直方图。过程如下

        Ptr<DescriptorExtractor> extractor = DescriptorExtractor::create("SIFT");
	Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
	BOWImgDescriptorExtractor bowDE(extractor, matcher);
	bowDE.setVocabulary(dictionary);

        对每幅图像图像进行如下操作:

                      Mat BOWdescriptor;
			//sift关键点检测
			vector<KeyPoint> keyPoints;
			SiftFeatureDetector detector;
			detector.detect(curImg, keyPoints);
			//BOWdecriptor表示每个图像的bow码本,即直方图,大小为1*clusterNum
			bowDE.compute(curImg, keyPoints, BOWdescriptor);
			//归一化
			normalize(BOWdescriptor, BOWdescriptor, 1.0, 0.0, NORM_MINMAX);

       得到的BOWdescriptor就是每个图像的直方图表示,可用做图像检索的特征。最简单的方法就是求测试图像的直方图与训练图像之间的欧明距离,得到检索图像。不过检索的方式不一样,效率和质量也不同。

过程中长的姿势:

       刚开始写的时候,不知道怎么求图像的码本,就不停的翻看OpenCV中关于函数BOWImgDescriptorExtractor::compute的解释,刚开始看的是中文解释,看了很久也没有看懂,后面找到了英文的注释,顿时就明白了。看来还是要英语好啊!!!!下面给出英语版的,中文的就算了。。。

BOWImgDescriptorExtractor::compute

Computes an image descriptor using the set visual vocabulary.

C++: void BOWImgDescriptorExtractor::compute(const Mat& image, vector<KeyPoint>& keypoints, Mat& imgDescriptor, vector<vector<int>>* pointIdxsOfClusters=0, Mat*descriptors=0 )
Parameters:
  • image – Image, for which the descriptor is computed.
  • keypoints – Keypoints detected in the input image.
  • imgDescriptor – Computed output image descriptor.
  • pointIdxsOfClusters – Indices of keypoints that belong to the cluster. This means that pointIdxsOfClusters[i] are keypoint indices that belong to the i -th cluster (word of vocabulary) returned if it is non-zero.
  • descriptors – Descriptors of the image keypoints that are returned if they are non-zero.

        祝各位身体健康,学习进步。今天看到CSDN大神雷霄骅去世的消息,十分悲痛!天妒英才啊!!所以大家在学习和工作的时候一定要注意休息,身体是革命的本钱啊!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章