CV之Haar特徵描述算子-人臉檢測

3.1簡介

Haar-like特徵最早是由Papageorgiou等應用於人臉表示,在2001年,Viola和Jones兩位大牛發表了經典的《Rapid Object Detection using a Boosted Cascade of Simple Features》和《Robust Real-Time Face Detection》,在AdaBoost算法的基礎上,使用Haar-like小波特徵和積分圖方法進行人臉檢測,他倆不是最早使用提出小波特徵的,但是他們設計了針對人臉檢測更有效的特徵,並對AdaBoost訓練出的強分類器進行級聯。這可以說是人臉檢測史上里程碑式的一筆了,也因此當時提出的這個算法被稱爲Viola-Jones檢測器。又過了一段時間,Rainer Lienhart和Jochen Maydt兩位大牛將這個檢測器進行了擴展,最終形成了OpenCV現在的Haar分類器。

3.2 算法理論介紹

3.2.1 Haar-like 特徵

Haar(哈爾)特徵分爲三類:邊緣特徵、線性特徵、中心特徵和對角線特徵,組合成特徵模板。特徵模板內有白色和黑色兩種矩形,並定義該模板的特徵值爲白色矩形像素和減去黑色矩形像素和。Haar特徵值反映了圖像的灰度變化情況。

例如:臉部的一些特徵能由矩形特徵簡單的描述,如:眼睛要比臉頰顏色要深,鼻樑兩側比鼻樑顏色要深,嘴巴比周圍顏色要深等。但矩形特徵只對一些簡單的圖形結構,如邊緣、線段較敏感,所以只能描述特定走向(水平、垂直、對角)的結構。
在這裏插入圖片描述
對於圖中的A, B和D這類特徵,特徵數值計算公式爲:v=Σ白-Σ黑,而對於C來說,計算公式如下:v=Σ白-2*Σ黑;之所以將黑色區域像素和乘以2,是爲了使兩種矩形區域中像素數目一致。我們希望當把矩形放到人臉區域計算出來的特徵值和放到非人臉區域計算出來的特徵值差別越大越好,這樣就可以用來區分人臉和非人臉。

通過改變特徵模板的大小和位置,可在圖像子窗口中窮舉出大量的特徵。上圖的特徵模板稱爲“特徵原型”;特徵原型在圖像子窗口中擴展(平移伸縮)得到的特徵稱爲“矩形特徵”;矩形特徵的值稱爲“特徵值”。
在這裏插入圖片描述上圖中兩個矩形特徵,表示出人臉的某些特徵。比如中間一幅表示眼睛區域的顏色比臉頰區域的顏色深,右邊一幅表示鼻樑兩側比鼻樑的顏色要深。同樣,其他目標,如眼睛等,也可以用一些矩形特徵來表示。使用特徵比單純地使用像素點具有很大的優越性,並且速度更快。

矩形特徵可位於圖像任意位置,大小也可以任意改變,所以矩形特徵值是矩形模版類別、矩形位置和矩形大小這三個因素的函數。故類別、大小和位置的變化,使得很小的檢測窗口含有非常多的矩形特徵,如:在24*24像素大小的檢測窗口內矩形特徵數量可以達到16萬個。這樣就有兩個問題需要解決了:

  • (1)如何快速計算那麼多的特徵?—積分圖大顯神通;

  • (2)哪些矩形特徵纔是對分類器分類最有效的?—如通過AdaBoost算法來訓練。

3.2.2 Haar-like特徵的計算—積分圖

積分圖就是隻遍歷一次圖像就可以求出圖像中所有區域像素和的快速算法,大大的提高了圖像特徵值計算的效率。

積分圖主要的思想是將圖像從起點開始到各個點所形成的矩形區域像素之和作爲一個數組的元素保存在內存中,當要計算某個區域的像素和時可以直接索引數組的元素,不用重新計算這個區域的像素和,從而加快了計算(這有個相應的稱呼,叫做動態規劃算法)。積分圖能夠在多種尺度下,使用相同的時間(常數時間)來計算不同的特徵,因此大大提高了檢測速度。

