C++ OpenCV人脸图像提取

本文介绍如何使用C++与OpenCV实现人脸提取及特征点检测,包括使用DNN进行人脸检测、特征点定位及凸包检测生成图像掩膜等关键技术。

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为2168,预计阅读6分钟

前言

C++ OpenCV Contrib模块LBF人脸特征点检测》文章中已经介绍了人脸特征点的检测,本篇文章是在原代码的基础上实现人脸的提取。

实现效果

从上图上可以看到,左边蓝色方框里面是截取的人脸图像,然后在人脸图像的基础上针对特征点选定区域,最后生成右边圆框中的人脸图像。

#实现方式
1使用DNN检测到人脸并截取人脸部分区域
2在截取的人脸区域中检测人脸68个特征点
3针对68个特征点实现凸包检测形成图像掩膜
4
根据掩膜提取图像的人脸信息

关于人脸68个特征点

微卡智享

上图中介绍了人脸特征点的几个关键位置:

位置
点的范围
左侧下巴轮廓
0-7
下巴
8
右侧下巴轮廓
9-16
左侧眉毛
17-21
右侧眉毛
22-26
鼻梁区域
27-30 ‍
鼻底区域
31-35
左眼
36-41
右眼
42-47
嘴唇外缘
48-59
嘴唇内缘
60-67

人脸关键点

  • 鼻尖   30

  • 鼻根   27

  • 下巴   8

  • 左眼外角    36   

  • 左眼内角    39

  • 右眼外角    45

  • 右眼内角    42

  • 嘴中心    66

  • 嘴左角    48

  • 嘴右角    54

  • 左脸最外    0

  • 右脸最外    16

核心代码

微卡智享

//初始化模版人脸
void InitFaceMarkModel(Mat& frame, Rect rect, Mat& dst, vector<Point2f>& dstfacemarkmodel)
{
  vector<int> faceid = { 30,27,8,36,39,45,42,66,48,54,0,16 };
  vector<int>::iterator it;


  dst = Mat(frame, rect);


  Mat tmpmodel;
  dst.copyTo(tmpmodel);


  Rect tmprect = Rect(0, 0, dst.cols, dst.rows);
  vector<Rect> tmprects;
  tmprects.push_back(tmprect);
  vector<vector<Point2f>> tmpfacemodels;
  facemarkdetect.facemarkdetector(dst, tmprects, tmpfacemodels);
  Mat tmpdst = Mat::zeros(dst.size(), CV_8UC1);
  if (tmpfacemodels.size() > 0) {
    facemarkmodel = tmpfacemodels[0];
    
    //将vector<Point2f>转为vector<Point>用于做凸包检测
    vector<Point> facemarkcontour;    
    for (int i = 0; i < facemarkmodel.size(); ++i) {
      facemarkcontour.push_back(Point(facemarkmodel[i].x, facemarkmodel[i].y));
      //it = find(faceid.begin(), faceid.end(), i);
      //if (it != faceid.end()) {
      //  putText(tmpmodel, to_string(i), facemarkmodel[i], FONT_HERSHEY_PLAIN, 1, Scalar(255, 0, 0));
      //}
      cout << "模版特征点"<< i <<":" << facemarkmodel[i] << endl;
    }


    //凸包检测
    vector<Point> contourhull;
    convexHull(facemarkcontour, contourhull);


    //存入二维数组vector<vector<Point>>中用于画轮廓处理
    vector<vector<Point>> contours;
    contours.push_back(contourhull);
    //画轮廓并添充
    drawContours(tmpdst, contours, -1, Scalar(255, 255, 255), -1);
  }


  dst = Mat::zeros(tmpmodel.size(), CV_8UC3);
  tmpmodel.copyTo(dst, tmpdst);
  imshow("dst", dst);


  //resize(tmpmodel, tmpmodel, Size(0, 0), 5, 5);
  imshow("srcmodel", tmpmodel);
  imshow("tmpdst", tmpdst);
}

划重点

上面的代码还是比较简单的,两个需要注意的点:

  1. 人脸关键点检测出来的数据是vector<vector<Point2f>>,而做凸包检测的时候需要将vector<vector<Point2f>>转换成vector<vector<Point>>。

  2. 做区域掩膜时先生成一张相同大小的全黑的图片,然后把要截取的区域全部填充为白色,再通过copyto的方式生成即可。

结语

源码下一篇会再提交上去,现在的源码在处理人脸的Delaunay三角形的

提取,正好遇到了问题。等下篇的时候一起说一下。

扫描二维码

获取更多精彩

微卡智享

「 往期文章 」

C++ OpenCV Contrib模块LBF人脸特征点检测

牛气冲天

OpenCV源码Android端编译,用时三天,我编了个寂寞。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值