基于SphereFace深度学习的人脸考勤系统(Caffe+windows+OpenCV)

界面展示

在这里插入图片描述
这是主界面。打开摄像头,能进行人脸捕捉并显示在屏幕上,自动连接数据库,显示出对应人脸的信息,并进行上下班打卡。

相关开发工具

数据库:Microsoft SQL Server Management Studio 17
OpenCV:OpenCV-2.4.13
人脸检测库:Libfacedetection

它是由作者ShiqiYu发布在Github上的遵循MIT开源协议的公共库,是一个用于图像中人脸检测和人脸标识检测的二进制库。github地址:https://github.com/ShiqiYu/libfacedetection

人脸识别模型:SphereFace-20

关于SphereFace网络模型的理论基础,可参考下面链接
https://blog.csdn.net/qianqing13579/article/details/78288780

深度学习框架:Caffe

搭建Windows版本的Caffe 无论是CPU还是GPU环境的,都可参考下面链接
https://blog.csdn.net/kaychangeek/article/details/79885494

编译环境:VS2013

VS2013配置OpenCV https://blog.csdn.net/bryant_meng/article/details/79863921

关键代码、函数功能说明

1. 【关于编写CaffeVggface.dll 动态库】

caffe自带的classification比较复杂,希望在自己的项目中进行测试,减去不需要的代码。下面给出改写的代码。
改写Caffe自带的classification.cpp编写CaffePredefine函数(即原本Classifierl的构造函数)

void CaffeClassification::CaffePredefine(std::string param_file, std::string pretrained_param_file, std::string labels_file,int classfymode)
{//param_file表示配置文件prototxt,pretrained_param_file表示训练好的模型文件
//labels_file标签文件,classfymode用0代表gqu训练,1代表CPU训练
#ifdef ZQ_CPU_ONLY  
	Caffe::set_mode(Caffe::CPU);//如果caffe是只在cpu上运行的,将运行模式设置为CPU  
#else  
	Caffe::set_mode(Caffe::GPU);//一般我们都是用的GPU模式  
#endif 
	net.reset(new caffe::Net<float>(param_file, caffe::TEST));//加载配置文件,设定模式为TEST测试
	printf(pretrained_param_file.c_str());
	net->CopyTrainedLayersFrom(pretrained_param_file);//加载caffemodel,该函数在net.cpp中实现	
	memory_layer = (caffe::MemoryDataLayer<float> *)net->layers()[0].get();

	if (1 == classfymode)
	{
		Blob<float>* input_layer = net->input_blobs()[0]; // 定义输入层变量
		input_geometry = Size(input_layer->width(), input_layer->height());//得到输入层图像大小
	}
	Blob<float>* output_layer = net->output_blobs()[0];
	if (labels_file.size() > 1)
	{
		std::ifstream labelsfile(labels_file.c_str());
		string line;
		while (std::getline(labelsfile, line))
			labels.push_back(string(line));
	}
}

ExtractFeature函数,功能是获取网路模型中提取的特征值

int CaffeClassification::ExtractFeature(Mat img, vector<float> &rsvt, int rsnum,const std::string& blobname)
{ //img网络训练的输入图片,rsvt存储图片在网络中被提取出的特征值
  //rsnum要提取的特征值数目,blobname向网络中的哪个层获取特征值
	std::vector<Mat> test = { img };
	std::vector<int> testLabel = { 0 };//图片标签
	memory_layer->AddMatVector(test, testLabel);// memory_layer and net , must be define be a global variable.
	//test.clear(); testLabel.clear();
	std::vector<caffe::Blob<float>*> input_vec;
	input_vec.clear();
	net->Forward(input_vec);//前向传导
	boost::shared_ptr<caffe::Blob<float>> fcblob = net->blob_by_name(blobname);  //InnerProduct 输出
	rsvt.clear();

	int featurenum = 0;
	//vector<float> tmpvc;
	while (featurenum < rsnum)
	{
		rsvt.push_back(fcblob->data_at(0, featurenum++, 1, 1));
	}

	return 1;
}

CaffeVggFace.cpp为动态库,定义CaffeClassification对象,调用相关接口函数。
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。引入extern "C"的目的是,实现C++与C及其它语言的混合编程。

CaffeClassification CaffeOBJ;

extern "C" __declspec(dllexport) int InitDLL(char *prototxtname, char* caffemodelname,char* labelname,int classfymode)
{
	CaffeOBJ.CaffePredefine(prototxtname, caffemodelname, labelname,classfymode);
	return 1;
}

extern "C" __declspec(dllexport) int FacedataToFeaturedata(unsigned char *pimgdata,int wid,int hi,double *pfeaturedata,int featurenum)
{
	Mat srcmat(hi, wid, CV_8UC3);
	memcpy(srcmat.data, pimgdata, wid*hi * 3);

	vector<float> rsvt;
	//rsvt.clear();
	CaffeOBJ.ExtractFeature(srcmat, rsvt, featurenum, "fc5");
	for (int i = 0; i < featurenum; ++i)
	{
		pfeaturedata[i] = rsvt[i];
	}

	return 1;
}
2. 【人脸识别系统实现】