積分圖是一種能夠描述全局信息的矩陣表示方法。積分圖的構造方式是:位置(𝑖,𝑗)處的值𝑖𝑖(𝑖,𝑗)是原圖像(𝑖,𝑗)左上角方向所有像素𝑓(𝑘,𝑙)的和: ii(i,j)=ki,ljf(k,l)ii(i,j)=ki,ljf(k,l)i i(i, j)=\sum k \leq i, l \leq j f(k, l) i i(i, j)=\sum k \leq i, l \leq j f(k, l) 積分圖構建算法:

  1. 用𝑠(𝑖,𝑗)表示行方向的累加和,初始化𝑠(𝑖,−1)=0;

  2. 使用𝑖𝑖(𝑖,𝑗)表示一個積分圖像,初始化𝑖𝑖(−1,𝑖)=0;

  3. 逐行掃描圖像,遞歸計算每個像素(𝑖,𝑗)行方向的累加和𝑠(𝑖,𝑗)和積分圖像𝑖𝑖(𝑖,𝑗)的值: s(i,j)=s(i,j1)+f(i,j)s(i, j)=s(i, j-1)+f(i, j) ii(i,j)=ii(i1,j)+s(i,j)i i(i, j)=i i(i-1, j)+s(i, j)

  4. 掃描圖像一遍,當到達圖像右下角像素時,積分圖像𝑖𝑖就構建好了。

積分圖構造好之後,圖像中任何矩陣區域像素累加和都可以通過簡單運算得到如圖所示:
在這裏插入圖片描述
設D的四個頂點分別爲α,β,γ,δ則D的像素和可以表示爲 Dsum=ii(α)+ii(β)(ii(γ)+ii(δ))D s u m=i i(\alpha)+i i(\beta)-(i i(\gamma)+i i(\delta)) 而Haar-like特徵值無非就是兩個矩陣像素和的差,同樣可以在常數時間內完成。

3.2.3 計算Haar特徵值

上面已經知道,一個區域的像素值的和,可以由該區域的端點的積分圖來計算。由前面特徵模板的特徵值的定義可以推出,矩形特徵的特徵值可以由特徵端點的積分圖計算出來。以A矩形特徵爲例,如下圖,使用積分圖計算其特徵值:
在這裏插入圖片描述
該矩形特徵的特徵值,由定義,爲區域A的像素值減去區域B的像素值。

  • 區域A的像素值:ii(5)+ii(1)ii(2)ii(4)i i(5)+i i(1)-i i(2)-i i(4)

  • 區域B的像素值:ii(2)+ii(6)ii(5)ii(3)i i(2)+i i(6)-i i(5)-i i(3)

  • 所以:該矩形特徵的特徵值 ii(5)+ii(1)ii(2)ii(4)[ii(6)+ii(2)ii(5)ii(3)]=[ii(5)ii(4)]+[ii(3)ii(2)][ii(2)ii(1)][ii(6)ii(5)]i i(5)+i i(1)-i i(2)-i i(4)-[i i(6)+i i(2)-i i(5)-i i(3)]=[i i(5)-i i(4)]+[i i(3)-i i(2)]-[i i(2)-i i(1)]-[i i(6)-i i(5)]

所以,矩形特徵的特徵值,只與特徵矩形的端點的積分圖有關,而與圖像的座標無關。通過計算特徵矩形的端點的積分圖,再進行簡單的加減運算,就可以得到特徵值,正因爲如此,特徵的計算速度大大提高,也提高了目標的檢測速度。

瞭解了特徵值的計算之後,我們來看看不同的特徵值的含義是什麼。我們選取MIT人臉庫中2706個大小爲20*20的人臉正樣本圖像,計算如下圖所示的Haar特徵:
在這裏插入圖片描述

