1. 程式人生 > >opencv 中關於BOW模型的實現以及相關的函式解釋

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