人臉檢測屬於計算機視覺的範疇,早期人們的主要研究方向是人臉識別,即根據人臉來識別人物的身份,後來在複雜背景下的人臉檢測需求愈來愈大,人臉檢測也逐漸做爲一個單獨的研究方向發展起來。html
目前人臉檢測的方法主要有兩大類:基於知識和基於統計。算法
基於知識的方法:主要利用先驗知識將人臉看做器官特徵的組合,根據眼睛、眉毛、嘴巴、鼻子等器官的特徵以及相互之間的幾何位置關係來檢測人臉。主要包括模板匹配、人臉特徵、形狀與邊緣、紋理特性、顏色特徵等方法。api
基於統計的方法:將人臉看做一個總體的模式——二維像素矩陣,從統計的觀點經過大量人臉圖像樣本構造人臉模式空間,根據類似度量來判斷人臉是否存在。主要包括主成分分析與特徵臉、神經網絡方法、支持向量機、隱馬爾可夫模型、Adaboost算法等。數組
本文中介紹的Haar分類器方法,包含了Adaboost算法,稍候會對這一算法作詳細介紹。所謂分類器,在這裏就是指對人臉和非人臉進行分類的算法,在機器學習領域,不少算法都是對事物進行分類、聚類的過程。緩存
咱們要探討的Haar分類器其實是Boosting算法的一個應用,Haar分類器用到了Boosting算法中的AdaBoost算法,只是把AdaBoost算法訓練出的強分類器進行了級聯,而且在底層的特徵提取中採用了高效率的矩形特徵和積分圖方法,這裏涉及到的幾個名詞接下來會具體討論。網絡
在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分類器。機器學習
AdaBoost是Freund和Schapire在1995年提出的算法,是對傳統Boosting算法的一大提高。Boosting算法的核心思想,是將弱學習方法提高成強學習算法,也就是「三個臭皮匠頂一個諸葛亮」。ide
Haar分類器 = Haar-like特徵 + 積分圖方法 + AdaBoost +級聯;函數
Haar分類器算法的要點以下:post
Haar(哈爾)特徵分爲三類:邊緣特徵、線性特徵、中心特徵和對角線特徵,組合成特徵模板。特徵模板內有白色和黑色兩種矩形,並定義該模板的特徵值爲白色矩形像素和減去黑色矩形像素和。Haar特徵值反映了圖像的灰度變化狀況。例如:臉部的一些特徵能由矩形特徵簡單的描述,如:眼睛要比臉頰顏色要深,鼻樑兩側比鼻樑顏色要深,嘴巴比周圍顏色要深等。但矩形特徵只對一些簡單的圖形結構,如邊緣、線段較敏感,因此只能描述特定走向(水平、垂直、對角)的結構。
對於圖中的A, B和D這類特徵,特徵數值計算公式爲:v=Σ白-Σ黑,而對於C來講,計算公式以下:v=Σ白-2*Σ黑;之因此將黑色區域像素和乘以2,是爲了使兩種矩形區域中像素數目一致。咱們但願當把矩形放到人臉區域計算出來的特徵值和放到非人臉區域計算出來的特徵值差異越大越好,這樣就能夠用來區分人臉和非人臉。
經過改變特徵模板的大小和位置,可在圖像子窗口中窮舉出大量的特徵。上圖的特徵模板稱爲「特徵原型」;特徵原型在圖像子窗口中擴展(平移伸縮)獲得的特徵稱爲「矩形特徵」;矩形特徵的值稱爲「特徵值」。
上圖中兩個矩形特徵,表示出人臉的某些特徵。好比中間一幅表示眼睛區域的顏色比臉頰區域的顏色深,右邊一幅表示鼻樑兩側比鼻樑的顏色要深。一樣,其餘目標,如眼睛等,也能夠用一些矩形特徵來表示。使用特徵比單純地使用像素點具備很大的優越性,而且速度更快。
矩形特徵可位於圖像任意位置,大小也能夠任意改變,因此矩形特徵值是矩形模版類別、矩形位置和矩形大小這三個因素的函數。故類別、大小和位置的變化,使得很小的檢測窗口含有很是多的矩形特徵,如:在24*24像素大小的檢測窗口內矩形特徵數量能夠達到16萬個。這樣就有兩個問題須要解決了:(1)如何快速計算那麼多的特徵?---積分圖大顯神通;(2)哪些矩形特徵纔是對分類器分類最有效的?---如經過AdaBoost算法來訓練。
積分圖就是隻遍歷一次圖像就能夠求出圖像中全部區域像素和的快速算法,大大的提升了圖像特徵值計算的效率。
積分圖主要的思想是將圖像從起點開始到各個點所造成的矩形區域像素之和做爲一個數組的元素保存在內存中,當要計算某個區域的像素和時能夠直接索引數組的元素,不用從新計算這個區域的像素和,從而加快了計算(這有個相應的稱呼,叫作動態規劃算法)。積分圖可以在多種尺度下,使用相同的時間(常數時間)來計算不一樣的特徵,所以大大提升了檢測速度。
積分圖是一種可以描述全局信息的矩陣表示方法。積分圖的構造方式是位置$(i,j)$處的值$ii(i,j)$是原圖像$(i,j)$左上角方向全部像素$f(k,l)$的和:$$ii(i,j)=\sum\limits_{k≤i,l≤j}f(k,l)$$
積分圖構建算法:
一、用$s(i,j)$表示行方向的累加和,初始化$s(i,-1)=0$;
二、使用$ii(i,j)$表示一個積分圖像,初始化$ii(-1,i)$=0;
三、逐行掃描圖像,遞歸計算每一個像素$(i,j)$行方向的累加和$s(i,j)$和積分圖像$ii(i,j)$的值:
$$s(i,j)=s(i,j-1)+f(i,j)$$
$$ii(i,j)=ii(i-1,j)+s(i,j)$$
四、掃描圖像一遍,當到達圖像右下角像素時,積分圖像$ii$就構建好了。
積分圖構造好以後,圖像中任何矩陣區域像素累加和均可以經過簡單運算獲得如圖所示:
設D的四個頂點分別爲α,β,γ,δ則D的像素和能夠表示位$$D_{sum}=ii(α)+ii(β)-(ii(γ)+ii(δ))$$
而Haar-like特徵值無非就是兩個矩陣像素和的差,一樣能夠在常數時間內完成。
上面已經知道,一個區域的像素值的和,能夠由該區域的端點的積分圖來計算。由前面特徵模板的特徵值的定義能夠推出,矩形特徵的特徵值能夠由特徵端點的積分圖計算出來。以A矩形特徵爲例,以下圖,使用積分圖計算其特徵值:
該矩形特徵的特徵值,由定義,爲區域A的像素值減去區域B的像素值。
區域A的像素值:$$ii(5)+ii(1)-ii(2)-ii(4)$$
區域B的像素值:$$ii(6)+ii(2)-ii(5)-ii(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)]$$
因此,矩形特徵的特徵值,只與特徵矩形的端點的積分圖有關,而與圖像的座標無關。經過計算特徵矩形的端點的積分圖,再進行簡單的加減運算,就能夠獲得特徵值,正由於如此,特徵的計算速度大大提升,也提升了目標的檢測速度。
瞭解了特徵值的計算以後,咱們來看看不一樣的特徵值的含義是什麼。咱們選取MIT人臉庫中2706個大小爲20*20的人臉正樣本圖像,計算以下圖所示的Haar特徵:
左邊對應的人眼區域,右邊無具體意義。
能夠看到,圖中2個不一樣Haar特徵在同一組樣本中具備不一樣的特徵值分佈,左邊特徵計算出的特徵值基本都大於0(對樣本的區分度大),而右邊特徵的特徵值基本均勻分佈於0兩側(對樣本的區分度小)。因此,正是因爲樣本中Haar特徵值分佈不均勻,致使了不一樣Haar特徵分類效果不一樣。顯而易見,對正負樣本區分度越大的特徵分類效果越好,即紅色曲線對應圖中的的左邊Haar特徵分類效果好於右邊Haar特徵。
那麼看到這裏,應該理解了下面2個問題:
(1)在檢測窗口經過平移+縮放能夠產生一系列Haar特徵,這些特徵因爲位置和大小不一樣,分類效果也不一樣;
(2)經過計算Haar特徵的特徵值,能夠有將圖像矩陣映射爲1維特徵值,有效實現了降維。
從上圖咱們能夠發現,僅僅一個12*8大小的Haar特徵計算出的特徵值變化範圍從-2000~+6000,跨度很是大。這種跨度大的特性不利於量化評定特徵值,因此須要進行「歸一化」,壓縮特徵值範圍。假設當前檢測窗口中的圖像像素爲$i(x,y)$,當前檢測窗口爲$w*h$大小(例如上圖中爲20*20大小),OpenCV採用以下方式「歸一化」:
一、計算檢測窗口中圖像的灰度值和灰度值平方和:
$$sum=\sum i(x,y)$$
$$sq_{sum}=\sum i^2(x,y)$$
二、計算平均值:
$$mean = \frac{sum}{w*h}$$
$$sq_{mean}=\frac{sq_{sum}}{w*h}$$
三、計算歸一化因子:
$$varNormFactor=\sqrt{sq_{mean}-mean^2}$$
四、歸一化特徵值:
$$normValue=\frac{featureValue}{varNormFactor}$$
以後使用歸一化的特徵值$normValue$與閾值對比。
前面幾塊內容咱們分析了Haar特徵,積分圖、特徵值計算。這裏則主要分析一下2個內容:
(1)OpenCV中的Adaboost級聯分類器的結構,包括強分類器和弱分類器的形式;
(2)OpenCV自帶的XML分類器中各項參數,如internalNodes和leafValues標籤裏面的一大堆數字的意義。
在集成學習值Adaboost算法原理和代碼小結(轉載)小節中咱們已經介紹過了Adboost分類器,這裏咱們會介紹一下Adaboost級聯分類器。級聯分類模型是樹狀結構能夠用下圖表示:
其中每個stage都表明一級強分類器。當檢測窗口經過全部的強分類器時才被認爲是正樣本,不然拒絕。實際上,不只強分類器是樹狀結構,強分類器中的每個弱分類器也是樹狀結構。因爲每個強分類器對負樣本的判別準確度很是高,因此一旦發現檢測到的目標位負樣本,就不在繼續調用下面的強分類器,減小了不少的檢測時間。由於一幅圖像中待檢測的區域不少都是負樣本,這樣由級聯分類器在分類器的初期就拋棄了不少負樣本的複雜檢測,因此級聯分類器的速度是很是快的;只有正樣本纔會送到下一個強分類器進行再次檢驗,這樣就保證了最後輸出的正樣本的僞正(false positive)的可能性很是低。
級聯分類器是如何訓練的呢?首先須要訓練出每個弱分類器,而後把每一個弱分類器按照必定的組合策略,獲得一個強分類器,咱們訓練出多個強分類器,而後按照級聯的方式把它們組合在一塊,就會獲得咱們最終想要的Haar分類器。
一個弱分類器就是一個基本和上圖相似的決策樹,最基本的弱分類器只包含一個Haar-like特徵,也就是它的決策樹只有一層,被稱爲樹樁(stump)。
以20*20圖像爲例,78,460個特徵,若是直接利用AdaBoost訓練,那麼工做量是極其極其巨大的。
因此必須有個篩選的過程,篩選出T個優秀的特徵值(即最優弱分類器),而後把這個T個最優弱分類器傳給AdaBoost進行訓練。
如今有人臉樣本2000張,非人臉樣本4000張,這些樣本都通過了歸一化,大小都是20x20的圖像。那麼,對於78,460中的任一特徵fi,咱們計算該特徵在這2000人臉樣本、4000非人臉樣本上的值,這樣就獲得6000個特徵值。將這些特徵值排序,而後選取一個最佳的特徵值,在該特徵值下,對於特徵$f_i$來講,樣本的加權錯誤率最低。
在肯定了訓練子窗口中(20x20的圖像)的矩形特徵數量(78,460)和特徵值後,須要對每個特徵$f$,訓練一個弱分類器$h(x,f,ρ,Θ)$。$$h(x,f,ρ,Θ)=\begin{cases}1, {ρf(x)<ρΘ}\\0, {other}\end{cases}$$
其中$f$爲特徵,$Θ$爲閾值,$ρ$指示不等號的方向,$x$表明一個檢測子窗口。對每一個特徵$f$,訓練一個弱分類器$h(x,f,ρ,Θ)$,就是肯定$f$的最優閾值,使得這個弱分類器對全部的訓練樣本分類偏差最低。
在弱分類器訓練的過程當中,訓練採用的照片通常都是20*20左右的小圖片,弱分類器訓練的具體步驟:
一、對於每一個特徵 $f$,計算全部訓練樣本的特徵值,並將其排序:
二、掃描一遍排好序的特徵值,對排好序的表中的每一個元素,計算下面四個值:
計算所有正例的權重和$T^+$;
計算所有負例的權重和$T^-$;
計算該元素前以前的正例的權重和$S^+$;
計算該元素前以前的負例的權重和$S^-$;
三、選取當前元素的特徵值$F_{k_j}$和它前面的一個特徵值$F_{k_{j-1}}$之間的數做爲閾值,所獲得的弱分類器就在當前元素處把樣本分開 —— 也就是說這個閾值對應的弱分類器將當前元素前的全部元素分爲人臉(或非人臉),而把當前元素後(含)的全部元素分爲非人臉(或人臉)。該閾值的分類偏差爲:
$$e=min(S^++(T^--S^-),S^-+(T^+-S^+))$$
因而,經過把這個排序表從頭至尾掃描一遍就能夠爲弱分類器選擇使分類偏差最小的閾值(最優閾值),也就是選取了一個最佳弱分類器。
因爲一共有78,460個特徵、所以會獲得78,460個最優弱分類器,在78,460個特徵中,咱們選取錯誤率最低的特徵,用來判斷人臉,同時用此分類器對樣本進行分類,並更新樣本的權重。
強分類器的訓練步驟:
1.、給定訓練樣本集($x_i$,$y_i$),$i=1,2,3,...N$,共N個樣本,$y_i$取值爲0(負樣本)或者1(正樣本);設人臉正樣本的數量爲$n_1$,負樣本數量爲$n_2$; T爲訓練的最大循環次數;
2.、初始化樣本權重爲$\frac{1}{n_1+n_2}$,即爲訓練樣本的初始機率分佈;
三、$for t=1,...T$:
①權重歸一化$$ω_{t,i}=\frac{ω_{t,i}}{\sum\limits_{j-1}^{n}ω_{t,j}}$$
②對每一個(種)特徵$f_j$,訓練一個弱分類器$h_j$(如上),每一個分類器只使用一種Haar特徵進行訓練。分類偏差爲:$$ε_j=\sum\limits_{i}ω_i|h_j(x_i)-y_i|$$
③從②肯定的弱分類器中,找出一個具備最小分類偏差的弱分類器$h_t$;
④更新每一個樣本對應的權重:
這裏,若是樣本$x_i$被正確分類,則$e_i=0$,不然$e_i=1$,而$$\beta_t=\frac{ε_t}{1-ε_t}$$
四、最終造成的強分類器組成爲:
其中:$$\alpha_t=log\frac{1}{\beta_t}$$
在使用Adaboost算法訓練分類器以前,須要準備好正、負樣本,根據樣本特色選擇和構造特徵集。由算法的訓練過程可知,當弱分類器對樣本分類正確,樣本的權重會減少;而分類錯誤時,樣本的權重會增長。這樣,後面的分類器會增強對錯分樣本的訓練。最後,組合全部的弱分類器造成強分類器,經過比較這些弱分類器投票的加權和與平均投票結果來檢測圖像。
訓練級聯分類器的目的就是爲了檢測的時候,更加準確,這涉及到Haar分類器的另外一個體系,檢測體系,檢測體系是以現實中的一幅大圖片做爲輸入,而後對圖片中進行多區域,多尺度的檢測,所謂多區域,是要對圖片劃分多塊,對每一個塊進行檢測,因爲訓練的時候用的照片通常都是20*20左右的小圖片,因此對於大的人臉,還須要進行多尺度的檢測,多尺度檢測機制通常有兩種策略:
在區域放大的過程當中會出現同一我的臉被屢次檢測,這須要進行區域的合併,這裏不做探討。
不管哪種搜索方法,都會爲輸入圖片輸出大量的子窗口圖像,這些子窗口圖像通過篩選式級聯分類器會不斷地被每個節點篩選,拋棄或經過。
從上面所述內容咱們能夠總結Haar分類器訓練的五大步驟:
一、準備人臉、非人臉樣本集;
二、計算特徵值和積分圖;
三、篩選出T個優秀的特徵值(即最優弱分類器);
四、把這個T個最優弱分類器傳給AdaBoost進行訓練。
五、級聯,也就是強分類器的強強聯手。
在開始前,必定要記住,以20*20窗口爲例,就有78,460的特徵數量,篩選出T個優秀的特徵值(即最優弱分類器),而後把這個T個最優弱分類器傳給AdaBoost進行訓練獲得一個強分類器,最後將強分類器進行級聯。
OpenCV 自帶了訓練器和檢測器。若是你想本身訓練一個分類器來檢測汽車,飛機等的話,可使用 OpenCV 構建。其中的細節參考這裏:Cascade Classifier Training。這裏咱們介紹的XML文件,就是OpenCV自帶的檢測器,在OpenCV 3的庫文件中會包含一個文件夾haarcascades,在個人電腦上路徑爲D:\Anaconda\pkgs\opencv-3.3.1-py36h20b85fd_1\Library\etc\haarcascades。在這個文件夾下包含了OpenCV的人臉檢測的XML文件,這些文件可用於檢測靜止圖像,視頻和攝像頭所獲得圖像中的人臉。除此以外還有一個文件夾是lbpcascades,它不是經過Haar特徵進行人臉檢測,而是採用的LBP特徵。
從這些文件名能夠知道這些級聯適用於檢測人臉、眼睛、鼻子和嘴等部位的跟蹤,這些文件須要正面、直立的人體圖像。
xml文件主要保存相關的特徵矩陣,以及各個弱分類器相關的信息,關於各個節點的具體含義能夠參考文章haar+adaboost結合講解(偏重實際),這裏不作過多的介紹。
在這裏咱們將會學習到使用級聯分類器進行人臉檢測。在靜態圖像或視頻中檢測人臉的操做很是類似。視頻人臉檢測知識從攝像頭讀出毎幀圖像,而後採用靜態圖像中的人臉檢測方法進行檢測,固然,視頻人臉檢測還涉及其餘概念,例如跟蹤,而靜態圖像中人臉檢測就沒有這樣的概念,可是它們的基本理論是一致的。
咱們首先把haarcascades文件夾複製到當前項目路徑下,而後建立.py文件,代碼以下:
# -*- coding: utf-8 -*- """ Created on Thu Aug 16 10:32:55 2018 @author: lenovo """ ''' 人臉檢測 ''' import cv2 import numpy as np #1.靜態圖像中的人臉檢測 def StaticDetect(filename): #建立一個級聯分類器 加載一個 .xml 分類器文件. 它既能夠是Haar特徵也能夠是LBP特徵的分類器. face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml') #加載圖像 img = cv2.imread(filename) #轉換爲灰度圖 gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #進行人臉檢測,傳入scaleFactor,minNegihbors,分別表示人臉檢測過程當中每次迭代時圖像的壓縮率以及 #每一個人臉矩形保留近似數目的最小值 #返回人臉矩形數組 faces = face_cascade.detectMultiScale(gray_img,1.3,5) for (x,y,w,h) in faces: #在原圖像上繪製矩形 img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) cv2.namedWindow('Face Detected!') cv2.imshow('Face Detected!',img) cv2.waitKey(0) cv2.destroyAllWindows() #二、視頻中的人臉檢測 def DynamicDetect(): ''' 打開攝像頭,讀取幀,檢測幀中的人臉,掃描檢測到的人臉中的眼睛,對人臉繪製藍色的矩形框,對人眼繪製綠色的矩形框 ''' #建立一個級聯分類器 加載一個 .xml 分類器文件. 它既能夠是Haar特徵也能夠是LBP特徵的分類器. face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_eye.xml') #打開攝像頭 camera = cv2.VideoCapture(0) cv2.namedWindow('Dynamic') while(True): #讀取一幀圖像 ret,frame = camera.read() #判斷圖片讀取成功? if ret: gray_img = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #人臉檢測 faces = face_cascade.detectMultiScale(gray_img,1.3,5) for (x,y,w,h) in faces: #在原圖像上繪製矩形 cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray_img[y:y+h,x:x+w] #眼睛檢測 eyes = eye_cascade.detectMultiScale(roi_gray,1.03,5,0,(40,40)) for (ex,ey,ew,eh) in eyes: cv2.rectangle(frame,(ex+x,ey+y),(x+ex+ew,y+ey+eh),(0,255,0),2) cv2.imshow('Dynamic',frame) #若是按下q鍵則退出 if cv2.waitKey(100) & 0xff == ord('q') : break camera.release() cv2.destroyAllWindows() if __name__=='__main__': #filename = './image/img23.jpg' #StaticDetect(filename) DynamicDetect()
咱們來分析一下StaticDetect函數,首先建立一個級聯分類器對象,而後加載xml檢測器,用來進行人臉檢測。
#建立一個級聯分類器 加載一個 .xml 分類器文件. 它既能夠是Haar特徵也能夠是LBP特徵的分類器. face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')
而後加載圖片文件,並將其轉換爲灰度圖像,由於人臉檢測須要這樣的色彩空間。
#加載圖像 img = cv2.imread(filename) #轉換爲灰度圖 gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
接下來進行人臉檢測,須要傳入scaleFactor和minNeighbors參數,它們分別表示人臉檢測過程當中每次迭代時圖像的壓縮率以及每一個人臉矩形保留近似數目的最小值。而後函數返回人臉矩陣數組。咱們利用cv2.rectangle函數在原圖中把矩形繪製出來。
#進行人臉檢測,傳入scaleFactor,minNegihbors,分別表示人臉檢測過程當中每次迭代時圖像的壓縮率以及 #每一個人臉矩形保留近似數目的最小值 #返回人臉矩形數組 faces = face_cascade.detectMultiScale(gray_img,1.3,5) for (x,y,w,h) in faces: #在原圖像上繪製矩形 img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) cv2.namedWindow('Face Detected!') cv2.imshow('Face Detected!',img) cv2.waitKey(0) cv2.destroyAllWindows()
運行結果以下,咱們能夠看到全部的人臉都檢測出來了,可是其中還有一個誤檢測:
上面已經介紹了在靜態圖像上進行人臉檢測,在視頻幀上重複進行這個過程就能完成視頻中的人臉檢測。DynamicDetect函數主要包括:打開攝像頭、讀取幀、檢測人臉、掃描檢測到的人臉中的眼睛,並使用不一樣顏色繪製出矩形框。
#二、視頻中的人臉檢測 def DynamicDetect(): ''' 打開攝像頭,讀取幀,檢測幀中的人臉,掃描檢測到的人臉中的眼睛,對人臉繪製藍色的矩形框,對人眼繪製綠色的矩形框 ''' #建立一個級聯分類器 加載一個 .xml 分類器文件. 它既能夠是Haar特徵也能夠是LBP特徵的分類器. face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_eye.xml') #打開攝像頭 camera = cv2.VideoCapture(0) cv2.namedWindow('Dynamic') while(True): #讀取一幀圖像 ret,frame = camera.read() #判斷圖片讀取成功? if ret: gray_img = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) #人臉檢測 faces = face_cascade.detectMultiScale(gray_img,1.3,5) for (x,y,w,h) in faces: #在原圖像上繪製矩形 cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2) roi_gray = gray_img[y:y+h,x:x+w] #眼睛檢測 eyes = eye_cascade.detectMultiScale(roi_gray,1.03,5,0,(40,40)) for (ex,ey,ew,eh) in eyes: cv2.rectangle(frame,(ex+x,ey+y),(x+ex+ew,y+ey+eh),(0,255,0),2) cv2.imshow('Dynamic',frame) #若是按下q鍵則退出 if cv2.waitKey(100) & 0xff == ord('q') : break camera.release() cv2.destroyAllWindows()
這裏和上面有些相似,只是在進行眼睛檢測的時候多了幾個參數。detectMultiScale有許多可選參數;在人臉檢測時,默認選項足以檢測人臉,可是眼睛是一個比較小的人臉特徵,而且鬍子或者鼻子的自己陰影以及幀的隨機陰影都會產生假陽性。經過限制對眼睛搜索的最小尺寸爲40x40像素,能夠去掉假陽性。而後測試這些參數,直至應用程序能夠知足預期(例如能夠嘗試指定特徵的最大尺寸,或增長比例因子以及近鄰的數量)。
下面咱們來總結一下detectMultiScale函數:
detectMultiScale(image[,scaleFactor[,minNeighbors[,flags[,minSize[,maxSize]]]]])
參考文獻:
[1]淺析人臉檢測之Haar分類器方法:Haar特徵、積分圖、 AdaBoost 、級聯
[3]Haar+cascade AdaBoost分類器學習訓練總結
[4]OpenCV中的Haar+Adaboost(一):Haar特徵詳細介紹