用10行代碼自己寫個人臉識別程序
CV (Computer Vision)
最近在研究CV的一些開源庫(OpenCV),有一個體會就是在此領域,除了一些非常學術的 機器學習 , 深度學習 等概念外,其實還有一些很有趣的 現實的 應用場景。比如之前很流行的微軟的 https://how-old.net , 你使用自己指定或者上傳的照片進行面部識別 猜年齡 。 如下圖所示:
細想一下這個很吸引眼球的程序,其實技術本身打散了就包括兩大塊,一是從圖片中掃描并進行面部識別,二是對找到的人臉根據算法去猜個年齡。大家可以猜猜實現第一個功能需要多少核心代碼量?其實不用
上萬行 ,在這里我就使用短短 幾行代碼 (去除空格換行什么的,有效代碼只要10行)就實現一個 高大上
面部識別的功能。在此文容我細述一下具體實現代碼以及我對機器識別圖像領域技術的理解。
面部識別,刷臉
人臉識別 技術大家應該都不陌生,之前大家使用的數碼相機,或者現在很多手機自帶的相機都有人臉識別的功能。其效果就像是下圖這樣。近的看, 剁手節 剛剛過了沒有多久 , 背后的馬老板一直在力推的刷臉支付也是一個此領域的所謂“黑科技”。比如在德國漢諾威電子展上,馬云用支付寶“刷臉”買了一套紀念郵票。人臉識別應用市場也從爆發。隨后,各大互聯網巨頭也紛紛推出了刷臉相關的應用。
如果要加個定義,人臉識別又叫做人像識別、面部識別,是一種通過用攝像機或攝像頭采集含有人臉的圖像或視頻流,并自動在圖像中檢測和跟蹤人臉,進而對檢測到的人臉進行臉部的一系列相關技術。
我的十行代碼程序
OK,長話短說,先上 干貨 ,下面就是此程序的 帶注釋 版本,完整的程序以及相關配套文件可以在 這個github庫 https://github.com/CloudsDocker/pyFacialRecognition 中找到,有興趣可以 fork 下來玩玩。下面是整個程序的代碼樣子,后面我會逐行去解釋分析。
就這短短的十行代碼代碼?seriously?“有圖有真相”,我們先來看下運行的效果:
首先是原始的圖片
運行程序后識別出面部并高亮顯示的結果
請注意 K歌二人組 的臉上的紅色框框,這就是上面十行代碼的成果。
代碼解析
準備工作
因為此程序使用是的Python,因此你需要去安裝Python。這里就不贅述了。除此之外,還需要安裝 OpenCV ( http://opencv.org/downloads.html)。
多說一句,這個 OpenCV正如其名,是一個開源的機器識別的深度學習框架。這是Intel(英特爾)實驗室里的一個俄羅斯團隊創造的,目前在開源社區非常的活躍。
特別提一下,對于Mac的用戶,推薦使用brew去安裝 (下面第一條語句可能會執行報錯,我當時也是搞了好久。如果遇到第一條命令不過可以通過文尾的方式聯系作者)
brew tap homebrew/science brew install opencv
安裝完成之后,在python的命令行中輸入如下代碼驗證,如果沒有報錯就說明安裝好了。
>>> import cv2
程序代碼“庖丁解牛”
-- coding: utf-8 --
import cv2,sys</pre>
- 由于這里注釋及窗口標題中使用了中文,因此加上utf-8字符集的支持
- 引入Opencv庫以及Python的sys內建庫,用于解析輸入的圖片參數
inputImageFile=sys.argv[1]
- 在運行程序時將需要測試的照片文件名作為一個參數傳進來
faceClassifier=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
- 加載OpenCV中自帶預先培訓好的人臉識別層級分類器 HAAR Casscade Classifier,這個會用來對我們輸入的圖片進行人臉判斷。
這里有幾個在深度學習及機器圖像識別領域中的幾個概念,稍微分析一下,至于深入的知識,大家可以自行搜索或者聯系作者。
Classifer
在機器深度學習領域,針對識別不同物體都有不同的classifier,比如有的classifier來識別洗車,還有識別飛機的classifier,有classifier來識別照片中的笑容,眼睛等等。而我們這個例子是需要去做人臉識別,因此需要一個面部識別的classifier。
物體識別的原理
一般來說,比如想要機器學習著去識別“人臉”,就會使用大量的樣本圖片來事先培訓,這些圖片分為兩大類,positive和negative的,也就是分為包“含有人臉”的圖片和“不包含人臉”的圖片,這樣當使用程序去一張一張的分析這些圖片,然后分析判斷并對這些圖片“分類” (classify),即合格的圖片與不合格的圖片,這也就其為什么叫做 classifier , 這樣學習過程中積累的"知識",比如一些判斷時的到底臨界值多少才能判斷是positive還是negative什么的,都會存儲在一個個XML文件中,這樣使用這些前人經驗(這里我們使用了 哈爾 分類器)來對新的圖片進行‘專家判斷'分析,是否是人臉或者不是人臉。
Cascade
這里的 Cascade是 層級分類器 的意思。為什么要 分層 呢?剛才提到在進行機器分析照片時,其實是對整個圖片從上到下,從左到右,一個像素一個像素的分析,這些分析又會涉及很多的 特征分析 ,比如對于人臉分析就包含識別眼睛,嘴巴等等,一般為了提高分析的準確度都需要有成千上萬個特征,這樣對于每個像素要進行成千上萬的分析,對于整個圖片都是百萬甚至千萬像素,這樣總體的計算量會是個天文數字。但是,科學家很聰明,就想到分級的理念,即把這些特征分層,這樣分層次去驗證圖片,如果前面層次的特征沒有通過,對于這個圖片就不用判斷后面的特征了。這有點像是系統架構中的 FF (Fail Fast) ,這樣就提高了處理的速度與效率。
objImage=cv2.imread(inputImageFile)
- 使用OpenCV庫來加載我們傳入的測試圖片
cvtImage=cv2.cvtColor(objImage,cv2.COLOR_BGR2GRAY)
- 首先將圖片進行灰度化處理,以便于進行圖片分析。這種方法在圖像識別領域非常常見,比如在進行驗證碼的機器識別時就會先灰度化,去除不相關的背景噪音圖像,然后再分析每個像素,以便抽取出真實的數據。不對針對此,你就看到非常多的驗證碼后面特意添加了很多的噪音點,線,就是為了防止這種程序來灰度化圖片進行分析破解。
foundFaces=faceClassifier.detectMultiScale(cvtImage,scaleFactor=1.3,minNeighbors=9,minSize=(50,50),flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
- 執行detectMultiScale方法來識別物體,因為我們這里使用的是人臉的cascade classifier分類器,因此調用這個方法會來進行面部識別。后面這幾個參數來設置進行識別時的配置,比如
- scaleFactor: 因為在拍照,尤其現在很多都是自拍,這樣照片中有的人臉大一些因為離鏡頭近,而有些離鏡頭遠就會小一些,因為這個參數用于設置這個因素,如果你在使用不同的照片時如果人臉遠近不同,就可以修改此參數,請注意此參數必須要大于1.0
- minNeighbors: 因為在識別物體時是使用一個移動的小窗口來逐步判斷的,這個參數就是決定是不是確定找到物體之前需要判斷多少個周邊的物體
- minSize:剛才提到識別物體時是合作小窗口來逐步判斷的,這個參數就是設置這個小窗口的大小
print(" 在圖片中找到了 {} 個人臉".format(len(foundFaces)))
- 顯示出查找到多少張人臉,需要提到的識別物體的方法返回的一個找到的物體的位置信息的列表,因此使用 len 來打印出找到了多少物體。
for (x,y,w,h) in foundFaces: cv2.rectangle(objImage,(x,y),(x+w,y+h),(0,0,255),2)
- 遍歷發現的“人臉”,需要說明的返回的是由4部分組成的位置數據,即這個“人臉”的橫軸,縱軸坐標,寬度與高度。
- 然后使用 OpenCV 提供的方法在原始圖片上畫出個矩形。其中 (0,0,255) 是使用的顏色,這里使用的是R/G/B的顏色表示方法,比如 (0,0,0)表示黑色,(255,255,255)表示白色,有些網頁編程經驗的程序員應該不陌生。
cv2.imshow(u'面部識別的結果已經高度框出來了。按任意鍵退出'.encode('gb2312'), objImage) cv2.waitKey(0)
- 接下來是使用 opencv 提供的imshow方法來顯示這個圖片,其中包括我們剛剛畫的紅色的識別的結果
- 最后一個語句是讓用戶按下鍵盤任意一個鍵來退出此圖片顯示窗口
總結
好了,上面是這個程序的詳細解釋以及相關的知識的講解。其實這個只是個 拋磚引玉 的作用,還用非常多的應用場景,比如程序解析網頁上的圖片驗證碼,雅虎前幾個月開源的 NSFW , Not Suitable for Work (NSFW),即判斷那些不適合工作場所的圖片,內容你懂的。 :-)
git clone https://github.com/CloudsDocker/pyFacialRecognition.git cd pyFacialRecognition ./run.sh
Reference
來自:http://www.jianshu.com/p/9aef6f4db349