FaceDetect.cpp //人脸规范化处理。利用libfacedetect接口(facedetect_multiview_reinforce函数),从图片中检测人脸,对人脸区域的大小进行调整并保存。效果如下:

伪代码

CNNFaceFeatureExtract.cpp //调用前面写好的动态库CaffeVggface.dll,传入配置文件prototxt、训练好的模型,进行特征提取。

extern "C" __declspec(dllexport) int InitDLL(char *prototxtname, char* caffemodelname, char* labelname, int classfymode);
extern "C" __declspec(dllexport) int FacedataToFeaturedata(unsigned char *pimgdata, int wid, int hi, double *pfeaturedata, int featurenum);

CNNFaceFeatureExtract::CNNFaceFeatureExtract()
{
	InitDLL("sphereface_deploy.prototxt", "sphereface.caffemodel", "", 0);
}

CNNFaceFeatureExtract::~CNNFaceFeatureExtract()
{    }
int CNNFaceFeatureExtract::FaceFeatureExtract(unsigned char *pimgdata, int wid, int hi, double *pfeaturedata, int featurenum)
{
	FacedataToFeaturedata(pimgdata, wid, hi, pfeaturedata, featurenum);
	return 1;
}

ADOConn.cpp //实现SQLServer数据库的基本操作(使用了ADODB类库,可实现对任意数据库的存取和访问)
REGISTER.cpp //员工信息注册(包括人脸注册)一共有5个数据内容(id、name、department、image、feature)
void CREGISTER::Register(CString m_filename, int id, CString name, CString depart) //连接SQL数据库,读取照片(通过摄像头拍摄),将图片转化为二进制存储在数据库中,如:

_StreamPtr  pStm;
pStm.CreateInstance("ADODB.Stream");
variant_t   varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
pStm->PutType(adTypeBinary);
pStm->Open(varOptional, adModeUnknown, adOpenStreamUnspecified, _bstr_t(), _bstr_t());
//获取图像并转化为二进制
CString strr;
strr.Format("%s", m_filename);
pStm->LoadFromFile(_bstr_t(strr));//读入文件 
variant_t  varBLOB = pStm->Read(adReadAll);

pRst->GetFields()->GetItem("image")->AppendChunk(varBLOB);   // 图片写入

类似的,将检测出的人脸传入训练好的模型中,提取特征值,转化为二进制存入数据库(因为特征值有512个,统一转化为一个二进制存储,更方便)
FaceContrast2Dlg.cpp //实现界面上所有响应函数

  • OnBnClickedButton4() //摄像获取图像,从摄像头读入图片,保存在本地
  • Check(CString file) //(重点) 传入之前保存图片的路径,调用FaceDetectObj.FaceDetectNormal进行人脸检测并规范化,再调用FeatureExtractObj.FaceFeatureExtract,提取网络模型中的人脸特征值(根据模型设计,输出了512个特征点),连接数据库,查找对应id的人脸特征值,通过余弦距离计算,比对人脸相似度,若>=阈值,则人脸匹配成功,可进行有员工权限的一切系统操作。
  • OnBnClickedButton3() //上班打卡,逻辑:先判断数据库中是否已经有今天的打卡记录,若没有,则获取当地时间,比对系统设置的上班时间,判断是否迟到,迟到了多久,并记录到数据库中。
  • OnBnClickedButton5()//下班打卡
  • OnBnClickedButton6() //查看个人基本信息
  • OnBnClickedButton7()//查看个人近期打卡日志
  • 数据库中建了四张表(“people”“login_table”“off_table”“administer”)

INFO.cpp //查看个人基本信息的功能实现,关键代码:从数据库中把二进制的人脸图片转化为bmp位图,例如:
在这里插入图片描述
————————————————————————————————————————————
补充Caffe模型训练的几点内容:

  • 首先准备训练的图像数据。下载 CASIA-WebFace人脸训练集,里面包括了10575个人的494414张照片,按照7:3的比例把人脸图像分成训练数据和测试数据,并对该人脸图像进行人脸检测和人脸归一化、标准化处理。效果如下
    在这里插入图片描述
  • 所有图像数据预处理完成后,生成训练和测试文件中所有图像对应的文本清单。利用Caffe的create_imagenet程序直接生成可训练的文件格式lmdb。在输入层data层修改source参数即训练文件的路径,调整Solver文件,修改其中stepvalue值,开始重新训练SphereFace网络模型。
  • 准备一组测试验证数据即LFW人脸数据库。

传送门:
CASIA-WebFace数据集下载 密码:abkq
LFW数据下载 密码:g2oj

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值