// 總結:OpenCV實現人臉識別
// 2016.2.12 by Huangtao
// 算法
主要有如下步驟:
一、人臉檢測
二、人臉預處理
三、從收集的人臉訓練機器學習算法
四、人臉識別
五、收尾工做機器學習
=================================================
人臉檢測算法:
=================================================ide
基於Haar的臉部檢測器的基本思想是,對於面部正面大部分區域而言,會有眼睛所在區域應該比前額和臉頰更暗,嘴巴
應該比臉頰更暗等情形。它一般執行大約20個這樣的比較來決定所檢測的對象是否爲人臉,實際上常常會作上千次。
基於LBP的人臉檢測器基本思想與基於Haar的人臉檢測器相似,但它比較的是像素亮度直方圖,例如,邊緣、角落和平坦
區域的直方圖。
這兩種人臉檢測器可經過訓練大的圖像集找到人臉,這些圖像集在opencv中存在XML文件中以便後續使用。
這些級聯分類檢測器一般至少需使用1000個獨特的人臉圖像和10000個非人臉圖像做爲訓練,訓練時間通常LBP要幾個小時,
Haar要一個星期。函數
項目中的關鍵代碼以下:
initDetectors
faceCascade.load(faceCascadeFilename);
eyeCascade1.load(eyeCascadeFilename1);
eyeCascade2.load(eyeCascadeFilename2);學習
initWebcam
videoCapture.open(cameraNumber);測試
cvtColor(img, gray, CV_BGR2GRAY);
//有須要則縮小圖片使檢測運行更快,以後要恢復原來大小
resize(gray, inputImg, Size(scaledWidth, scaledHeight));
equalizeHist(inputImg, equalizedImg);
cascade.detectMultiScale(equalizedImg......);spa
=================================================
人臉預處理:
=================================================orm
實際中一般訓練(採集圖像)和測試(來自攝像機圖像)的圖像會有很大不一樣,受(如光照、人臉方位、表情等),
結果會不好,所以用於訓練的數據集很重要。
人臉預處理目的是減小這類問題,有助於提升整我的臉識別系統的可靠性。對象
人臉預處理的最簡單形式就是使用equalizeHist()函數作直方圖均衡,這與人臉檢測那步同樣。
實際中,爲了讓檢測算法更可靠,會使用面部特徵檢測(如,檢測眼睛、鼻子、嘴巴和眉毛),本項目只使用眼睛檢測。
使用OpenCV自帶的訓練好的眼部探測器。如,正面人臉檢測完畢後,獲得一我的臉,在使用眼睛檢測器提取人臉的左眼區域
和右眼區域,並對每一個眼部區域進行直方圖均衡。圖片
這步涉及的操做有如下內容:
一、幾何變換和裁剪
人臉對齊很重要,旋轉人臉使眼睛保持水平,縮放人臉使眼睛之間距離始終相同,平移人臉使眼睛老是在所需高度上水平居中,
裁剪人臉外圍(如圖像背景、頭髮、額頭、耳朵和下巴)。
二、對人臉左側和右側分別用直方圖均衡
三、平滑
用雙邊濾波器來減小圖像噪聲
四、橢圓掩碼
將剩餘頭髮和人臉圖像背景去掉
項目中的關鍵代碼以下:
detectBothEyes(const Mat &face, CascadeClassifier &eyeCascade1, CascadeClassifier &eyeCascade2,
Point &leftEye, Point &rightEye, Rect *searchedLeftEye, Rect *searchedRightEye);
topLeftOfFace = face(Rect(leftX, topY, widthX, heightY));
//在左臉區域內檢測左眼
detectLargestObject(topLeftOfFace, eyeCascade1, leftEyeRect, topLeftOfFace.cols);
//右眼相似,這樣眼睛中心點就獲得了
leftEye = Point(leftEyeRect.x + leftEyeRect.width/2, leftEyeRect.y + leftEyeRect.height/2);
//再獲得兩眼的中點,而後計算兩眼之間的角度
Point2f eyesCenter = Point2f( (leftEye.x + rightEye.x) * 0.5f, (leftEye.y + rightEye.y) * 0.5f );
//仿射扭曲(Affine Warping)須要一個仿射矩陣
rot_mat = getRotationMatrix2D(eyesCenter, angle, scale);
//如今可變換人臉來獲得檢測到的雙眼出如今人臉的所需位置
warpAffine(gray, warped, rot_mat, warped.size());
//先對人臉左側和右側分開進行直方圖均衡
equalizeHist(leftSide, leftSide);
equalizeHist(rightSide, rightSide);
//再合併,這裏合併時左側1/4和右側1/4直接取像素值,中間的2/4區域像素值經過必定計算進行處理。
//雙邊濾波
bilateralFilter(warped, filtered, 0, 20.0, 2.0);
//採用橢圓掩碼來刪除一些區域
filtered.copyTo(dstImg, mask);
=================================================
收集並訓練人臉:
=================================================
一個好的數據集應包含人臉變換的各類情形,這些變化可能出如今訓練集中。如只測試正面人臉,則只需訓練圖像有徹底正面人臉便可。
所以一個好的訓練集應包含不少實際情形。
本項目收集的圖像之間至少有一秒的間隔,使用基於L2範數的相對錯誤評價標準來比較兩幅圖像素之間的類似性。
errorL2 = norm(A, B, CV_L2);
similarity = errorL2 / (double)(A.rows * A.cols);
再與收集新人臉的閾值相比來決定是否收集此次圖像。
可用不少技巧來獲取更多的訓練數據,如,使用鏡像人臉、加入隨機噪聲、改變人臉圖像的一些像素、旋轉等。
//翻轉
flip(preprocessedFace, mirroredFace, 1);
對每一個人收集到足夠多的人臉圖像後,接下來必須選擇適合人臉識別的機器學習算法,經過它來學習收集的數據,從而訓練出一我的臉識別系統。
人臉識別算法:
一、特徵臉,也稱PCA(主成分分析)
二、Fisher臉,也稱LDA(線性判別分析)
三、局部二值模式直方圖(Local Binary Pattern Histograms,LBPH)
其餘人臉識別算法:www.face-rec.org/algorithms/
OpenCV提供了CV::Algorithm類,該類有幾種不一樣的算法,用其中一種算法就能夠完成簡單而通用的人臉識別。
OpenCV的contrib模板中有一個FaceRecognizer類,它實現以上這些人臉識別算法。
initModule_contrib();
model = Algorithm::create<FaceRecognizer>(facerecAlgorithm);
model->train(preprocessedFaces, faceLabels);
這一代碼將執行所選人臉識別的整個訓練算法。
=================================================
人臉識別:
=================================================
一、人臉識別:經過人臉來識別這我的
能夠簡單調用FaceRecognizer::predict()函數來識別照片中的人,
int identity = model->predict(preprocessedFace);
它帶來的問題是它總能預測給定的人(即便輸入圖像不屬於訓練集中的人)。
解決此問題的辦法是制定置信度標準,置信度太低則可判讀是一個不認識的人。
二、人臉驗證:驗證圖像中是否有想找的人
爲了驗證是否可靠,或者說系統是否能對一個不認識的人進行正確識別,這須要進行人臉驗證。
這裏計算置信度的方法是:
使用特徵向量和特徵值重構人臉圖,而後將輸入的圖像與重構圖進行比較。若是一我的在訓練集中有多張人臉圖,用特徵向量和特徵
值重構後應該有很是好的效果,若是沒有則差異很大,代表它多是一個未知的人臉。
subspaceProject()函數將人臉圖像映射到特徵空間,再用
subspaceReconstruct()函數從特徵空間重構圖像。
=================================================
收尾:交互式GUI
=================================================
利用OpenCV函數很容易繪製一些組件,鼠標點擊等。
參考書籍:
《深刻理解OpenCV 實用計算機視覺項目解析 》,這本書確實不錯,裏面相關項目也不少,寫的也很好。