使用ShiqiYu老师的 face landmark detection方法进行人脸识别与人脸转动角度的计算,使用的是
ShiqiYu老师在2017年1月更新的代码。
Github地址:https://github.com/ShiqiYu/libfacedetection
其代码较2015年的版本做了一些修改,
其中提供了
frontal,frontal-surveillance,multiview,multiview_reinforce四种方法。每种方法的耗费时间与检测的人脸转向的范围有所不同,在Github中对其效果差异做了详细说明。
使用multiview_reinforce为例进行编写,此次改动在调用函数中做了参数的修改需要注意。
各个参数的含义如下:
FACEDETECTDLL_API int * facedetect_multiview_reinforce(unsigned char * result_buffer, //buffer memory for storing face detection results, !!its size must be 0xC004 Bytes!!
unsigned char * gray_image_data, int width, int height, int step, //input image, it must be gray (single-channel) image!
float scale, //scale factor for scan windows
int min_neighbors, //how many neighbors each candidate rectangle should have to retain it
int min_object_width, //Minimum possible face size. Faces smaller than that are ignored.
int max_object_width = 0, //Maximum possible face size. Faces larger than that are ignored. It is the largest posible when max_object_width=0.
int doLandmark = 0); // landmark detection
在提供的example例子上进行了修改,使用OpenCV接口读取摄像头的图片,进行实时操作。代码如下:
//2017.2.6
#include
#include
#include "facedetect-dll.h"
#pragma comment(lib,"libfacedetect.lib")
//#pragma comment(lib,"libfacedetect-x64.lib")
//define the buffer size. Do not change the size!
#define DETECT_BUFFER_SIZE 0x20000
using namespace cv;
void OnMouseAction(int event, int x, int y, int falgs, void *ustc);
bool stime = false;
int main(int argc, char* argv[])
{
Mat gray;
Mat frame;
Mat new_frame;
int resize_height = 480;
int resize_width = 640;
int * pResults = NULL;
unsigned char * pBuffer = (unsigned char *)malloc(DETECT_BUFFER_SIZE);
if(!pBuffer)
{
fprintf(stderr, "Can not alloc buffer.\n");
return -1;
}
VideoCapture capture(0);
while (stime==false)
{
capture >> frame;
cv::resize(frame, new_frame, cv::Size(resize_width, resize_height), (0.0), (0.0), cv::INTER_LINEAR);
cvtColor(new_frame, gray, CV_BGR2GRAY);
int doLandmark = 1;
pResults = facedetect_multiview_reinforce(pBuffer, (unsigned char*)(gray.ptr(0)), gray.cols, gray.rows, (int)gray.step,
1.2f, 3, 24, 0, doLandmark);
//printf("%d faces detected.\n", (pResults ? *pResults : 0));
Mat result_multiview_reinforce = new_frame.clone();;
//print the detection results
for (int i = 0; i < (pResults ? *pResults : 0); i++)
{
short * p = ((short*)(pResults + 1)) + 142 * i;
int x = p[0];
int y = p[1];
int w = p[2];
int h = p[3];
int neighbors = p[4];
int angle = p[5];
printf("face_rect=[%d, %d, %d, %d], neighbors=%d, angle=%d\n", x, y, w, h, neighbors, angle);
rectangle(result_multiview_reinforce, Rect(x, y, w, h), Scalar(0, 255, 0), 2);
if (doLandmark)
{
for (int j = 0; j < 68; j++)
circle(result_multiview_reinforce, Point((int)p[6 + 2 * j], (int)p[6 + 2 * j + 1]), 1, Scalar(0, 255, 0));
}
}
imshow("Results_multiview_reinforce", result_multiview_reinforce);
waitKey(30);
setMouseCallback("Results_multiview_reinforce",OnMouseAction);
}
//release the buffer
free(pBuffer);
return 0;
}
void OnMouseAction(int event, int x, int y, int falgs, void *ustc)
{
if (event==CV_EVENT_LBUTTONDOWN)
{
stime = true;
}
else
{
stime = false;
}
}
效果图如下:
评价一下性能的话,识别效果确实不错。不足点的话一是当人脸有部分遮挡、低头或仰头时无法识别,因此更适合应用于正面下人脸左右摆动识别,如各种身份确认等领域。不是用在安防等领域的检测跟踪的应用背景中。