到dlib官网的GitHub下载入口dlib-source和shape_predictor_68_face_landmarks.dat。
最新版本的dlib需要C++11的支持,所以在windows-msvc编译器至少要vs2015(msvc14)的。之前的18.*版本的不需要C++11,起初本人PC上只有VS2013,只能cmake老版本的dlib,cmake也成功了,但是在使用的时候却报错,报错如下图:
使出浑身解数度娘和调试一段时间无果后,还是放弃了···,不过大概出错的地方在哪里,出错的地方实在调用dlib的人脸检测器的时候编译就会报这个错(代码为:std::vector
好了,废话了这么多,进入正题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。
新建工程-工程属性-C/C++-附加包含目录,添加dlib_sdk目录下的include路径。
工程属性-附加库目录,添加dlib_sdk目录下的lib路径。
工程属性-输入-附加依赖项,添加dlib_sdk目录下的lib目录下的dlib.lib(当然debug和release要分开)。
略。
利用dlib封装一个人脸特征检测的单例类
#ifndef FACEDETECTOR
#define FACEDETECTOR
#include
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
using namespace dlib;
class FaceDetector
{
public:
static FaceDetector *I();
void init();
std::vector detect(cv::Mat &image, bool isDraw = false);
void draw68Landmarks(cv::Mat &image, std::vector landmarks, cv::Scalar color = cv::Scalar(255, 0, 0), int radius = 3);
private:
FaceDetector();
~FaceDetector();
static FaceDetector *inst;
frontal_face_detector detector;
shape_predictor pose_model;
};
#endif
#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 FaceDetector::detect(cv::Mat &image, bool isDraw) {
std::vector landmarks;
cv_image cimg(image);
// Detect faces
std::vector faces = detector(cimg);
std::vector 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 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 landmarks = FaceDetector::I()->detect(image); // 返回特征点集
FaceDetector::I()->draw68LandmarksNet(image, landmarks, GetCurColor(), 1); // 画特征点集
在以上准备就绪后编译可能还会出错如下图:
解决方法是打开dlib_sdk目录下的include目录下的dlib/threads/threads_kernel_shared.h文件,将其中的一段代码注释掉,保存,再次编译就OK了,如下图所示:
源代码工程戳这里(注:release下的可执行程序可以直接运行)。