Dlib实现人脸特征点检测全过程



本文转载自:https://blog.csdn.net/KayChanGEEK/article/details/80008875

下载dlib source和shape_predictor_68_face_landmarks.dat

    到dlib官网的GitHub下载入口dlib-sourceshape_predictor_68_face_landmarks.dat

CMake dlib

    最新版本的dlib需要C++11的支持,所以在windows-msvc编译器至少要vs2015(msvc14)的。之前的18.*版本的不需要C++11,起初本人PC上只有VS2013,只能cmake老版本的dlib,cmake也成功了,但是在使用的时候却报错,报错如下图:

使出浑身解数度娘和调试一段时间无果后,还是放弃了···,不过大概出错的地方在哪里,出错的地方实在调用dlib的人脸检测器的时候编译就会报这个错(代码为:std::vector<dlib::rectangle> faces = detector(frame);)···,但是把这句注释掉,编译就可以过,所以灵机一动想到了一个解决方法:干脆换别的人脸检测器比如opencv的harris等,我换成了利用opencv-dnn加载resnet+ssd的人脸检测,检测结果也是一个矩形ROI,现在要做的就是将矩形ROI(cv::Rect)转换成dlib::rectangle就可以了啊,对吧,查看了dlib::rectangle的构造函数,就是输入ROI左上角坐标和右下角坐标就好了,于是进行了cv::Rect到dlib::rectangle的转换,结果编译通过了,嘻嘻很激动···,结果运行时奔溃···,debug进去也不知道是个怎么肥四···。于是还是老老实实的装了VS2015。为了少走弯路,VS2015以下版本的兄弟姐妹的还是在装一个VS2015上去吧!

    好了,废话了这么多,进入正题cmake dlib。这个比cmake opencv要简单多了。下载了dlib源码后,在源码目录下建立一个build文件夹,进入build文件夹下建立一个dlib_sdk文件夹。然后打开cmake-gui,配置如下图:

然后点击configure,编译器选择VS2015X64的,不出意外就成功了,然后会出现一些配置项目,修改其中的CMAKE_INSTALL_PREFIX配置项,设置其路径为刚才在build目录下新建的dlib_sdk路径,如下图:

再次点击configure,然后点击generate,然后点击Open Project(如果有多个VS版本请使用VS2015打开)。打开后选择解决方案-INSTALL-右键-生成,如下图:

然后切换到release,INSTALL-右键-生成(噢,对了,很重要的事情,在切换到release前请先将dlib_sdk目录下的lib备份一下···,否则切换到release生成后会覆盖掉debug下的lib,然后你再使用debug模式写代码就会出错,都是坑啊)。到此cmake完成,会在dlib_sdk目录下生成我们需要的lib和include。

配置dlib

    新建工程-工程属性-C/C++-附加包含目录,添加cv_sdk目录下的include路径。

    工程属性-附加库目录,添加cv_sdk目录下的lib路径。

    工程属性-输入-附加依赖项,添加cv_sdk目录下的lib目录下的dlib.lib(当然debug和release要分开)。

配置opencv

    略。

主要代码

    利用dlib封装一个人脸特征检测的单例类

FaceDetector.h

FaceDetector.cpp

#include "FaceDetector.h"

FaceDetector *FaceDetector::inst = new FaceDetector();

FaceDetector::FaceDetector() {

 
}

FaceDetector::~FaceDetector() {

 if (inst != nullptr) {

  delete inst;
  inst = nullptr;
 }
}

FaceDetector *FaceDetector::I() {

 if (inst == nullptr) inst = new FaceDetector();
 return inst;
}

void FaceDetector::init() {

 // Load face detection and pose estimation models.
 detector = get_frontal_face_detector();
 deserialize("shape_predictor_68_face_landmarks/shape_predictor_68_face_landmarks.dat") >> pose_model;
}

std::vector<cv::Point> FaceDetector::detect(cv::Mat &image, bool isDraw) {

 std::vector<cv::Point> landmarks;
 cv_image<bgr_pixel> cimg(image);
 // Detect faces
 std::vector<dlib::rectangle> faces = detector(cimg);

 std::vector<full_object_detection> shapes;
 for (unsigned long i = 0; i < faces.size(); ++i){

  full_object_detection shape = pose_model(cimg, faces[i]);
  shapes.push_back(shape);
  for (int j = 0; j < 68; ++j) {

   cv::Point p = cv::Point(shapes[i].part(j).x(), shapes[i].part(j).y());
   landmarks.push_back(p);
   if(isDraw)
    cv::circle(image, p, 3, cv::Scalar(255, 0, 0), -1);
  }
 }
 return landmarks;
}

void FaceDetector::draw68Landmarks(cv::Mat &image, std::vector<cv::Point> landmarks, cv::Scalar color, int radius) {

 for (int i = 0; i < landmarks.size(); i++) {

  cv::circle(image, landmarks[i], radius, color, -1);
  //cv::putText(image, to_string(i), landmarks[i], CV_FONT_HERSHEY_PLAIN, 1, cv::Scalar(0, 0, 255));
 }
}
调用示例代码

FaceDetector::I()->init(); // 初始化
std::vector<cv::Point> landmarks = FaceDetector::I()->detect(image); // 返回特征点集
FaceDetector::I()->draw68LandmarksNet(image, landmarks, GetCurColor(), 1); // 画特征点集

错误解决

    在以上准备就绪后编译可能还会出错如下图:

解决方法是打开dlib_sdk目录下的include目录下的dlib/threads/threads_kernel_shared.h文件,将其中的一段代码注释掉,保存,再次编译就OK了,如下图所示:

运行效果

本地图片(附上我伦帅照)

相机实时

附录

    源代码工程戳这里(注:release下的可执行程序可以直接运行)。

猜你喜欢

转载自blog.csdn.net/xirongxu_dlut/article/details/80737733