Summary:利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection)

Author:    Amusi

Date:       2018-03-20

Note:       OpenCV3.4以及上支持Facemark

原文:OpenCV实战:人脸关键点检测(FaceMark)

PS:点击“阅读原文”,可以下载所有源码和模型,记得给star哦!

教程目录

  • 测试环境

  • 引言

  • 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代码进行实时人脸关键点检测

步骤

1. 加载人脸检测器(face detector)

所有的人脸关键点检测算法的输入都是一个截切的人脸图像。因为,我们的第一步就是在图像中检测所有的人脸,并将所有的人脸矩形框输入到人脸关键点检测器中。这里,我们可以使用OpenCV的Haar人脸检测器或者lbp人脸检测器来检测人脸。

2. 创建Facemark对象

创建Facemark类的对象。在OpenCV中,Facemark是使用智能指针(smart pointer,PTR),所以我们不需要考虑内存泄漏问题。

3. 加载landmark检测器

加载关键点检测器(lbfmodel.yaml)。此人脸检测器是在几千幅带有关键点标签的人脸图像上训练得到的。

带有注释/标签关键点的人脸图像公共数据集可以访问这个链接下载:https://ibug.doc.ic.ac.uk/resources/facial-point-annotations/

4.从网络摄像头中捕获帧

捕获视频帧并处理。我们既可以打开一个本地视频(.mp4),也可以打开网络摄像机(如果电脑有的话)来进行人脸关键点检测。

5. 检测人脸

我们对视频的每一帧运行人脸检测器。人脸检测器的输出是一个包含一个或多个矩形(rectangles)的容器(vector),即视频帧中可能有一张或者多张人脸。

6. 运行人脸关键点检测器

我们根据人脸矩形框截取原图中的人脸ROI,再利用人脸关键点检测器(facial landmark detector)对人脸ROI进行检测。

对于每张脸我们获得,我们可以获得68个关键点,并将其存储在点的容器中。因为视频帧中可能有多张脸,所以我们应采用点的容器的容器。

7. 绘制人脸关键点

根据获得关键点,我们可以在视频帧上绘制出来并显示。

代码

本教程的代码一共有两个程序,分别为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

OpenCV实战:人脸关键点检测(FaceMark)的更多相关文章

  1. OpenCV Facial Landmark Detection 人脸关键点检测

    Opencv-Facial-Landmark-Detection 利用OpenCV中的LBF算法进行人脸关键点检测(Facial Landmark Detection) Note: OpenCV3.4 ...

  2. dlib人脸关键点检测的模型分析与压缩

    本文系原创,转载请注明出处~ 小喵的博客:https://www.miaoerduo.com 博客原文(排版更精美):https://www.miaoerduo.com/c/dlib人脸关键点检测的模 ...

  3. 用keras实现人脸关键点检测(2)

    上一个代码只能实现小数据的读取与训练,在大数据训练的情况下.会造内存紧张,于是我根据keras的官方文档,对上一个代码进行了改进. 用keras实现人脸关键点检测 数据集:https://pan.ba ...

  4. keras实现简单CNN人脸关键点检测

    用keras实现人脸关键点检测 改良版:http://www.cnblogs.com/ansang/p/8583122.html 第一步:准备好需要的库 tensorflow  1.4.0 h5py ...

  5. 机器学习进阶-人脸关键点检测 1.dlib.get_frontal_face_detector(构建人脸框位置检测器) 2.dlib.shape_predictor(绘制人脸关键点检测器) 3.cv2.convexHull(获得凸包位置信息)

    1.dlib.get_frontal_face_detector()  # 获得人脸框位置的检测器, detector(gray, 1) gray表示灰度图, 2.dlib.shape_predict ...

  6. Opencv与dlib联合进行人脸关键点检测与识别

    前言 依赖库:opencv 2.4.9 /dlib 19.0/libfacedetection 本篇不记录如何配置,重点在实现上.使用libfacedetection实现人脸区域检测,联合dlib标记 ...

  7. SmileyFace——基于OpenCV的人脸人眼检测、面部识别程序

    项目地址 https://github.com/guoyaohua/SmileyFace 开发环境 Visual Studio 2010 MFC + OpenCV 功能描述 静态图像人脸检测 视频人脸 ...

  8. opencv+python+dlib人脸关键点检测、实时检测

    安装的是anaconde3.python3.7.3,3.7环境安装dlib太麻烦, 在anaconde3中新建环境python3.6.8, 在3.6环境下安装dlib-19.6.1-cp36-cp36 ...

  9. Facial landmark detection - 人脸关键点检测

    Facial landmark detection  (Facial keypoints detection) OpenSourceLibrary: DLib Project Home:  http: ...

随机推荐

  1. React Native 如何做轮播图 react-native-swiper

    //:仿饿了么github:https://github.com/stoneWeb/elm-react-native 欢迎各位同学加入: React-Native群:397885169 大前端群:54 ...

  2. AJAX四种跨域处理方法

    同源策略 同源策略 同源策略限制从一个源加载的文档或者脚本如何与来自另一个源的资源进行交互.这是一个用于隔离潜在恶意文件的关键的安全机制. 具体定义是:一段脚本向后台请求数据,只能读取属于同一协议名. ...

  3. spring boot(18)-servlet、filter、listener

    servlet.filter.listener的用法就不讲了,只讲如何在spring boot中配置它们.有两种方式,一种是从servlet3开始提供的注解方式,另一种是spring的注入方式 ser ...

  4. Linux基础知识与基础命令

    Linux基础知识与基础命令 系统目录 Linux只有一个根目录,没有盘符的概念,文件目录是一个倒立的树形结构. 常用的目录功能 bin 与程序相关的文件 boot 与系统启动相关 cdrom 与Li ...

  5. linux 下查看外网ip

    1. curl ipinfo.io ~/codes/qt_codes/qt-5.4.1-build$ curl ipinfo.io{  "ip": "114.241.21 ...

  6. 通过HTTP参数污染绕过WAF拦截 (转)

    上个星期我被邀请组队去参加一个由CSAW组织的CTF夺旗比赛.因为老婆孩子的缘故,我只能挑一个与Web漏洞利用相关的题目,名字叫做”HorceForce”.这道题价值300点.这道题大概的背景是,你拥 ...

  7. Centos 6.5-yum安装出现错误解决方案

    最近在用Centos 6.5 的时候出现了以下情况: 遇到这种问题试试以下方法: 1.检查是否能上网:ping www.baidu.com 如果显示没有连接的话,就说明没网,也就无法使用yum 命令安 ...

  8. 在Ubuntu17.04中遇到无法清空回收站解决方法

    在Ubuntu17.04下,遇到清空回收站文件时报错,提示”Failed to delete the item from the trash”,无法清空回收站. 回收站其实就是一个文件夹,存放着被删掉 ...

  9. 配置nginx支持TP框架

    TP框架配置中默认URL_MODEL=1,而Nginx默认是不支持PATHINFO的.如果我们只想跑起来tp框架,很简单,只需到更改TP配置,设置URL_MODEL=3(兼容模式).但是如果要让Ngi ...

  10. 软件架构方面基础-ESB \SOA \GEO-ESB

    学习初稿 软件架构演变历史 SOA  (Service-Oriented Architecture)面向服务的体系结构 它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起 ...