分類器的訓練進行目標識別,以車輛識別為例
一、從網路上下載或者自己找到的圖片中裁剪挑選出合適的圖片。圖片的大小和格式都要相同,準備好兩個資料夾,分別命名為posdata(正樣本)和negdata(負樣本),所有樣本的尺寸必須一致,如果不一致的或者尺寸較大的,可以先將所有樣本統一縮放到100*40。posdata中的圖片為車輛樣本。給分類器展示的是正確的樣本。
negdata中的圖片為一些背景樣本,裡面不包含車輛,是用來告訴分類器哪些是錯誤的樣本。雖然負樣本就是樣本中不存在正樣本的內容,但最好是根據不同的專案選擇不同的負樣本,比如一個專案是做機場的人臉檢測,那麼就最好從現場拍攝一些圖片資料回來,從中採集負樣本。
二、在negdata和posdata資料夾準備好之後,使用命令提示符(win + r),輸入cmd,把位置切換到posdata資料夾的位置。
然後在裡面輸入“ dir /b/s/p/w *.jpg > pos.txt ”,將會在posdata資料夾中產生一個pos.txt的文件。開啟pos.txt,選擇編輯-替換,在查詢中搜索jpg,替換為jpg 1 0 0 100 40,之後儲存,將pos.txt複製到上一級目錄中。
之後對negdata資料夾進行相同的操作,在cmd中輸入的語句為“ dir /b/s/p/w *.jpg > neg.txt ”。
三、找到自己下載的OpenCV資料夾,開啟opencv,開啟build,開啟x64,開啟vc14,開啟bin資料夾。
選擇opencv_createsamples.exe和opencv_traincascade.exe兩項,將其複製到需要的資料夾中,與negdata、posdata並列。
四、開啟cmd,在該檔案目錄下輸入“ opencv_createsamples.exe -vec pos.vec -info pos.txt -num 32 -w 100 -h 40 ” 。
pos.txt 表明這是正樣本;
num 32 代表正樣本照片數量;
w 100 h40表示圖片解析度(寬和高)
之後在該資料夾中會出現pos.vec
之後重複該步驟,cmd輸入的語句換為“ opencv_createsamples.exe -vec neg.vec -info neg.txt -num 100 -w 100 -h 40 ”,產生neg.vec。
五、在主資料夾下建立一個txt文件,命名為“traincascade”,在該txt中輸入“
opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 32 -numNeg 100 -numStages 20 -w 100 -h 40 -mode ALL
pause
”
numPos 32 代表正樣本照片數量 numNeg100 表示負樣本照片數量 numStage 20表示檢測次數 pause為暫停
對“traincascade.txt”進行重新命名,將字尾名改為bat。
之後雙擊“traincascade.bat”。會產生如下效果
訓練分類器時佔用CPU空間多,電腦執行將會變卡,處理時間較長。處理完成之後將會在資料夾下生成一個cascade.xml。
六、 之後可以執行VS,新建一個VC++專案。輸入一下程式碼之後進行測試。
程式碼為:
#include<opencv2\opencv.hpp> #include<iostream>
using namespace cv; using namespace std;
String filename = "F:/車輛樣本2/cascade.xml"; //之前cascade.xml放置的位置 CascadeClassifier car_classifier;
int main(int argc, char**argv) { if (!car_classifier.load(filename)) { printf("could not laod car feature data..\n"); return -1; }
Mat src = imread("D:/圖片/15.jpg"); //需要檢測的圖片 if (src.empty()) { printf("could not laod image...\n"); return -1; } imshow("inupt image", src); Mat gray; cvtColor(src, gray, COLOR_BGR2GRAY); equalizeHist(gray, gray);
vector<Rect>cars; car_classifier.detectMultiScale(gray, cars, 1.1, 3, 0, Size(50, 50)); for (size_t t = 0; t < cars.size(); t++) { rectangle(src, cars[static_cast<int>(t)], Scalar(0, 0, 255), 2, 8, 0); }
imshow("detect cars", src); waitKey(0); return 0;
}
之後點選執行,因為設定的正負樣本過少的原因,效果不是很明顯。出現效果如下: