OpenCV 是 Intel 開源計算機視覺庫 (Computer Version) 。它由一系列 C 函數和少許 C++類構成,實現了圖像處理和計算機視覺方面的不少通用算法。javascript
OpenCV 擁有包括 300 多個 C 函數的跨平臺的中、高層 API 。它不依賴於其它的外部庫 —— 儘管也可使用某些外部庫。OpenCV 對非商業應用和商業應用都是免費 的。同時 OpenCV 提供了對硬件的訪問,能夠直接訪問攝像頭,而且 opencv 還提供了一個簡單的 GUI(graphics user interface) 系統 :highgui 。 咱們就經過 OpenCV 提供的一些方法來構造出這我的臉檢測 (face detection ) 程序來。java
OpenCV 自己是有 C/C++ 編寫的,若是要在其餘語言中使用,咱們能夠經過對其動態連接庫文件進行包裝便可,幸運的是,Python 下有不少個這樣的包裝,本文中使用的是 Cvtypes 。python
事實上,在 Python 中不少的包都是來自第三方的,好比 PIL(Python Image Library) 即爲 C 語言實現的一個圖形處理包,被包裝到了 Python 中,這些包裝可讓你像使用 Python 的內建函數同樣的使用這些 API 。算法
人臉檢測屬於目標檢測(object detection) 的一部分,主要涉及兩個方面網絡
計算機的視覺系統,跟人的眼睛是大不相同的,可是其中也有相似之處。人眼之可以看到物體,是經過物體上反射出來的光線刺激人眼的感光細胞,而後視覺神經在大腦中造成物體的像。計算機經過攝像頭看到的東西要簡單的多,簡單來講,就是一堆由數字組成的矩陣。這些數字代表了物體發出的光的強弱,攝像頭的光敏元件將光信號轉化成數字信號,將其量化爲矩陣。
如何從這些數字中得出:"這是一我的臉"的結論,是一個比較複雜的事情。物理世界是彩色的,通常來講,計算機中的彩色圖片都是由若干個色彩通道累積出來的,好比RGB模式的圖片,有紅色通道(Red),綠色通道(Green)和藍色通道(Blue),這三個通道都是灰度圖,好比一個點由8位來表示,則一個通道能夠表示2^8=256個灰度。那樣三個通道進行疊加之後能夠表3*8=24位種色彩,也就是咱們常說的24位真彩。
對這樣的圖片作處理,無疑是一件很複雜的事,因此有必要先將彩色圖轉爲灰度圖,那樣能夠減小數據量(好比RGB模式,能夠減小到原圖片的1/3),同時能夠去掉一些噪聲信號。先將圖片轉化爲灰度圖,而後將這個灰度圖的對比度增高,這樣可使得圖片原本暗的地方更暗,亮的地方更亮一些。這樣處理之後,圖片就更容易被算法設別出來了。app
OpenCV在物體檢測上使用的是haar特徵的級聯表,這個級聯表中包含的是boost的分類器。首先,人們採用樣本的haar特徵進行分類器的訓練,從而獲得一個級聯的boost分類器。訓練的方式包含兩方面:
1. 正例樣本,即待檢測目標樣本
2. 反例樣本,其餘任意的圖片
首先將這些圖片統一成相同的尺寸,這個過程被稱爲歸一化,而後進行統計。一旦分類器創建完成,就能夠用來檢測輸入圖片中的感興趣區域的檢測了,通常來講,輸入的圖片會大於樣本,那樣,須要移動搜索窗口,爲了檢索出不一樣大小的目標,分類器能夠按比例的改變本身的尺寸,這樣可能要對輸入圖片進行屢次的掃描。
什麼是級聯的分類器呢?級聯分類器是由若干個簡單分類器級聯成的一個大的分類器,被檢測的窗口依次經過每個分類器,能夠經過全部分類器的窗口便可斷定爲目標區域。同時,爲了考慮效率問題,能夠將最嚴格的分類器放在整個級聯分類器的最頂端,那樣能夠減小匹配次數。
基礎分類器以haar特徵爲輸入,以0/1爲輸出,0表示未匹配,1表示匹配。函數
在掃描待檢測圖片的時候,以邊界特徵中的(a)爲例,正如前面提到的那樣,計算機中的圖片是一個數字組成的矩陣,程序先計算整個窗口中的灰度值x,而後計算矩形框中的黑色灰度值y,而後計算(x-2y)的值,獲得的數值與x作比較,若是這個比值在某一個範圍內,則表示待檢測圖片的當前掃描區域符合邊界特徵(a),而後繼續掃描。
關於這個算法的更詳細描述已經超出了本文的範圍,能夠在參考資源中得到更多的信息。ui
由於是基於視頻流的目標檢測,咱們事先不太可能知道要檢測的目標的大小,這就要求咱們的級聯表中的分類器具備按比例增大(或者縮小)的能力,這樣,當小的窗口移動完整個待檢測圖片沒有發現目標時,咱們能夠調整分類器的大小,而後繼續檢測,直到檢測到目標或者窗口與待檢測圖片的大小至關爲止。spa
在從攝像頭中得到一個幀(一張圖片)後,咱們須要先對這張圖片進行一些預處理:orm
這兩個步驟在OpenCV中是很是簡單的:
OpenCV中,對於人臉檢測的模型已經創建爲一個XML文件,其中包含了上面提到的harr特徵的分類器的訓練結果,咱們能夠經過加載這個文件而省略掉本身創建級聯表的過程。有了級聯表,咱們只須要將待檢測圖片和級聯表一同傳遞給OpenCV的目標檢測算法便可獲得一個檢測到的人臉的集合。
能夠看到,OpenCV的API至關清晰,使用Python的包裝,可使得代碼很是小。好了,咱們能夠看看程序的運行結果:
因爲視頻流是動態的,因此咱們能夠在程序的入口中使用一個無限循環,在循環中,每次從視頻中讀入一個幀,將這個幀傳輸給人臉檢測模塊,檢測模塊在這個幀上進行標記(若是有人臉的話),而後返回這個幀,主程序拿到這個幀後,更新顯示窗口。
效果圖:
CVtypes中自帶了一個關於圖像色彩空間的直方圖的例子:
OpenCV的功能十分強大,並且提供了大量的算法實現,文中涉及到的內容只是計算機視覺中很小的一部分。讀者能夠考慮將採集到的人臉進行標識,從而實現特定人的人臉識別。或者考慮將人臉檢測移植到網絡上,從而實現遠程監控。試想一下,原來沒有生命的機器,咱們能夠經過本身的思想,動做來使得它們看起來像是有思想同樣,這件事自己就很是的有趣。