惯例开头放结论:
1.光照对于人脸检测的影响非常大,光照充足且均匀更方便人脸检测
2.特征点匹配花费时间较少(每个大约3-5ms),人脸检测用640*480的摄像头大概每帧需要100ms,之后有空写一篇博客针对这个缺点进行算法改进。
-----------------------------------------------------------------------
今天上午在食堂测试Dlib人脸特征点检测程序,效果好到爆炸,所以忍不住来写一篇博客了……
首先放一张效果图吧,可以看出来即便扭头角度达到近乎九十度也能较好地识别出来(比之前在图书馆以及寝室以及实验室的效果要好很多)
初步分析为光照问题,本次测试是在光线充足且均匀的食堂,环境如下:
在寝室环境下80%的情况会检测不到人脸(效果很差),故而在结果层面,至少人脸检测部分对于光照的依赖性非常强。
在食堂环境下的动态效果如下:
在实验室光照一般情况下的效果:
在寝室基本检测不出人脸就不放图了
可以看得出来在实验室的时候脸稍微测一下基本就检测不出人脸了,但是在食堂环境下偏侧较大的角度仍能较为准确地检测出人脸……
故而均匀的光照是这种人脸检测方法的鲁棒性的必要条件
-----------------------------------
下面来看下Dlib人脸检测部分的代码,总共有两块核心内容:
1.人脸检测(也就是检测出有人脸)
核心代码如下:
frontal_face_detector detector = get_frontal_face_detector();
2.特定点定位(在人脸检测的矩形框基础之上进行特征点标定)
核心关键代码如下:
①载入训练好的模型:
shape_predictor pose_model;
deserialize("shape_predictor_68_face_landmarks.dat") >> pose_model;
②进行特征点定位:for (unsigned long i = 0; i < faces.size(); ++i)
shapes.push_back(pose_model(cimg, faces[i]));
再返回来看之前的效果图(代码粘在下面):
这台笔记本的配置如下:
可以看出在I5四代标压双核处理器的笔记本上,载入模型花费时间大约在3秒左右
每帧检测人脸Detector函数耗时大约稳定在100ms(软件运行过多的情况下会到180ms)
每张脸特征点的提取大约在3-5ms,没有脸的时候近乎是0ms,测试两个人的时候大约在6-10ms。
两个人的检测效果如下(2333,女票实力马赛克):
可以料想的是绝大部分耗时都用在了人脸检测提取之上,这也是后续可能要花费大力气去解决的问题。
如果想移植到其他处理性能一般的平台上,检测人脸的部分肯定是需要大改的……
配置Dlib见博客:
http://blog.csdn.net/zmdsjtu/article/category/6399432
详细测试代码如下:
//@[email protected]
//2016-12-9
//http://blog.csdn.net/zmdsjtu/article/details/53454071
#include
#include
#include
#include
#include
#include
#include
using namespace dlib;
using namespace std;
class 高精度计时
{
public:
高精度计时(void);
~高精度计时(void);//析构函数
private:
LARGE_INTEGER 开始时间;
LARGE_INTEGER 结束时间;
LARGE_INTEGER CPU频率;
public:
double 间隔;
public:
void 开始();
void 结束();
};
高精度计时::高精度计时(void)
{
QueryPerformanceFrequency(&CPU频率);
}
高精度计时::~高精度计时(void)
{
}
void 高精度计时::开始()
{
QueryPerformanceCounter(&开始时间);
}
void 高精度计时::结束()
{
QueryPerformanceCounter(&结束时间);
间隔 = ((double)结束时间.QuadPart - (double)开始时间.QuadPart) / (double)CPU频率.QuadPart;
}
int main()
{
高精度计时 时间;
try
{
时间.开始();
cv::VideoCapture cap(0);
if (!cap.isOpened())
{
cerr << "Unable to connect to camera" << endl;
return 1;
}
//image_window win;
// Load face detection and pose estimation models.
frontal_face_detector detector = get_frontal_face_detector();
shape_predictor pose_model;
deserialize("shape_predictor_68_face_landmarks.dat") >> pose_model;
时间.结束();
float 初始化时间 = 时间.间隔;
DWORD k = ::GetTickCount(); //获取毫秒级数目
// Grab and process frames until the main window is closed by the user.
while (cv::waitKey(30) != 27)
{
// Grab a frame
cv::Mat temp;
cap >> temp;
cv::putText(temp, "Initial Time/ms : " + to_string(初始化时间 * 1000), cv::Point(20, 380),5, 2, cvScalar(0, 0, 255));
cv_image cimg(temp);
// Detect faces
// DWORD k = ::GetTickCount(); //获取毫秒级数目
std::vector faces = detector(cimg);
时间.结束();
cout << "检测人脸部分耗时:" << 时间.间隔*1000 << endl;
cv::putText(temp, "Face Detector/ms : " + to_string(时间.间隔 * 1000), cv::Point(20, 420),5,2, cvScalar(0, 0, 255));
// cout << (::GetTickCount() - k) << endl;
// Find the pose of each face.
std::vector shapes;
// k = ::GetTickCount();
时间.开始();
for (unsigned long i = 0; i < faces.size(); ++i)
shapes.push_back(pose_model(cimg, faces[i]));
if (!shapes.empty()) {
for (int j = 0; j < shapes.size();j++){
for (int i = 0; i < 68; i++) {
circle(temp, cvPoint(shapes[j].part(i).x(), shapes[j].part(i).y()), 2, cvScalar(255, 0, 0), -1);
// shapes[0].part(i).x();//68个
}
}
}
时间.结束();
cout << "剩余部分的总时间:"<< 时间.间隔 * 1000 << endl<
最后祝被打马赛克的人天天开心~
当然也祝大家开发愉快咯~