您的位置:首页 > 运维架构

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

2016-08-05 19:49 513 查看
       这两天在做关于图像的局部特征提取的内容,使用工具是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大神雷霄骅去世的消息,十分悲痛!天妒英才啊!!所以大家在学习和工作的时候一定要注意休息,身体是革命的本钱啊!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息