目錄
前言
一、目標(biāo)檢測技術(shù)
二、樣本采集工作原理
三、創(chuàng)建自己的級聯(lián)分類器
Step1:準(zhǔn)備好樣本圖像
Step2:環(huán)境配置(OpenCV win10)
Step3:設(shè)置路徑
Step4:實現(xiàn)樣本數(shù)據(jù)采集?
Step5:實現(xiàn)樣本數(shù)據(jù)訓(xùn)練
Step6:生成級聯(lián)分類器文件?
四、案例實現(xiàn)
Step1:灰度處理
Step2:二次壓縮
Step3:直方圖均衡化
Step4:標(biāo)定、框選目標(biāo)
??案例完整代碼
五、總結(jié)?
前言
本文繼續(xù)以車輛識別為目標(biāo),繼續(xù)改進方法,以此提高車輛識別進準(zhǔn)度,核心的內(nèi)容包括:OpenCV級聯(lián)分類器概念、創(chuàng)建自己的級聯(lián)分類器以及使用級聯(lián)分類器對車流進行識別?
一、目標(biāo)檢測技術(shù)
目前常用實用性目標(biāo)檢測與跟蹤的方法有以下兩種:
- 幀差法
- 識別原理:基于前后兩幀圖像之間的差異進行對比,獲取圖像畫面中正在運動的物體從而達到目標(biāo)檢測
- 缺點:畫面中所有運動中物體都能識別
- 舉個例子:我們的目標(biāo)是識別運動的車輛,但是,在畫面中鏡頭晃動,大風(fēng)吹過樹葉飄動也會被計算在甄別范圍內(nèi),這就會導(dǎo)致甄別物出現(xiàn)錯誤
- 級聯(lián)分類器
- 那么,有沒有更好的方式能降低我們甄別目標(biāo)出現(xiàn)錯誤的概率呢?
- 這邊就可以使用我們的級聯(lián)分類器了,如果我們的識別目標(biāo)是車輛,那就需要把車輛相關(guān)的信息全部統(tǒng)計出來,比如:車輛顏色、車輛形狀、車輛大小等信息,將他們存儲在一個文件中,以提高甄別準(zhǔn)確度,這個文件就是級聯(lián)分類器
- 級聯(lián)分類器也是機器視覺和機器學(xué)習(xí)中非常重要的一個環(huán)節(jié)
二、樣本采集工作原理
- 分析一?
使用基于Haar特征的級聯(lián)分類器的對象檢測,這是一種基于機器學(xué)習(xí)的方法,其中從許多正負(fù)圖像中訓(xùn)練級聯(lián)函數(shù),然后,用于檢測其他圖像中的對象,在這里,我將進行人臉檢測舉例說明,最初,該算法需要大量正圖像(面部圖像)和負(fù)圖像(無面部圖像)來訓(xùn)練分類器,?然后,我們需要從中提取特征,為此,使用下圖所示的Haar功能,?它們就像我們的卷積核一樣,每個特征都是通過從黑色矩形下的像素總和中減去白色矩形下的像素總和而獲得的單個值
- 分析二
現(xiàn)在,每個內(nèi)核的所有可能大小和位置都用于計算許多功能,試想一下它產(chǎn)生多少計算?即使是一個24x24的窗口也會產(chǎn)生超過160000個特征,這對于每個特征計算,我們需要找到白色和黑色矩形下的像素總和,為了解決這個問題,引入了整體圖像,無論你的圖像有多大,它都會將給定像素的計算減少到僅涉及四個像素的操作,它使事情變得更快,?但是,在我們計算的所有這些特征中,大多數(shù)都不相關(guān),例如,下圖,第一行顯示了兩個良好的特征,選擇的第一個特征似乎著眼于眼睛區(qū)域通常比鼻子和臉頰區(qū)域更暗的性質(zhì),選擇的第二個特征依賴于眼睛比鼻梁更黑的屬性,但是,將相同的窗口應(yīng)用于臉頰或其他任何地方都是無關(guān)緊要的,那么,我們將如何從16萬多個功能中選擇最佳特征?
我們將所有特征應(yīng)用于所有訓(xùn)練圖像,對于每個特征,它會找到最佳的閾值,該閾值會將人臉分為正面和負(fù)面,顯然,會出現(xiàn)錯誤或分類錯誤,我們選擇錯誤率最低的特征,這意味著它們是對人臉和非人臉圖像進行最準(zhǔn)確分類的特征,此過程并非如此簡單,在開始時,每個圖像的權(quán)重均相等,在每次分類后,錯誤分類的圖像的權(quán)重都會增加,然后執(zhí)行相同的過程,將計算新的錯誤率,還要計算新的權(quán)重,繼續(xù)進行此過程,直到達到所需的精度或錯誤率或找到所需的功能數(shù)量為止,?最終分類器是這些弱分類器的加權(quán)和,之所以稱為弱分類,是因為僅憑它不能對圖像進行分類,而是與其他分類一起形成強分類器,甚至200個功能都可以提供95%的準(zhǔn)確度檢測
三、創(chuàng)建自己的級聯(lián)分類器
Step1:準(zhǔn)備好樣本圖像
- 正樣本數(shù)據(jù)采集(我們需要檢識別的目標(biāo)圖片,例如:車輛)
- 負(fù)樣本數(shù)據(jù)采集(非檢測物的圖片)
我們可以在生活中觀察到,大馬路上除了車輛,還存在諸多的干擾,比如說:行人、斑馬線、交通設(shè)別(路障、護欄、紅綠燈、路燈等等),以及上文所說的風(fēng)吹動,樹葉飄動等等
Step2:環(huán)境配置(OpenCV win10)
- 下載OpenCV win10系統(tǒng)安裝包
- 從安裝包中的opencv\build\x64\vc15\bin 找到
? ? ? ? -??opencv_createsamples.exe
? ? ? ? -? opencv_traincascade.exe
? ? ? ??-? opencv_world342.dll
- 將以上文件拷貝到正負(fù)樣本文件路徑下
Step3:設(shè)置路徑
- 創(chuàng)建正負(fù)樣本的圖像路徑的?.txt文件
Step4:實現(xiàn)樣本數(shù)據(jù)采集?
- 調(diào)用opencv中opencv_createsamples.exe實現(xiàn)樣本數(shù)據(jù)采集
通過命令行執(zhí)行命令進行樣本采集生成car_samples.vec正樣本矢量集文件,命令行如下:
opencv_createsamples.exe -info car_list.txt -vec car_samples.vec ?-num 80 -w 33 -h 33
- - info字段填寫正樣本描述文件
- - vec用于保存制作的正樣本
- - num制定正樣本的數(shù)目
- ?- w和-h分別指定正樣本的寬和高
- 在windows下終端運行,如下圖所示:?
Step5:實現(xiàn)樣本數(shù)據(jù)訓(xùn)練
- 調(diào)用opencv中opencv_traincascade.exe對樣本進行訓(xùn)練?
通過命令行執(zhí)行命令進行訓(xùn)練生成,命令行如下:
opencv_traincascade.exe -data data -vec car_samples.vec ?-bg ng_data.txt ?-numPos 80 -numNeg 240 -numStages 7 -w 33 -h 33 -minHitRate 0.995 -maxFalseAlarmRate 0.45 -mode ALL
- -data:指定保存訓(xùn)練結(jié)果的文件夾
- -vec:指定正樣本集; -bg:指定負(fù)樣本的描述文件夾?
- -numPos:指定每一級參與訓(xùn)練的正樣本的數(shù)目(要小于正樣本總數(shù))
- -numNeg:指定每一級參與訓(xùn)練的負(fù)樣本的數(shù)目(可以大于負(fù)樣本圖片的總數(shù))
- -numStage:訓(xùn)練的級數(shù)
- -w:正樣本的寬
- -h:正樣本的高?
- -minHitRate:每一級需要達到的命中率(一般取值0.95-0.995)
- -maxFalseAlarmRate:每一級所允許的最大誤檢率?
- -mode:使用Haar-like特征時使用,可選BASIC、CORE或者ALL?
- 另外,還可指定以下字段:
- -featureType:可選HAAR或LBP,默認(rèn)為HAAR;
- 在windows下終端運行,進行訓(xùn)練,每一層訓(xùn)練都會有顯示,如下圖所示:??
- PS:訓(xùn)練時需要考慮一下自身電腦配置,小心電腦跑出問題!
Step6:生成級聯(lián)分類器文件?
-
生成文件,如下所示:?
四、案例實現(xiàn)
我們將繼續(xù)編寫代碼通過C++ 編寫 OpenCV 在Qt上來展現(xiàn)出我們的案例效果
Step1:灰度處理
- 將我們的色彩通道縮小,簡化矩陣,提高運算速度?
//【灰度處理】
Mat gray;
cvtColor(frame,gray,CV_RGB2GRAY);
Step2:二次壓縮
- 灰度處理還不夠,級聯(lián)分類器比幀差法還更加慢,因此,再將灰度圖大小壓縮一半左右?
//一次還不夠,級聯(lián)分類器比幀差法還更加慢
//【二次壓縮】因此,再將灰度圖大小壓縮一半左右
Mat smalling(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1);
resize(gray,smalling,smalling.size(),0,0,INTER_LINEAR);
Step3:直方圖均衡化
- 將縮小一半的灰度圖進行均值化使其更加黑白分明
equalizeHist(smalling,smalling);
//imshow("smalling",smalling);
Step4:標(biāo)定、框選目標(biāo)
- 調(diào)用級聯(lián)分類器進行模型匹配并框選目標(biāo)
//調(diào)用級聯(lián)分類器進行模型匹配并框出內(nèi)容
vector<Rect>cars;
//【參數(shù)說明】 待檢測的圖片幀 被檢測物體的矩形向量容器 每次搜索減小的圖像比例 檢測目標(biāo)周圍相鄰矩形的最小個數(shù)(此處設(shè)為2個) 類型 目標(biāo)區(qū)域的大小尺寸
cascade.detectMultiScale(smalling,cars,1.05,5,0|CV_HAAR_SCALE_IMAGE,Size(25,25));
vector<Rect>::const_iterator iter;
//【繪制標(biāo)記框】注意,標(biāo)記要畫在原幀上,要講方框的大小和幀坐標(biāo)擴大,因為是根據(jù)灰度圖識別的,灰度圖被縮小了
for(iter=cars.begin();iter!=cars.end();iter++)
{
rectangle(frame,
cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)),
cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)),
Scalar(0,255,0),2,8
);
}
imshow("frame",frame);
}
??案例完整代碼
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void datectCarDaw(Mat &frame,CascadeClassifier cascade,double scale)
{
//【灰度處理】
Mat gray;
cvtColor(frame,gray,CV_RGB2GRAY);
//一次還不夠,級聯(lián)分類器比幀差法還更加慢
//【二次壓縮】因此,再將灰度圖大小壓縮一半左右
Mat smalling(cvRound(frame.rows/scale),cvRound(frame.cols/scale),CV_8UC1);
resize(gray,smalling,smalling.size(),0,0,INTER_LINEAR);
//【直方圖均衡化】將縮小一半的灰度圖進行均值化使其更加黑白分明
equalizeHist(smalling,smalling);
//imshow("smalling",smalling);
//調(diào)用級聯(lián)分類器進行模型匹配并框出內(nèi)容
vector<Rect>cars;
//【參數(shù)說明】 待檢測的圖片幀 被檢測物體的矩形向量容器 每次搜索減小的圖像比例 檢測目標(biāo)周圍相鄰矩形的最小個數(shù)(此處設(shè)為2個) 類型 目標(biāo)區(qū)域的大小尺寸
cascade.detectMultiScale(smalling,cars,1.05,5,0|CV_HAAR_SCALE_IMAGE,Size(25,25));
vector<Rect>::const_iterator iter;
//【繪制標(biāo)記框】注意,標(biāo)記要畫在原幀上,要講方框的大小和幀坐標(biāo)擴大,因為是根據(jù)灰度圖識別的,灰度圖被縮小了
for(iter=cars.begin();iter!=cars.end();iter++)
{
rectangle(frame,
cvPoint(cvRound(iter->x*scale),cvRound(iter->y*scale)),
cvPoint(cvRound((iter->x+iter->width)*scale),cvRound((iter->y+iter->height)*scale)),
Scalar(0,255,0),2,8
);
}
imshow("frame",frame);
}
int main(int argc, char *argv[])
{
//級聯(lián)分類器(模型)
CascadeClassifier cascade;
cascade.load("C:/Users/86177/Desktop/cars-face/cars.xml");//讀取級聯(lián)分類器
Mat frame;
VideoCapture cap("C:/Users/86177/Desktop/image/test.mp4");//視頻路徑
while (cap.read(frame))
{
imshow("video",frame);//將讀到的幀顯示出來
datectCarDaw(frame,cascade,2);//將讀到的幀傳入函數(shù)用作識別
waitKey(5);//延時5ms
}
return 0;
}
- 實現(xiàn)效果,總體來說還是相當(dāng)不錯的,相較于幀差法而言,精度提高很多
- 級聯(lián)分類器實現(xiàn),如下圖所示:
- 為了方便對比,再次使用幀差法實現(xiàn),可以看到移動的電動車都被識別進去了,如下圖所示:
- 幀差法實現(xiàn),如下圖所示:
五、總結(jié)?
- 本文核心的內(nèi)容包括:OpenCV級聯(lián)分類器概念、創(chuàng)建自己的級聯(lián)分類器以及使用級聯(lián)分類器對車流進行識別
- 以車輛識別為例子,講解了級聯(lián)分類器相較于幀差法的實戰(zhàn)案例,實際效果還是不錯的
- 車輛識別在我們?nèi)粘I钪蟹浅3R?,是一個很經(jīng)典的案例,本案例采用了較高級別的級聯(lián)分類器,可以實現(xiàn)對車輛較高精度的識別,車輛識別還是需要更大更復(fù)雜的樣本量才能在復(fù)雜環(huán)境下對車輛進行精確的識別,總體而言效果相較于幀差法更加精準(zhǔn)了!新能源汽車的發(fā)展,與車輛識別同理的無人駕駛技術(shù),在針對實際路況的識別難度還是較大的,各大巨頭還在努力研究相關(guān)技術(shù),相信在不久的將來,我們能看到無人駕駛技術(shù)達到較為成熟的一天!
以上就是本文的全部內(nèi)容啦!如果對您有幫助,麻煩點贊啦!收藏啦!歡迎各位評論區(qū)留言??!?文章來源:http://www.zghlxwxcb.cn/news/detail-446154.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-446154.html
到了這里,關(guān)于【OpenCV】車輛識別 目標(biāo)檢測 級聯(lián)分類器 C++ 案例實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!