Summary:利用OpenCV中的LBF算法進行人臉關鍵點檢測(Facial Landmark Detection)html
Author: Amusiios
Date: 2018-03-20git
Note: OpenCV3.4以及上支持Facemarkgithub
PS:點擊「閱讀原文」,能夠下載全部源碼和模型,記得給star哦!算法
教程目錄網絡
測試環境ide
引言函數
Facemark API學習
Facemark訓練好的模型測試
利用OpenCV代碼進行實時人臉關鍵點檢測
步驟
代碼
實驗結果
Reference
測試環境
Windows10
Visual Studio 2013
OpenCV3.4.1
引言
人臉通常是有68個關鍵點,經常使用的人臉開源庫有Dlib,還有不少深度學習的方法。
本教程僅利用OpenCV,不依賴任何其它第三方庫來實現人臉關鍵點檢測,這一特性是以前沒有的。由於OpenCV自帶的samples中只有常見的人臉檢測、眼睛檢測和眼鏡檢測等(方法是harr+cascade或lbp+cascade)。
本教程主要參考Facemark : Facial Landmark Detection using OpenCV[1]
截止到2018-03-20,OpenCV3.4可支持三種人臉關鍵點檢測,但目前只能找到一種已訓練好的模型,因此本教程只介紹一種實現人臉關鍵點檢測的算法。並且此類算法尚未Python接口,因此這裏只介紹C++的代碼實現。
Facemark API
OpenCV官方的人臉關鍵點檢測API稱爲Facemark。Facemark目前分別基於下述三篇論文,實現了三種人臉關鍵點檢測的方法。
FacemarkKazemi[2]: This implementation is based on a paper titled 「One Millisecond Face Alignment with an Ensemble of Regression Trees」 by V.Kazemi and J. Sullivan published in CVPR 2014[3]. An alternative implementation of this algorithm can be found in DLIB
FacemarkAAM[4]: This implementation uses an Active Appearance Model (AAM) and is based on an the paper titled 「Optimization problems for fast AAM fitting in-the-wild」 by G. Tzimiropoulos and M. Pantic, published in ICCV 2013[5].
FacemarkLBF[6]: This implementation is based a paper titled 「Face alignment at 3000 fps via regressing local binary features」 by S. Ren published in CVPR 2014[7].
在寫這篇文章的時候,FacemarkKazemi相似乎不是從Facemark類派生的,而其餘兩個類都是。
Facemark訓練好的模型
儘管Facemark API包含三種不一樣的實現,但只有FacemarkLBF(local binary features,LBF)才提供通過訓練的模型。 (以後在咱們根據公共數據集訓練咱們本身的模型後,這篇文章將在將來更新)
你能夠從中下載已訓練好的模型:
lbfmodel.yaml[8]
利用OpenCV代碼進行實時人臉關鍵點檢測
步驟
全部的人臉關鍵點檢測算法的輸入都是一個截切的人臉圖像。由於,咱們的第一步就是在圖像中檢測全部的人臉,並將全部的人臉矩形框輸入到人臉關鍵點檢測器中。這裏,咱們可使用OpenCV的Haar人臉檢測器或者lbp人臉檢測器來檢測人臉。
建立Facemark類的對象。在OpenCV中,Facemark是使用智能指針(smart pointer,PTR),因此咱們不須要考慮內存泄漏問題。
加載關鍵點檢測器(lbfmodel.yaml)。此人臉檢測器是在幾千幅帶有關鍵點標籤的人臉圖像上訓練獲得的。
帶有註釋/標籤關鍵點的人臉圖像公共數據集能夠訪問這個連接下載:https://ibug.doc.ic.ac.uk/resources/facial-point-annotations/
4.從網絡攝像頭中捕獲幀
捕獲視頻幀並處理。咱們既能夠打開一個本地視頻(.mp4),也能夠打開網絡攝像機(若是電腦有的話)來進行人臉關鍵點檢測。
咱們對視頻的每一幀運行人臉檢測器。人臉檢測器的輸出是一個包含一個或多個矩形(rectangles)的容器(vector),即視頻幀中可能有一張或者多張人臉。
咱們根據人臉矩形框截取原圖中的人臉ROI,再利用人臉關鍵點檢測器(facial landmark detector)對人臉ROI進行檢測。
對於每張臉咱們得到,咱們能夠得到68個關鍵點,並將其存儲在點的容器中。由於視頻幀中可能有多張臉,因此咱們應採用點的容器的容器。
根據得到關鍵點,咱們能夠在視頻幀上繪製出來並顯示。
代碼
本教程的代碼一共有兩個程序,分別爲faceLandmarkDetection.cpp和drawLandmarks.hpp。
faceLandmarkDetection.cpp實現視頻幀捕獲、人臉檢測、人臉關鍵點檢測;
drawLandmarks.hpp實現人臉關鍵點繪製和多邊形線繪製。
faceLandmarkDetection.cpp
1// Summary: 利用OpenCV的LBF算法進行人臉關鍵點檢測 2// Author: Amusi 3// Date: 2018-03-20 4// Reference: 5// [1]Tutorial: https://www.learnopencv.com/facemark-facial-landmark-detection-using-opencv/ 6// [2]Code: https://github.com/spmallick/learnopencv/tree/master/FacialLandmarkDetection 7 8// Note: OpenCV3.4以及上支持Facemark 9 10#include <opencv2/opencv.hpp> 11#include <opencv2/face.hpp> 12#include "drawLandmarks.hpp" 13 14 15using namespace std; 16using namespace cv; 17using namespace cv::face; 18 19 20int main(int argc,char** argv) 21{ 22 // 加載人臉檢測器(Face Detector) 23 // [1]Haar Face Detector 24 //CascadeClassifier faceDetector("haarcascade_frontalface_alt2.xml"); 25 // [2]LBP Face Detector 26 CascadeClassifier faceDetector("lbpcascade_frontalface.xml"); 27 28 // 建立Facemark類的對象 29 Ptr<Facemark> facemark = FacemarkLBF::create(); 30 31 // 加載人臉檢測器模型 32 facemark->loadModel("lbfmodel.yaml"); 33 34 // 設置網絡攝像頭用來捕獲視頻 35 VideoCapture cam(0); 36 37 // 存儲視頻幀和灰度圖的變量 38 Mat frame, gray; 39 40 // 讀取幀 41 while(cam.read(frame)) 42 { 43 44 // 存儲人臉矩形框的容器 45 vector<Rect> faces; 46 // 將視頻幀轉換至灰度圖, 由於Face Detector的輸入是灰度圖 47 cvtColor(frame, gray, COLOR_BGR2GRAY); 48 49 // 人臉檢測 50 faceDetector.detectMultiScale(gray, faces); 51 52 // 人臉關鍵點的容器 53 vector< vector<Point2f> > landmarks; 54 55 // 運行人臉關鍵點檢測器(landmark detector) 56 bool success = facemark->fit(frame,faces,landmarks); 57 58 if(success) 59 { 60 // 若是成功, 在視頻幀上繪製關鍵點 61 for(int i = 0; i < landmarks.size(); i++) 62 { 63 // 自定義繪製人臉特徵點函數, 可繪製人臉特徵點形狀/輪廓 64 drawLandmarks(frame, landmarks[i]); 65 // OpenCV自帶繪製人臉關鍵點函數: drawFacemarks 66 drawFacemarks(frame, landmarks[i], Scalar(0, 0, 255)); 67 } 68 69 } 70 71 // 顯示結果 72 imshow("Facial Landmark Detection", frame); 73 74 // 若是按下ESC鍵, 則退出程序 75 if (waitKey(1) == 27) break; 76 77 } 78 return 0; 79}
drawLandmarks.hpp
1// Summary: 繪製人臉關鍵點和多邊形線 2// Author: Amusi 3// Date: 2018-03-20 4 5#ifndef _renderFace_H_ 6#define _renderFace_H_ 7 8#include <iostream> 9#include <opencv2/opencv.hpp> 10 11using namespace cv; 12using namespace std; 13 14#define COLOR Scalar(255, 200,0) 15 16// drawPolyline經過鏈接開始和結束索引之間的連續點來繪製多邊形線。 17void drawPolyline 18( 19 Mat &im, 20 const vector<Point2f> &landmarks, 21 const int start, 22 const int end, 23 bool isClosed = false 24) 25{ 26 // 收集開始和結束索引之間的全部點 27 vector <Point> points; 28 for (int i = start; i <= end; i++) 29 { 30 points.push_back(cv::Point(landmarks[i].x, landmarks[i].y)); 31 } 32 33 // 繪製多邊形曲線 34 polylines(im, points, isClosed, COLOR, 2, 16); 35 36} 37 38// 繪製人臉關鍵點 39void drawLandmarks(Mat &im, vector<Point2f> &landmarks) 40{ 41 // 在臉上繪製68點及輪廓(點的順序是特定的,有屬性的) 42 if (landmarks.size() == 68) 43 { 44 drawPolyline(im, landmarks, 0, 16); // Jaw line 45 drawPolyline(im, landmarks, 17, 21); // Left eyebrow 46 drawPolyline(im, landmarks, 22, 26); // Right eyebrow 47 drawPolyline(im, landmarks, 27, 30); // Nose bridge 48 drawPolyline(im, landmarks, 30, 35, true); // Lower nose 49 drawPolyline(im, landmarks, 36, 41, true); // Left eye 50 drawPolyline(im, landmarks, 42, 47, true); // Right Eye 51 drawPolyline(im, landmarks, 48, 59, true); // Outer lip 52 drawPolyline(im, landmarks, 60, 67, true); // Inner lip 53 } 54 else 55 { 56 // 若是人臉關鍵點數不是68,則咱們不知道哪些點對應於哪些面部特徵。因此,咱們爲每一個landamrk畫一個圓圈。 57 for(int i = 0; i < landmarks.size(); i++) 58 { 59 circle(im,landmarks[i],3, COLOR, FILLED); 60 } 61 } 62 63} 64 65#endif // _renderFace_H_
實驗結果
Reference
[1]Tutorial:https://www.learnopencv.com/facemark-facial-landmark-detection-using-opencv/
[2]FacemarkKazemi:https://docs.opencv.org/trunk/dc/de0/classcv_1_1face_1_1FacemarkKazemi.html
[3]One Millisecond Face Alignment with an Ensemble of Regression Trees:http://www.csc.kth.se/~vahidk/face_ert.html
[4]FacemarkAAM:
https://docs.opencv.org/trunk/d5/d7b/classcv_1_1face_1_1FacemarkAAM.html
[5]Optimization problems for fast AAM fitting in-the-wild:
https://ibug.doc.ic.ac.uk/media/uploads/documents/tzimiro_pantic_iccv2013.pdf
[6]FacemarkLBF:https://docs.opencv.org/trunk/dc/d63/classcv_1_1face_1_1FacemarkLBF.html
[7]Face alignment at 3000 fps via regressing local binary features:http://www.jiansun.org/papers/CVPR14_FaceAlignment.pdf
[8]lbfmodel.yaml:https://github.com/kurnianggoro/GSOC2017/blob/master/data/lbfmodel.yaml