左邊對應的人眼區域,右邊無具體意義。

在這裏插入圖片描述可以看到,圖中2個不同Haar特徵在同一組樣本中具有不同的特徵值分佈,左邊特徵計算出的特徵值基本都大於0(對樣本的區分度大),而右邊特徵的特徵值基本均勻分佈於0兩側(對樣本的區分度小)。所以,正是由於樣本中Haar特徵值分佈不均勻,導致了不同Haar特徵分類效果不同。顯而易見,對正負樣本區分度越大的特徵分類效果越好,即紅色曲線對應圖中的的左邊Haar特徵分類效果好於右邊Haar特徵。

那麼看到這裏,應該理解了下面2個問題:

(1)在檢測窗口通過平移+縮放可以產生一系列Haar特徵,這些特徵由於位置和大小不同,分類效果也不同;

(2)通過計算Haar特徵的特徵值,可以有將圖像矩陣映射爲1維特徵值,有效實現了降維。

3.2.4 Haar特徵值歸一化(也可以採用標準歸一化)

從上圖我們可以發現,僅僅一個128大小的Haar特徵計算出的特徵值變化範圍從-2000~+6000,跨度非常大。這種跨度大的特性不利於量化評定特徵值,所以需要進行“歸一化”,壓縮特徵值範圍。假設當前檢測窗口中的圖像像素爲𝑖(𝑥,𝑦)i(x,y),當前檢測窗口爲𝑤∗ℎw∗h大小(例如上圖中爲2020大小),OpenCV採用如下方式“歸一化”:

  1. 計算檢測窗口中圖像的灰度值和灰度值平方和: sum=i(x,y) sum=\sum i(x,y)

sqsum=i2(x,y) sq_{sum}=\sum i^2(x,y)

  1. 計算平均值: mean=sumwh mean = \frac{sum}{w*h}

sqmean=sqsumwh sq_{mean}=\frac{sq_{sum}}{w*h}

  1. 計算歸一化因子: varNormFactor=sqmeanmean2 varNormFactor=\sqrt{sq_{mean}-mean^2}
  2. 歸一化特徵值: normValue=featureValuevarNormFactor normValue=\frac{featureValue}{varNormFactor} 之後使用歸一化的特徵值𝑛𝑜𝑟𝑚𝑉𝑎𝑙𝑢𝑒與閾值對比。

3.2.5 Adaboost級聯分類器

前面幾塊內容我們分析了Haar特徵,積分圖、特徵值計算。這裏則主要分析一下2個內容:

(1)OpenCV中的Adaboost級聯分類器的結構,包括強分類器和弱分類器的形式;

(2)OpenCV自帶的XML分類器中各項參數,如internalNodes和leafValues標籤裏面的一大堆數字的意義。

  1. 級聯分類器
    級聯分類模型是樹狀結構可以用下圖表示:

在這裏插入圖片描述
其中每一個stage都代表一級強分類器。當檢測窗口通過所有的強分類器時才被認爲是正樣本,否則拒絕。實際上,不僅強分類器是樹狀結構,強分類器中的每一個弱分類器也是樹狀結構。由於每一個強分類器對負樣本的判別準確度非常高,所以一旦發現檢測到的目標位負樣本,就不在繼續調用下面的強分類器,減少了很多的檢測時間。因爲一幅圖像中待檢測的區域很多都是負樣本,這樣由級聯分類器在分類器的初期就拋棄了很多負樣本的複雜檢測,所以級聯分類器的速度是非常快的;只有正樣本纔會送到下一個強分類器進行再次檢驗,這樣就保證了最後輸出的正樣本的僞正(false positive)的可能性非常低。

  1. 級聯分類器的訓練

