【人臉識別7】haar+CART+Adaboost+Cascade訓練過程分析
【人臉識別7】haar+CART+Adaboost+Cascade訓練過程分析
人臉檢測分類器可以總結為:
人臉檢測分類器=haar-like (特徵)+CART(弱)+ Adaboost(強) + Cascade(級聯)
下面將從以下幾個問題入手,各個擊破:
1.什麼是Haar特徵?為什麼使用feature而不是直接使用pixels?
2.什麼是CART分類迴歸樹?CART在本節的訓練中有何作用?
3.什麼是弱分類器?在本節中,具體是指什麼?如何得到弱分類器(CART)?
4.強分類器是什麼?如何訓練得到(ADaboost)?結構如何?
5.Cascade是什麼?有什麼作用?
6.整個人臉檢測分類器的組成?詳述訓練過程 haar+CART+adaboost+cascade?
一、帶著問題來學習
1.什麼是Haar特徵?為什麼使用feature而不是直接使用pixels?
Haar特徵:
為什麼使用feature而不是直接使用pixels?
我們的目標檢測過程是根據簡單特徵的值對影象進行分類。使用特徵而不是直接使用畫素有很多動機。
(1)特徵可以用來編碼特定領域的知識,而這些知識是很難用有限數量的培訓資料來學習的。
(2)對於這個系統使用特徵,還有第二個關鍵的動機:基於特徵的系統的執行速度比基於畫素的系統要快得多。
在本分類器中,所涉及的haar特徵具體引數如下:
typedef struct CvTHaarFeature
{
char desc[CV_HAAR_FEATURE_DESC_MAX];
int tilted;/*haar特徵包括一個tilted標誌,tilted = 0 是直立型特徵; tilted =1 是45度特徵
特徵是2-3 個帶權重的矩形,如果rect[2].weight != 0 則特徵是3個矩形,否則是2 個矩形*/
struct
{
CvRect r; //矩形
float weight; //權值
} rect[CV_HAAR_FEATURE_MAX];
} CvTHaarFeature; //haar特徵
typedef struct CvFastHaarFeature
{
int tilted;
struct
{
int p0, p1, p2, p3;
float weight;
} rect[CV_HAAR_FEATURE_MAX];
} CvFastHaarFeature;
typedef struct CvIntHaarFeatures
{
CvSize winsize;
int count;
CvTHaarFeature* feature;
CvFastHaarFeature* fastfeature;
} CvIntHaarFeatures;
2、什麼是CART分類迴歸樹?CART在本節的訓練中有何作用?
本節中,所用的CART(分類迴歸樹)是一種決策樹學習演算法。分類迴歸樹(classification and regression tree,CART)模型由Breiman等人在1984年提出,是應用廣泛的決策樹學習方法。CART同樣由特徵選擇、樹的生成以及剪枝組成,既可以用於分類也可以用於迴歸。
CART的演算法思想是:CART演算法採用的是一種二分遞迴分割的技術,將當前樣本分成兩個子樣本集,使得生成的非葉子節點都有兩個分支。因此CART實際上是一棵二叉樹。
特點:當CART是分類樹的時候,採用GINI值作為分裂節點的依據,當CART作為迴歸樹的時候,使用樣本的最小方差作為分裂節點的依據
具體關於CART的介紹,可看:https://blog.csdn.net/gzj_1101/article/details/78355234
在本節中,我們主要使用CART分類功能。假設我們使用三個Haar-like特徵f1,f2,f3來判斷輸入資料是否為人臉,可以建立如下決策樹:(下圖相當於是CART tree:較優弱分類器)
可以看出,在分類的應用中,CART每個非葉子節點都表示一種判斷,每個路徑代表一種判斷的輸出,每個葉子節點代表一種類別,並作為最終判斷的結果。
CART在本節的訓練中有何作用?
CART在本節的訓練中,可以將最基本的弱分類器,通過訓練,找到最優閾值,使之成為可用的較優弱分類器。(下面會有詳細的CART訓練過程)
3.什麼是弱分類器?在本節中,具體是指什麼?如何得到弱分類器?
弱分類器(弱學習演算法),是一個學習演算法對一組概念的識別比隨機分類的正確率高一點,強分類器(強學習演算法),就是指一個學習演算法對一組概念的識別率很高。
弱分類器分為最基本弱分類器和最優弱分類器。最基本的弱分類器,只含有一個haar-like特徵,在決策樹CART結構中,它相當於只有一層,被稱為“樹樁”(stump),如下圖所示。
由於單特徵的分類器(只有一個樹樁)太簡陋了,可能並不比隨機判斷的效果好。所以,採用了CART的決策樹形式,單節點的基本分類器通過訓練可以優化為有更高的辨別力的分類器,即為弱分類器(CARTHaarClf),最終弱分類器形式一般為多節點形式,如下。
但本節所採用的是樹樁型CART樹。所以一個CART樹,僅有一個樹樁節點(單個特徵),所以最終的弱分類器形式,如下圖所示:
那一個最基本的弱分類器,如何成為一個較優的弱分類器呢?
最基本的弱分類器可能只是一個最基本的Haar-like特徵,計算輸入影象的Haar-like特徵值,和最基本的弱分類器的閾值比較,以此來判斷輸入影象是不是人臉,然而這個弱分類器太簡陋了,可能並不比隨機判斷的效果好。弱學習演算法被設計成選擇單個矩形特性,它可以最好地分離正樣本和負樣本的例子。對於每個特徵,弱學習器決定了最優閾值分類函式,這樣被錯誤分類的樣本數最少。因此,一個弱分類器hj(x)包括一個影象的子視窗x、一個特徵fj、一個閾值θj和一個指示不等號方向的極性pj(作用是控制不等式的方向,使得不等式都是<號,形式方便)組成,:
最重要的就是如何決定每個結點判斷的輸出,要比較輸入圖片的特徵值和弱分類器中特徵,一定需要一個閾值,當輸入圖片的特徵值大於該閾值時才判定其為人臉。訓練最優弱分類器的過程實際上就是在尋找合適的分類器閾值,使該分類器對所有樣本的判讀誤差最低。
具體尋找最優閾值的過程:
弱分類器的具體引數,程式碼如下:
/*
* CART classifier
*/
typedef struct CvCARTHaarClassifier
{
CV_INT_HAAR_CLASSIFIER_FIELDS()
int count;
int* compidx;
CvTHaarFeature* feature;// 特徵(指標相當於陣列,表明可以有多層CART tree,但在本訓練中,採用樹樁結構,即一個CARTHaarClf,一個特徵)
CvFastHaarFeature* fastfeature;
float* threshold;//閾值
int* left;//左葉子值
int* right;//右葉子值
float* val;//計算值
} CvCARTHaarClassifier;
4.強分類器是什麼?如何訓練得到?結構如何?
在任何影象子視窗中,haar-like的特徵的總數非常大,遠遠大於畫素的數量。為了確保快速分類,學習過程必須排除大部分可用的特徵,並將重點放在一小部分關鍵特徵上。在Tieu和Viola的工作的激勵下,通過對AdaBoost程式的簡單修改,特徵選擇被實現了:通過使用AdaBoost選擇少量重要特徵來構造強分類器,即通過組合弱分類器得到了強分類器。
其中,弱分類器的分類誤差越小(效能越好),在強分類器中所佔的比重越大。即αt 越大。
如何訓練得到強分類器?
每個弱分類器只能依賴於單個特徵。因此,選擇一個新的弱分類器的提升(boosting)過程的每個階段,都可以被看作是一個特徵選擇過程。Adalboost提供了一種有效的學習演算法和強大的邊界泛化效能。Adalboos演算法具體過程如下:
對於人臉檢測的任務,AdaBoost選擇的初始矩形特徵是有意義且容易解釋的。第一個特徵選擇似乎專注於眼睛比鼻子和臉頰更暗這一屬性 (參見圖4)。這個特徵與檢測子視窗相比相對較大,並且應該對臉的大小和位置不敏感。選擇的第二個特徵依賴於眼睛比鼻樑更暗的屬性。
圖4:AdaBoost選擇的第一個和第二個特徵。這兩個特徵顯示在最上面一行,然後在底部的一個典型的訓練面上覆蓋。第一個特徵是測量眼睛區域和上頰區域之間的強度差異。該特徵利用觀察到的觀察結果,即眼睛區域通常比臉頰更暗。第二個特徵是將眼睛區域的強度與鼻樑上的強度進行比較。
想看更詳細的Adalboost的演算法介紹,請戳:https://blog.csdn.net/u012679707/article/details/80369772
強分類器(stageHaarClf)的引數,見程式碼:
/* internal stage classifier */
typedef struct CvStageHaarClassifier
{
CV_INT_HAAR_CLASSIFIER_FIELDS()
int count;
float threshold;
CvIntHaarClassifier** classifier;
} CvStageHaarClassifier;
強分類器結構:
xml檔案中的stageHaarClf:
5.Cascade是什麼?有什麼作用?整個人臉檢測分類器的組成?
Cascade是什麼?
檢測過程的整體形式是一個退化的決策樹,我們稱之為“cascade”(級聯分類器,見圖5)。第一個分類器的結果如果為正(positive result),則將觸發對第二個分類器的評估,它也被調整以達到很高的檢測率。第二個分類器的正的結果觸發第三個分類器,以此類推。任何時候的負結果(A negative)都會導致子視窗立即被拒絕。
級聯的階段是通過使用Adaboost訓練分類器,然後調整閾值以減少errar rate來構建的。注意,預設的Adaboost閾值被設計為在訓練資料上產生低錯誤率。一般來說,較低的閾值會產生更高的檢測率和更高的假正率。
圖5:檢測級聯的示意圖。每個子視窗都應用了一系列分類器。最初的分類器消除了大量的負面例子,且只需很少的處理。隨後的層消除了額外的負面例子,但需要額外的計算。經過幾個階段的處理後,子視窗的數量已經大大減少了。進一步的處理可以採取任何形式,例如附加級聯階段(如在我們的檢測系統中)或使用另一種可選擇的檢測系統。
TreeCascadeClf結構:
HaarCascadeTree結構:
CascadeTree
{
Stage 0:
{
Tree 0:
Tree 1:
…
Tree T0:
}
Stage 1:
{
Tree 0:
Tree 1:
…
Tree T1:
}
……
Stage N:
……
}
想要了解人臉檢測分類器的具體內容,開啟cascade.xml檔案,一看便知:
這是我自己訓練的分類器,選擇的是樹樁型(stump),每棵CART樹只有root node,沒有葉子節點。所以一個CART弱分類器就是一個樹樁stump,包含一個特徵。若選擇分裂節點不為1,則是多節點樹,每個弱分類器將包含多個node,也就含有多個特徵(每個cart tree node帶有一個特徵)。
具體設定可見【附錄1】,訓練haartraing時,引數分裂子節點設定成了1,則表明樹高為1,即只有樹樁;預設是2,則表明樹高為2。
Cascade有什麼作用?
在一個級聯結構中,將更復雜的分類器組合在一起(強強聯手),通過對影象中有”希望“的區域的關注,極大地提高了檢測器的速度。第一個分類器的結果如果為正(positive result),則將觸發對第二個分類器的評估,它也被調整閾值以達到很高的檢測率。第二個分類器的正的結果觸發第三個分類器,以此類推。任何時候的負結果(A negative)都會導致子視窗立即被拒絕。這就使得待檢測區域急速縮小,提升了檢測速度,節省了大量時間。
如何訓練得到CascadeTree?
級聯訓練過程涉及兩種型別的權衡(折衷)。在大多數情況下,具有更多特徵的分類器將獲得更高的檢測率和更低的假陽性率。與此同時,具有更多特徵的分類器需要更多的時間來計算。原則上,我們可以定義一個優化框架,其中:
i)分類器迭代階數
ii)每個迭代階段(stage)的特徵數量
iii)每個階段的閾值,為了最小化預期的被評估特性的數量而被改變。
不幸的是,找到這種最優的方法是一個非常困難的問題。
在實踐中,一個非常簡單的框架被用來產生一個高效的分類器。級聯的每個階段都降低了假正率,降低了檢測率。選擇一個目標,以減少誤報和最大化減少檢測量。具體的訓練過程,包括弱分類的訓練,和強分類的訓練。
(1)每個階段都通過新增特徵feature(弱分類器)來訓練,直到目標檢測和假陽性率得到滿足(這些率rate是通過在驗證集中測試檢測器來確定的)。
(2)在達到假陽性和檢測率的總體目標之前,增加迭代數目(stage,強分類器)。直到滿足條件,停止迭代。
具體訓練過程如下:
/* internal cascade classifier */
typedef struct CvCascadeHaarClassifier
{
CV_INT_HAAR_CLASSIFIER_FIELDS()
int count;
CvIntHaarClassifier** classifier;
} CvCascadeHaarClassifier;
/* internal tree cascade classifier node */
typedef struct CvTreeCascadeNode
{
CvStageHaarClassifier* stage;
struct CvTreeCascadeNode* next;
struct CvTreeCascadeNode* child;
struct CvTreeCascadeNode* parent;
struct CvTreeCascadeNode* next_same_level;
struct CvTreeCascadeNode* child_eval;
int idx;
int leaf;
} CvTreeCascadeNode;
6.整個人臉檢測分類器的組成?人臉檢測分類器可以總結為:
人臉檢測分類器=haar-like (特徵)+CART(弱)+ Adaboost(強) + Cascade(級聯)
haar-like+CART+adaboost+Cascade 訓練過程分析圖:
整個訓練過程原始碼簡摘:
獲取訓練的樣本資料(正和負)-----計運算元視窗特徵值----訓練弱分類器----訓練強分類器----訓練級聯分類器----輸出訓練好的人臉檢測分類器
原始碼分析:
//建立TreeCasecadeClf
cvCreateTreeCascadeClassifier( dirname, vecname, bgname,
npos, nneg, nstages, mem,
nsplits,
minhitrate, maxfalsealarm, weightfraction,
mode, symmetric,
equalweights, width, height,
boosttype, stumperror,
maxtreesplits, minpos, bg_vecfile );
haar_features = icvCreateIntHaarFeatures( winsize, mode, symmetric );
training_data = icvCreateHaarTrainingData( winsize, npos + nneg );
//從vec正樣本檔案獲取訓練資料
poscount = icvGetHaarTrainingDataFromVec( training_data, 0, npos,
(CvIntHaarClassifier*) tcc, vecfilename, &consumed );
// consumed = consumed + thread_consumed_count(執行緒消耗數)
printf( "POS: %d %d %f\n", poscount, consumed, ((double) poscount)/consumed );
//從負樣本檔案獲取訓練資料
negcount = icvGetHaarTrainingDataFromBG( training_data, poscount, nneg,
(CvIntHaarClassifier*) tcc, &false_alarm, bg_vecfile ? bgfilename : NULL );
printf( "NEG: %d %g\n", negcount, false_alarm );
printf( "BACKGROUND PROCESSING TIME: %.2f\n", (proctime + TIME( 0 )) );
//Adaboost
/* precalculate feature values 預先計算特徵值*/
icvPrecalculate( training_data, haar_features, numprecalculated );
printf( "Precalculation time: %.2f\n", (proctime + TIME( 0 )) );
/* train stage classifier using all positive samples 使用所有正樣本訓練強分類器TreeCascadeNode=stage*/
CV_CALL( single_cluster = icvCreateTreeCascadeNode() );
//訓練每一強分類器stage中的弱分類器CartTree
single_cluster->stage = (CvStageHaarClassifier*) icvCreateCARTStageClassifier(
training_data, NULL, haar_features,
minhitrate, maxfalsealarm, symmetric,
weightfraction, numsplits, (CvBoostType) boosttype,
(CvStumpError) stumperror, 0 );
printf( "Stage training time: %.2f\n", (proctime + TIME( 0 )) );
---------------------------------------------- 附錄 --------------------------------------------------------------
【附錄1】訓練haartraing時,引數分裂子節點設定成了1,則表明樹高為1,即只有樹樁;預設是2,則表明樹高為2。
------------------------------------------- END -------------------------------------
參考:
(人臉檢測過程分析 非常棒!) http://www.cnblogs.com/ello/archive/2012/04/28/2475419.html
(haar原始碼) https://blog.csdn.net/u011783201/article/details/52184093
(CART) https://blog.csdn.net/acdreamers/article/details/44664481
人臉檢測經典論文翻譯 https://blog.csdn.net/u012679707/article/details/80626775
相關文章
- opencv 人臉識別OpenCV
- OpenCV — 人臉識別OpenCV
- 人臉識別專案打包成exe的過程遇到的問題
- [Python急救站]人臉識別技術練習Python
- 人臉檢測識別,人臉檢測,人臉識別,離線檢測,C#原始碼C#原始碼
- 人臉識別損失函式疏理與分析函式
- C#人臉識別入門篇-STEP BY STEP人臉識別--入門篇C#
- 智慧人臉識別門禁系統開發,人臉識別開鎖流程
- OpenPose訓練過程解析(2)
- 人臉識別之特徵臉方法(Eigenface)特徵
- 前端人臉識別--兩張臉相似度前端
- 人臉活體檢測人臉識別:眨眼+張口
- 乾貨 | AI人臉識別之人臉搜尋AI
- 人臉識別智慧考勤系統開發_人臉識別考勤管理系統開發
- 視覺化 Keras 訓練過程視覺化Keras
- 人臉識別技術應用
- 前端如何玩轉人臉識別前端
- python—呼叫API人臉識別PythonAPI
- 從零玩轉人臉識別
- 人臉識別之人臉檢測的重要性
- Yolov8訓練識別模型YOLO模型
- python ubuntu dlib人臉識別3-人臉對齊PythonUbuntu
- 保障人臉安全!頂象釋出《人臉識別安全白皮書》
- IOS人臉識別開發入門教程--人臉檢測篇iOS
- 人臉識別之Python DLib庫進行人臉關鍵點識別Python
- 刷臉支付人臉識別特徵點越多是別越精確特徵
- 中國人臉識別產業鏈全景圖產業
- Python人臉識別微笑檢測Python
- 刪除十億人臉資料,Facebook關閉人臉識別系統
- 人臉識別與人體動作識別技術及應用pdf
- 人臉識別 -- 活體檢測(張嘴搖頭識別)
- 人臉識別 — 活體檢測(張嘴搖頭識別)
- 98.52% vs 97.53%:人臉識別演算法終於超過了人類本身演算法
- 人臉識別技術看這一篇就夠了(附國內人臉識別20強公司)
- AI+慈善 ▏人臉識別+人臉模擬助力失散親人找到回家的路AI
- 從零玩轉人臉識別之RGB人臉活體檢測
- 【基於PCA的人臉識別演算法】從QR分解到PCA,再到人臉識別PCA演算法
- OpenCV-Python 人臉眼睛嘴識別OpenCVPython