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大神雷霄驊去世的消息,十分悲痛!天妒英才啊!!所以大家在學習和工作的時候一定要注意休息,身體是革命的本錢啊!!!