級聯分類器是如何訓練的呢?首先需要訓練出每一個弱分類器,然後把每個弱分類器按照一定的組合策略,得到一個強分類器,我們訓練出多個強分類器,然後按照級聯的方式把它們組合在一塊,就會得到我們最終想要的Haar分類器。

在這裏插入圖片描述
一個弱分類器就是一個基本和上圖類似的決策樹,最基本的弱分類器只包含一個Haar-like特徵,也就是它的決策樹只有一層,被稱爲樹樁(stump)。

以20*20圖像爲例,78,460個特徵,如果直接利用AdaBoost訓練,那麼工作量是極其極其巨大的。

所以必須有個篩選的過程,篩選出T個優秀的特徵值(即最優弱分類器),然後把這個T個最優弱分類器傳給AdaBoost進行訓練。

現在有人臉樣本2000張,非人臉樣本4000張,這些樣本都經過了歸一化,大小都是20x20的圖像。那麼,對於78,460中的任一特徵fif_i,我們計算該特徵在這2000人臉樣本、4000非人臉樣本上的值,這樣就得到6000個特徵值。將這些特徵值排序,然後選取一個最佳的特徵值,在該特徵值下,對於特徵fif_i來說,樣本的加權錯誤率最低。

在確定了訓練子窗口中(20x20的圖像)的矩形特徵數量(78,460)和特徵值後,需要對每一個特徵ff,訓練一個弱分類器h(𝑥,𝑓,ρ,Θ) : h(x,f,ρ,Θ)={1,ρf(x)<ρΘ0, other h(x, f, \rho, \Theta)=\left\{\begin{array}{l} 1, \rho f(x)<\rho \Theta \\ 0, \text { other } \end{array}\right.
其中𝑓爲特徵,Θ爲閾值,ρ指示不等號的方向,𝑥代表一個檢測子窗口。對每個特徵𝑓,訓練一個弱分類器ℎ(𝑥,𝑓,ρ,Θ),就是確定𝑓的最優閾值,使得這個弱分類器對所有的訓練樣本分類誤差最低。

在弱分類器訓練的過程中,訓練採用的照片一般都是20*20左右的小圖片,弱分類器訓練的具體步驟:

  1. 對於每個特徵 𝑓,計算所有訓練樣本的特徵值,並將其排序:

  2. 掃描一遍排好序的特徵值,對排好序的表中的每個元素,計算下面四個值:
    計算全部正例的權重和𝑇+;
    計算全部負例的權重和𝑇−;
    計算該元素前之前的正例的權重和𝑆+;
    計算該元素前之前的負例的權重和𝑆−;

  3. 選取當前元素的特徵值Fk,jF_{k,j}和它前面的一個特徵值Fk,j1F_{k,j-1}之間的數作爲閾值,所得到的弱分類器就在當前元素處把樣本分開 —— 也就是說這個閾值對應的弱分類器將當前元素前的所有元素分爲人臉(或非人臉),而把當前元素後(含)的所有元素分爲非人臉(或人臉)。該閾值的分類誤差爲: e=min(S++(TS),S+(T+S+)) e=min(S^++(T^--S^-),S^-+(T^+-S^+)) 於是,通過把這個排序表從頭到尾掃描一遍就可以爲弱分類器選擇使分類誤差最小的閾值(最優閾值),也就是選取了一個最佳弱分類器。
    在這裏插入圖片描述
    由於一共有78,460個特徵、因此會得到78,460個最優弱分類器,在78,460個特徵中,我們選取錯誤率最低的特徵,用來判斷人臉,同時用此分類器對樣本進行分類,並更新樣本的權重。

強分類器的訓練步驟:

  1. 給定訓練樣本集(xi,yi),i=1,2,3,N\left(x_{i}, y_{i}\right), i=1,2,3, \ldots N,共N個樣本,yiy_i取值爲0(負樣本)或者1(正樣本);設人臉正樣本的數量爲n1n_1,負樣本數量爲n2n_2; T爲訓練的最大循環次數;

  2. 初始化樣本權重爲1n1+n2\frac{1}{n_1+n_2},即爲訓練樣本的初始概率分佈;

  3. for t=1,...Tfor\ t=1,...T: ①權重歸一化 ωt,i=ωt,ij1nωt,j ω_{t,i}=\frac{ω_{t,i}}{\sum\limits_{j-1}^{n}ω_{t,j}}

②對每個(種)特徵𝑓𝑗fj,訓練一個弱分類器ℎ𝑗hj(如上),每個分類器只使用一種Haar特徵進行訓練。分類誤差爲: εj=iωihj(xi)yi ε_j=\sum\limits_{i}ω_i|h_j(x_i)-y_i| ③從②確定的弱分類器中,找出一個具有最小分類誤差的弱分類器hth_t; ④更新每個樣本對應的權重: ωt+1,i=ωt,iβt1ei \omega_{t+1, i}=\omega_{t, i} \beta_{t}^{1-e_{i}}

這裏,如果樣本xix_i被正確分類,則ei=0e_i=0,否則ei=1e_i=1,而 βt=εt1εt \beta_t=\frac{ε_t}{1-ε_t}

  1. 最終形成的強分類器組成爲h(x)={1t1Tαtht(x)1/2t=1Tαt0 otherwise h(x)=\left\{\begin{array}{cc} 1 & \sum_{t-1}^{T} \alpha_{t} h_{t}(x) \geq 1 / 2 \sum_{t=1}^{T} \alpha_{t} \\ 0 & \text { otherwise } \end{array}\right. 其中: αt=log1βt \alpha_t=log\frac{1}{\beta_t}

在使用Adaboost算法訓練分類器之前,需要準備好正、負樣本,根據樣本特點選擇和構造特徵集。由算法的訓練過程可知,當弱分類器對樣本分類正確,樣本的權重會減小;而分類錯誤時,樣本的權重會增加。這樣,後面的分類器會加強對錯分樣本的訓練。最後,組合所有的弱分類器形成強分類器,通過比較這些弱分類器投票的加權和與平均投票結果來檢測圖像。

3、級聯分類器的檢測

訓練級聯分類器的目的就是爲了檢測的時候,更加準確,這涉及到Haar分類器的另一個體系,檢測體系,檢測體系是以現實中的一幅大圖片作爲輸入,然後對圖片中進行多區域,多尺度的檢測,所謂多區域,是要對圖片劃分多塊,對每個塊進行檢測,由於訓練的時候用的照片一般都是20*20左右的小圖片,所以對於大的人臉,還需要進行多尺度的檢測,多尺度檢測機制一般有兩種策略:

一種是不改變搜索窗口的大小,而不斷縮放圖片,這種方法顯然需要對每個縮放後的圖片進行區域特徵值的運算,效率不高;

另一種方法,不斷擴大搜索窗口,進行搜索,解決了第一種方法的弱勢。
在區域放大的過程中會出現同一個人臉被多次檢測,這需要進行區域的合併,這裏不作探討。

無論哪一種搜索方法,都會爲輸入圖片輸出大量的子窗口圖像,這些子窗口圖像經過篩選式級聯分類器會不斷地被每一個節點篩選,拋棄或通過。

4、總結
從上面所述內容我們可以總結Haar分類器訓練的五大步驟:

  1. 準備人臉、非人臉樣本集;

  2. 計算特徵值和積分圖;

  3. 篩選出T個優秀的特徵值(即最優弱分類器);

  4. 把這個T個最優弱分類器傳給AdaBoost進行訓練。

  5. 級聯,也就是強分類器的強強聯手。

在開始前,一定要記住,以20*20窗口爲例,就有78,460的特徵數量,篩選出T個優秀的特徵值(即最優弱分類器),然後把這個T個最優弱分類器傳給AdaBoost進行訓練得到一個強分類器,最後將強分類器進行級聯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章