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