如何使用 SeetaFaceEngine 人脸检测库实现人脸三部曲?

如何使用 SeetaFaceEngine 人脸检测库实现人脸三部曲?

  • 人脸检测 FaceDetection
  • 人脸校准 FaceAlignment
  • 人脸识别 FaceIdentification

https://github.com/seetaface/SeetaFaceEngine

前期准备

  1. SeetaFaceEngine 编译 Win32 动态库
  2. 编译 Opencv Win32 库

Note:

该代码测试环境 Win7 x64 SeetaFaceEngine Win32 动态库 Opencv3.3.0 Win32 动态库

测试结果

使用多张脸图片,图中可以标记图人脸的特征点

使用两张原图对比,相似度达到 0.99

使用一张原图和angelababy图片做对比,相似度达到 0.46

使用两张angelababy图像做对比,相似度达到 0.64 ,主要这两个样本人脸方向差异太大

使用一张angelababy图像和dilraba图像做对比,相似度 0.64

使用一张angelababy图像和dilraba图像做对比,相似度 0.53 ,这张人脸方向差异不大

使用两张dilraba图像做对比,相似度 0.68

使用两张dilraba图像做对比,相似度 0.80

使用两张dilraba图像做对比,相似度 0.50,人脸方向差异大

1. 人脸检测

#include <stdlib.h>
#include <iostream>
#include <string>
#include "opencv2\highgui.hpp" //GUI模块
#include "opencv2\imgproc.hpp" //图像处理模块
#include "opencv2\imgcodecs.hpp" //图像读写模块
#include "opencv2\core.hpp" //核心模块
#include "face_detection.h" //SeetaFaceEngine 人脸检测模块
#pragma comment(lib,"opencv_highgui330.lib")
#pragma comment(lib,"opencv_imgproc330.lib")
#pragma comment(lib,"opencv_imgcodecs330.lib")
#pragma comment(lib,"opencv_core330.lib")
#pragma comment(lib,"FaceDetection.lib")

using namespace std;
using namespace cv;
using namespace seeta;

int main()
{
	//加载模型
	seeta::FaceDetection detector("model/seeta_fd_frontal_v1.0.bin");
	//设置参数
	detector.SetMinFaceSize(40);//设置检测器最小尺寸,默认为20。
	detector.SetScoreThresh(2.f);//设置检测阈值
	detector.SetImagePyramidScaleFactor(0.8f);//设置图像金字塔缩放系数
	detector.SetWindowStep(4, 4);//设置滑动窗口步长
	//读取待检测图像并转换为灰度图像。
	cv::Mat img = cv::imread("1.jpg", cv::IMREAD_UNCHANGED);
	cv::Mat img_gray;
	if (img.channels() != 1)
	{
		cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
	}
	else
	{
		img_gray = img;
	}
	//初始化 seeta::ImageData  图像数据结构体
	seeta::ImageData img_data;
	img_data.data = img_gray.data;
	img_data.width = img_gray.cols;
	img_data.height = img_gray.rows;
	img_data.num_channels = 1;
	//开始检测人脸并获取运行时间
	long t0 = cv::getTickCount();
	std::vector<seeta::FaceInfo> faces = detector.Detect(img_data);
	long t1 = cv::getTickCount();
	double secs = (t1 - t0) / cv::getTickFrequency();
	//获取搜寻到人脸的数量并绘制矩形框
	cv::Rect face_rect;
	int32_t num_face = static_cast<int32_t>(faces.size());
	for (int32_t i = 0; i < num_face; i++) {
		face_rect.x = faces[i].bbox.x;
		face_rect.y = faces[i].bbox.y;
		face_rect.width = faces[i].bbox.width;
		face_rect.height = faces[i].bbox.height;

		cv::rectangle(img, face_rect, CV_RGB(0, 255, 0), 2, 8, 0);
	}
	//显示最后结果图像
	cv::namedWindow("Win7", cv::WINDOW_AUTOSIZE);
	cv::imshow("Win7",img);
	cv::waitKey(0);
	cv::destroyAllWindows();
	system("pause");
  return 0;
}

2. 人脸校正

#include <stdlib.h>
#include <iostream>
#include <string>
#include "opencv2\highgui.hpp" //GUI模块
#include "opencv2\imgproc.hpp" //图像处理模块
#include "opencv2\imgcodecs.hpp" //图像读写模块
#include "opencv2\core.hpp" //核心模块
#include "face_detection.h" //SeetaFaceEngine			人脸检测模块
#include "face_alignment.h" //SeetaFaceAlignment		人脸校准模块

