image = imread(path);
//sift关键点检测
SiftFeatureDetector detector;
detector.detect(image, keyPoints);
//sift关键点描述,角度,强度等
SiftDescriptorExtractor extractor;
extractor.compute(image, keyPoints, descriptor);
另外函数的头文件是:#include 实现原理:
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 extractor = DescriptorExtractor::create("SIFT");
Ptr matcher = DescriptorMatcher::create("BruteForce");
BOWImgDescriptorExtractor bowDE(extractor, matcher);
bowDE.setVocabulary(dictionary);
对每幅图像图像进行如下操作:
Mat BOWdescriptor;
//sift关键点检测
vector 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.
Parameters: |
|
---|
祝各位身体健康,学习进步。今天看到CSDN大神雷霄骅去世的消息,十分悲痛!天妒英才啊!!所以大家在学习和工作的时候一定要注意休息,身体是革命的本钱啊!!!