如何使用 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;
}