本文转载自:https://blog.csdn.net/KayChanGEEK/article/details/80008875
下载dlib source和shape_predictor_68_face_landmarks.dat
到dlib官网的GitHub下载入口dlib-source和shape_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下的可执行程序可以直接运行)。