提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔
使用級聯分類器訓練人臉模型
項目場景:
作為一個大四狗,在畢業之前想做點有意思的東西,加上人工智能這兩年很火,也就從網上找資源,進行了一個學習的過程,使用的平台是QT5.12+OpenCV3.40。目的就是為了訓練一個可以進行人臉檢測的模型。
正樣本準備:
跟着賈志剛老師的課程學了一段時間以後,自己也就找項目去練手去了。不過在訓練的過程中還是借鑒了大佬的部落格https://blog.csdn.net/yangdashi888/article/details/80385041
裡面的描述還是很詳細的。采集的方法有了,但是資料方面也是很重要的,為此,我寫了一個QT的應用程式來進行資料采集的工作。` string writePath = “E:/Trainslation/img/”;
VideoCapture capture(1);
string name;
Mat Gray,outs;
int i = 939 ;
Rect rect(0,0,300,300);
capture.set(CAP_PROP_FRAME_WIDTH, 540.0);
//設定攝像頭采集圖像分辨率
capture.set(CAP_PROP_FRAME_HEIGHT, 680.0);
while(1){
Mat frame;
capture>>frame;
if(32==waitKey(20))
{
name = writePath + to_string(i)+".jpg";
outs = Mat(frame,rect);
cvtColor(outs,Gray,COLOR_BGR2GRAY);
imwrite(name,frame);
cout<<name<<endl;
i++;
}
if (97 == waitKey(10)) { //'a’退出
break;
}
rectangle(frame,rect,Scalar(125,125,125),3,LINE_8,0);
imshow(“hello”,frame);
//imshow(“GRAY”,Gray);
}
運作結果圖:

方框裡面的就是圖像采集區域,可以通過修改Rect參數來控制範圍,通過按下空格進行拍照,講目标圖檔存入指定的位置。
通過對實驗室的國小弟進行友好互動,得到了近500張人臉的樣本,因為對正樣本的要求是要灰階圖檔,是以在采集的時候做了灰階轉換處理。
cvtColor(outs,Gray,COLOR_BGR2GRAY);//灰階轉換
負樣本準備:
對于負樣本的要求很簡單的,隻需要不包含正樣本的照片就可以的了,當然負樣本數量跟正樣本數量的比例約為3:1。
從網上找了一些圖檔,還有就是使用上面的素材采樣程式,通過加大開窗,以及取消灰階轉換,得到了近1500張的負樣本素材。
分類器樣本制作:
制作方法很簡單,首先就是在采集到的圖像的路徑下面通過記事本建立一個.txt檔案。輸入以下内容:
dir /b/s/p/w *.jpg > positives.txt
這個正樣本使用相對路徑即可,打開記事本講路徑進行替換
face\0.jpg 1 0 0 100 100
保留為前面的face\即可,後面的.jpg替換為.jpg 1 0 0 100 100
注意後面的100 100 是圖檔的長度和寬度,這個根據需求自行改變
最後将生産的txt檔案字尾改為.bat格式。然後将這個檔案剪切到上一級路徑上。
同理,負樣本也是可以通過這種方法來進行制作,但是.jpg 後面的内容是可以省略的。
opencv配置:
在正式訓練之前我們需要将opencv路徑下的一些檔案進行拷貝。
E:\opencv3.4\opencv\build\x64\vc15\bin
上面的是我的opencv安裝位置,然後将其下的
這幾個檔案拷貝到需要訓練的位置,注意裡面的.dll檔案不能忘記哦。至此,我們的準備工作已經齊全了。
接下來要做的就是進行分類訓練了。
vec檔案擷取:
使用快捷鍵win+R輸入cmd:
然後進入目标位置,也就是自己訓練的位置。
然後使用opencv_createsamples.exe
這個是該應用程式的參數,隻需要按照自己的需求進行調整即可。
opencv_createsam
plesd.exe -info E:\image\face\positive\info.dat -vec E:\image\face\sample_310.ve
c -num 760 -bgcolor 0 -bgthresh 0 -w 24 -h 24
最終會得到一個vec檔案。
提示:這裡可以添加要學的内容
例如:
1、 搭建 Java 開發環境
2、 掌握 Java 基本文法
3、 掌握條件語句
4、 掌握循環語句
開始訓練:
opencv_traincascaded.exe -data E:\image\face -vec E:\image\face\sample_310.vec -bg bg.txt -numPos 500-numNeg 1500 -numStages 12 -featureType LBP -w 24 -h 24 -minHitRate 0.995 -maxFalseAlarmRate 0.5
這個是一些參數,可以根據自己的需要進行調整。
最終訓練結束會得到一個xml檔案,接下來我們就用用這個檔案去做驗證了。
ui->setupUi(this);
VideoCapture capture(0);
// capture.set(CAP_PROP_FRAME_WIDTH, 540.0);//設定攝像頭采集圖像分辨率
// capture.set(CAP_PROP_FRAME_HEIGHT, 680.0);
String fileName = "E://Trainslation//xml3//cascade.xml";
//Mat img = imread("C:/Users/HS/Desktop/test.jpg");
CascadeClassifier left_classifier;
if (!left_classifier.load(fileName)) {
printf("could not load face feature data...\n");
}
Mat Gary,outs;
vector<Rect> left;
//cvtColor(img,Gary,COLOR_BGR2GRAY);
//equalizeHist(Gary,Gary);
// left_classifier.detectMultiScale(Gary,left,1.1,3,0| cv::CASCADE_SCALE_IMAGE,Size(20,20));
// for(size_t t= 0 ; t<left.size();t++)
// {
// rectangle(img,left[static_cast<int>(t)],Scalar(0,0,255),2,8,0);
// }
// imshow( "output",img);
while(1)
{
Mat frame;
capture>>frame;
cvtColor(frame,Gary,COLOR_BGR2GRAY);
equalizeHist(Gary,Gary);
left_classifier.detectMultiScale(Gary,left,1.1,3,0,Size(40,40));
waitKey(100);
for(size_t t= 0 ; t<left.size();t++)
{
rectangle(frame,left[static_cast<int>(t)],Scalar(0,0,255),2,8,0);
}
imshow("The src imput img",frame);
waitKey(40);
}
結果驗證:
還是可以成果找到自己的,效果還是欠佳,多訓練幾次,加大訓練量效果會更好的。
總結
通過一段時間對于opencv的學習,感覺opencv的應用還是很不錯的,在于圖像處理方面擁有這極好的應用。想起來之前動手做攝像頭循迹小車的時候。當時用的是ov2640做的圖像處理,裡面要對每一幀圖像的每一個像素點做一個判斷,最終也就做出來一個黑白二值化的結果,如今應用opencv可以輕松做到這些個,自己學習的道路還是很長,也希望跟志同道合的朋友一起鑽研項目,一起成長。