OpneCV3——使用SURF、SVM、BOW对图像进行分类
前言
1.按圖像中的內容給圖像分類是計算機視覺中比較適合初學者的項目,好多手機相冊都有這一個功能,比如把美食歸為一個標簽,藍天白云歸為一個標簽等等。還有我之前做過的車牌識別的項目都用到圖像分類這個功能。
2.項目的環境:Winwods7 ,vs2015,OpenCV3.3加opencv_contrib庫,boost庫,實現語言是C++.
3.項目用到的知識點有OpenCV的SURF特征提取、BOW(Bag-of-words model-詞袋模型),SVM分類器等,boost是用來操作文件。
4.項目的是功能是先對一些已經手動歸類好的圖像樣本進行輸入并訓練,把訓練好的結果保存,然后使用訓練好的結果對未知的圖像進行預測判斷并分類,我使用的樣本每個種類只有120張,特性提取的SURF的hessianThreshold取值從400到2000,準確率在70%到80%之間。
一.數據收集與處理
1.圖像數據是從ZOL壁紙網站下載,里面有分類好的壁紙,可以整個系列下載。下載之后新建文件夾放同類型的圖像,我收集了四個類型圖像,新建一個data/train的文件夾,然后手工分類并放到相關的文件夾里再放到該目錄下,每個種類收集了差不多120張圖像。
????????
2.圖像不能太大,也不能太小,試過在訓練集放了全是幾M以上的圖像,跑特征聚類時跑了一天沒有跑出來,如果圖像太小只有幾B,到特征提取那里有可能會報錯,認為是空的圖像矩陣。從網上收集的圖像太大可以編寫python腳本把每個文件夾下的圖像改成統一大小的像素的,該腳本把所有圖像改成寬384和高256的圖像。
resize.ipynb
3.在data目錄再創建一個test的文件夾,用來放測試時用的圖像,就是放訓練種類相關的圖像,圖像大小隨便,沒有尺寸要求。
4.可以從這里下載我分好類的正樣本和測試樣本,下載地址:https://download.csdn.net/download/matt45m/11044699
二.項目流程與步驟
1.訓練代碼流程圖
2.測試代碼流程
三.代碼示例
1.初始化與讀取相關文件夾,如果第一次運行,創建要用到的文件夾,有放模板的文件夾、放測試訓練結果的文件夾、放訓練好的文件的文件夾。然后從訓練集每個文件夾拿出一張圖像放到模板文件夾里并按類型命名。
創建相關文件夾
3.遍歷訓練集文件夾下的所有圖像文件,保存multimap容器。
(1).循環遍歷train文件夾下的訓練文件夾
(2)multimap的存儲方式如下圖:
4.提取訓練集里每張圖像的特征點,得出BOW詞典,并保存BOW文件。
5.構造與保存BOW文件。
// 對于每一幅模板,提取SURF算子,存入到vocab_descriptors中 multimap<string, Mat> ::iterator i = train_set.begin();for (; i != train_set.end(); i++) {//定義關鍵點vector<KeyPoint>key_point;//從容器里讀出文件絕對路徑string cate_name = (*i).first;//從容器里讀出圖片Mat temp_image = (*i).second;Mat imageDescriptor;//detect函數檢測SURF/SIFT特征的關鍵點,并保存在vector容器中,最后使用drawKeypoints函數繪制出特征點。feature_decter->detect(temp_image, key_point);//用視覺詞典計算圖像特征描述子bow_descriptor_extractor->compute(temp_image, key_point, imageDescriptor);//push_back(Mat);在原來的Mat的最后一行后再加幾行,元素為Mat時, 其類型和列的數目 必須和矩陣容器是相同的allsamples_bow[cate_name].push_back(imageDescriptor); }6.訓練分類器并保存訓練好的文件,訓練完成。
for (int i = 0; i < categories_size; i++) {//在創建對象同時,提供矩陣行數、列數、存儲類型Mat tem_Samples(0, allsamples_bow.at(category_name[i]).cols,allsamples_bow.at(category_name[i]).type());//新行一個0行一列的矩陣Mat responses(0, 1, CV_32SC1);//把上面包含特征點的矩陣加到新建的矩陣后面tem_Samples.push_back(allsamples_bow.at(category_name[i]));//新建一個跟特征模板行數一樣,1列,并全部初始化為1的矩陣Mat posResponses(allsamples_bow.at(category_name[i]).rows, 1, CV_32SC1, Scalar::all(1));//把數據壓入矩陣responses.push_back(posResponses);//遍歷容器for (auto itr = allsamples_bow.begin(); itr != allsamples_bow.end(); ++itr){if (itr->first == category_name[i]){continue;}//壓入數據tem_Samples.push_back(itr->second);Mat response(itr->second.rows, 1, CV_32SC1, Scalar::all(-1));responses.push_back(response);}//samples是訓練樣本特征的矩陣,layout參數有ROW_SAMPLE和COL_SMAPLE兩個選擇,//說明了樣本矩陣中一行還是一列代表一個樣本,response矩陣和samples矩陣相對應,說明了樣本的標記Ptr<TrainData> t_tdata = TrainData::create(tem_Samples,ROW_SAMPLE, responses);//開始訓練stor_svms.at(i)->train(t_tdata);//存儲svmstring svm_filename = xml_path + category_name[i] + string("SVM.xml");stor_svms.at(i)->save(svm_filename.c_str()); }四、測試
1.測試代碼
2.測試結果
卡通這個類別的,可以看到有幾張是錯誤的。
花這個類別的,也有幾張誤判的:
結語:
1.同樣的數據,使用opencv進行預測時,所有的時間和準確率和caffe訓練成模型之后調用,完全不是一個級別的,caffe的模型預測速度比opencv這個項目要快差不多3倍。
caffe預測一張圖像所花的時間:
SVM分類預測一張圖像所花的時間:
2.準確率也不一樣,如果樣本數量少,caffe還可使用遷移學習來提高準確率,caffe預測能達到97%上,但SVM分類器只能達到80%左右,也許是代碼優化的問題吧。
3.關于工程的源碼,運行程序時的bug,都可以加這個群(487350510)互相討論學習。
總結
以上是生活随笔為你收集整理的OpneCV3——使用SURF、SVM、BOW对图像进行分类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV图像处理——对比两张图像差异
- 下一篇: OpenCV图像处理使用笔记(三)——单