#pragma comment(lib,"opencv_highgui330.lib")
#pragma comment(lib,"opencv_imgproc330.lib")
#pragma comment(lib,"opencv_imgcodecs330.lib")
#pragma comment(lib,"opencv_core330.lib")
#pragma comment(lib,"FaceDetection.lib")
#pragma comment(lib,"SeetaFaceAlignment.lib")

using namespace std;
using namespace cv;
using namespace seeta;


int main()
{
	//加载模型
	seeta::FaceDetection detector("model/seeta_fd_frontal_v1.0.bin");
	seeta::FaceAlignment point_detector("model/seeta_fa_v1.1.bin");

	//设置参数
	detector.SetMinFaceSize(40);//设置检测器最小尺寸,默认为20。
	detector.SetScoreThresh(2.f);//设置检测阈值
	detector.SetImagePyramidScaleFactor(0.8f);//设置图像金字塔缩放系数
	detector.SetWindowStep(4, 4);//设置滑动窗口步长
	//读取待检测图像并转换为灰度图像。
	cv::Mat img = cv::imread("000.jpg", cv::IMREAD_UNCHANGED);
	cv::Mat img_gray;
	if (img.channels() != 1)
	{
		cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
	}
	else
	{
		img_gray = img;
	}
	//初始化 seeta::ImageData  图像数据结构体
	seeta::ImageData img_data;
	img_data.data = img_gray.data;
	img_data.width = img_gray.cols;
	img_data.height = img_gray.rows;
	img_data.num_channels = 1;
	//开始检测人脸并获取运行时间
	long t0 = cv::getTickCount();
	std::vector<seeta::FaceInfo> faces = detector.Detect(img_data);
	long t1 = cv::getTickCount();
	double secs = (t1 - t0) / cv::getTickFrequency();
	//检测5个特征点
	int pts_num = 5;
	seeta::FacialLandmark points[5];
	//获取搜寻到人脸的数量并绘制矩形框
	cv::Rect face_rect;
	int32_t num_face = static_cast<int32_t>(faces.size());
	for (int32_t i = 0; i < num_face; ++i) {
		face_rect.x = faces[i].bbox.x;
		face_rect.y = faces[i].bbox.y;
		face_rect.width = faces[i].bbox.width;
		face_rect.height = faces[i].bbox.height;
		cv::rectangle(img, face_rect, CV_RGB(0, 255, 0), 2, 8, 0);
		//开始查找特征点
		point_detector.PointDetectLandmarks(img_data, faces[i], points);
		//绘制
		//cv::rectangle(img, 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), 0, 0, 0);
		for (int j = 0; j<pts_num; ++j)
		{
			cv::circle(img, cvPoint(points[j].x, points[j].y), 2, CV_RGB(0, 255, 0), CV_FILLED);
		}
	}
	cv::resize(img, img, cv::Size(img.cols * 1, img.rows * 1));
	//显示最后结果图像
	cv::namedWindow("Win7", cv::WINDOW_AUTOSIZE);
	cv::imshow("Win7", img);
	cv::waitKey(0);
	cv::destroyAllWindows();
	system("pause");
	return 0;
}

3.人脸识别

#include <stdlib.h>
#include <iostream>
#include <string>
#include "opencv2\highgui.hpp" //GUI模块
#include "opencv2\imgproc.hpp" //图像处理模块
#include "opencv2\imgcodecs.hpp" //图像读写模块
#include "opencv2\core.hpp" //核心模块
#include "face_detection.h" //SeetaFaceEngine			人脸检测模块
#include "face_alignment.h" //SeetaFaceAlignment		人脸校准模块
#include "face_identification.h" //FaceIdentification	人脸识别模块
#pragma comment(lib,"opencv_highgui330.lib")
#pragma comment(lib,"opencv_imgproc330.lib")
#pragma comment(lib,"opencv_imgcodecs330.lib")
#pragma comment(lib,"opencv_core330.lib")
#pragma comment(lib,"FaceDetection.lib")
#pragma comment(lib,"SeetaFaceAlignment.lib")
#pragma comment(lib,"FaceIdentification.lib")
using namespace std;
using namespace cv;
using namespace seeta;


