前面一篇写了编译人脸检测部分,现在就介绍下人脸配准部分,SeetaFace的Face Alignment通过人脸的五个关键点来配准人脸,也就是双眼、鼻尖、两个嘴角。

这部分的编译也和上一篇一样,步骤如下:

1、创建空的DLL工程:

 

2、修改配置器:

 

3、添加include:

 

这里要注意,因为人脸配准需要先检测人脸,会用到前面配置好的人脸检测,所以要加上其头文件;

4、添加Lib文件路径和依赖项

 

 

5、修改预处理器:

 

6、打开OpenMP:

 

7、添加源文件到工程:

image.png

 

一样,先将SeetaFaceEngine\FaceDetection\src下的所有文件和文件夹(test除外)都复制到工程目录下,并将全部文件添加到工程中。

8、编译工程(Release的步骤也是一样的)

9、使用Face Alignment

这里使用的是FaceAlignment\src\test下的face_alignment_test.cpp,需要根据自己的路径修改模型和数据的路径

int testFaceAlignment(std::string src_Path)
{
    seeta::FaceDetection detector("D:/SeetaFaceEngine/include_lib/model/FaceDetection/seeta_fd_frontal_v1.0.bin");
    detector.SetMinFaceSize(40);
    detector.SetScoreThresh(2.f);
    detector.SetImagePyramidScaleFactor(0.8f);
    detector.SetWindowStep(4, 4);

    // Initialize face alignment model 
    seeta::FaceAlignment point_detector((MODEL_DIR + "seeta_fa_v1.1.bin").c_str());

    //load image
    IplImage *img_grayscale = NULL;
    img_grayscale = cvLoadImage(src_Path.c_str(), 0);
    if (img_grayscale == NULL)
    {
    	return 0;
    }

    IplImage *img_color = cvLoadImage(src_Path.c_str(), 1);
    int pts_num = 5;
    int im_width = img_grayscale->width;
    int im_height = img_grayscale->height;
    unsigned char* data = new unsigned char[im_width * im_height];
    unsigned char* data_ptr = data;
    unsigned char* image_data_ptr = (unsigned char*)img_grayscale->imageData;
    int h = 0;
    for (h = 0; h < im_height; h++) 
    {
    	memcpy(data_ptr, image_data_ptr, im_width);
    	data_ptr += im_width;
    	image_data_ptr += img_grayscale->widthStep;
    }

	seeta::ImageData image_data;
	image_data.data = data;
	image_data.width = im_width;
	image_data.height = im_height;
	image_data.num_channels = 1;

	// Detect faces
	std::vector<seeta::FaceInfo> faces = detector.Detect(image_data);
	int32_t face_num = static_cast<int32_t>(faces.size());

	if (face_num == 0)
	{
		delete[]data;
		cvReleaseImage(&img_grayscale);
		cvReleaseImage(&img_color);
		return 0;
	}

	// Detect 5 facial landmarks
	seeta::FacialLandmark points[5];
	point_detector.PointDetectLandmarks(image_data, faces[0], points);

	// Visualize the results
	cvRectangle(img_color, cvPoint(faces[0].bbox.x, faces[0].bbox.y), cvPoint(faces[0].bbox.x + faces[0].bbox.width - 1, faces[0].bbox.y + faces[0].bbox.height - 1), CV_RGB(255, 0, 0));
	for (int i = 0; i < pts_num; i++)
	{
		cvCircle(img_color, cvPoint(points[i].x, points[i].y), 2, CV_RGB(0, 255, 0), CV_FILLED);
	}
    // 	cvSaveImage("result.jpg", img_color);
	cvShowImage("dst", img_color);
	cvWaitKey(0);

	// Release memory
	cvReleaseImage(&img_color);
	cvReleaseImage(&img_grayscale);
	delete[]data;
}

关键点检测的结果:

桃源一向绝风尘柳市南头访隐沦。
到门不敢题凡鸟,看竹何须问主人。
城上青山如屋里,东家流水入西邻。
闭户著书多岁月,种松皆老作龙鳞。

  -- 王维 《春日与裴迪过新昌里访吕逸人不遇》