如何使用 SeetaFaceEngine 人脸检测库实现人脸三部曲?
如何使用 SeetaFaceEngine 人脸检测库实现人脸三部曲?
- 人脸检测
FaceDetection
- 人脸校准
FaceAlignment
- 人脸识别
FaceIdentification
前期准备
- SeetaFaceEngine 编译 Win32 动态库
- 编译 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;
}
转载请注明出处并保持作品的完整性,谢谢