int main()
{
	//加载模型
	seeta::FaceDetection detector("model/seeta_fd_frontal_v1.0.bin");
	seeta::FaceAlignment point_detector("model/seeta_fa_v1.1.bin");
	seeta::FaceIdentification face_recognizer("model/seeta_fr_v1.0.bin");
	//设置参数
	detector.SetMinFaceSize(40);//设置检测器最小尺寸,默认为20。
	detector.SetScoreThresh(2.f);//设置检测阈值
	detector.SetImagePyramidScaleFactor(0.8f);//设置图像金字塔缩放系数
	detector.SetWindowStep(4, 4);//设置滑动窗口步长
	//读取待检测图像并转换为灰度图像。
	cv::Mat img = cv::imread("Dilraba3.jpg", cv::IMREAD_UNCHANGED);
	//保存彩色图像样本用于裁剪
	cv::Mat _img = img.clone();
	ImageData src_img_data(_img.cols, _img.rows, _img.channels());
	src_img_data.data = _img.data;
	cv::Mat img_gray;
	if (img.channels() != 1)
	{
		cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY);
	}
	else
	{
		img_gray = img;
	}
	//初始化 seeta::ImageData  图像数据结构体
	seeta::ImageData img_data;
	img_data.data = img_gray.data;
	img_data.width = img_gray.cols;
	img_data.height = img_gray.rows;
	img_data.num_channels = 1;
	//开始检测人脸并获取运行时间
	long t0 = cv::getTickCount();
	std::vector<seeta::FaceInfo> faces = detector.Detect(img_data);
	long t1 = cv::getTickCount();
	double secs = (t1 - t0) / cv::getTickFrequency();
	//检测5个特征点
	int pts_num = 5;
	seeta::FacialLandmark points[5];
	//获取搜寻到人脸的数量并绘制矩形框
	cv::Rect face_rect;
	int32_t num_face = static_cast<int32_t>(faces.size());
	for (int32_t i = 0; i < num_face; ++i) {
		face_rect.x = faces[i].bbox.x;
		face_rect.y = faces[i].bbox.y;
		face_rect.width = faces[i].bbox.width;
		face_rect.height = faces[i].bbox.height;
		cv::rectangle(img, face_rect, CV_RGB(0, 255, 0), 2, 8, 0);
		//开始查找特征点
		point_detector.PointDetectLandmarks(img_data, faces[i], points);
		//绘制
		//cv::rectangle(img, 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), 0, 0, 0);
		for (int j = 0; j<pts_num; ++j)
		{
			cv::circle(img, cvPoint(points[j].x, points[j].y), 2, CV_RGB(0, 255, 0), CV_FILLED);
		}
	}
	//创建一个用来存储根据5个特征点裁剪后的图像
	cv::Mat dst_img(face_recognizer.crop_height(),face_recognizer.crop_width(),CV_8UC(face_recognizer.crop_channels()));
	ImageData dst_img_data(dst_img.cols, dst_img.rows, dst_img.channels());
	dst_img_data.data = dst_img.data;
	//裁剪图像并显示 256x256
	face_recognizer.CropFace(src_img_data,points,dst_img_data);
	cv::imwrite("Dilraba3Crop.jpg", dst_img);
	cv::imshow("Crop Face", dst_img);

	//判定特征维度是否等于2048
	int feat_size = face_recognizer.feature_size();
	if (feat_size != 2048)
	{
		return 1;
	}
	//读取待测图片并大小归一化
	cv::Mat src_img = cv::imread("Dilraba1Crop.jpg",cv::IMREAD_COLOR);
	cv::imshow("Probe Face", src_img);
	cv::resize(src_img,src_img, cv::Size(face_recognizer.crop_height(),face_recognizer.crop_width()));
	//
	ImageData _src_img_data(src_img.cols, src_img.rows, src_img.channels());
	_src_img_data.data = src_img.data;
	//获取脸部特征,注意获取的特征维度必须等于模型的特征维度
	float * feats = new  float[face_recognizer.feature_size()];
	float probe_fea[2048];
	//FacialLandmark pt5[5] = { points[0],points[1],points[2],points[3],points[4] };
	face_recognizer.ExtractFeature(dst_img_data, feats);
	face_recognizer.ExtractFeature(_src_img_data, probe_fea);
	//face_recognizer.ExtractFeatureWithCrop(_src_img_data, pt5, feats);
	//计算相似度
	float sim = face_recognizer.CalcSimilarity(feats,probe_fea);
	std::cout << sim << std::endl;
	//图像比较小,不好查看,就把图像放大,太大就缩小
	cv::resize(img, img, cv::Size(img.cols * 1, img.rows * 1));
	//显示最后结果图像
	cv::namedWindow("Win7", cv::WINDOW_AUTOSIZE);
	cv::imshow("Win7", img);
	cv::waitKey(0);
	cv::destroyAllWindows();
	system("pause");
	delete[] feats;
	return 0;
}
posted @ 2017-10-08 21:49  學海無涯  阅读(3565)  评论(0编辑  收藏  举报