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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM