C# 人脸识别- (人脸考勤)
哈喽!大家晚上好!
这是我在博客的第一篇文章,主要功能是人脸识别(上位机方向,可接单片机做下属控制,图像处理使用的是OpenCV, 其核心算法是虹软3.0 开源 人脸识别算法,下面就为大家介绍准备工作
1.虹软官网申请应用
这个是申请的算法:拿到SDK_KEY 和 APP_ID 下载对应的SDK 如下:
将这三个文件放在项目Debug 根目录下 里面包含dome 没有图像处理基础比较难理解 多花点时间啃下来
1.配置appid ,sdkkey
// 初始化引擎 也就是 SDK的密钥 需要使用对于的Key开锁使用其功能
///
/// 初始化引擎
///
private void InitEngines()
{
//读取配置文件
AppSettingsReader reader = new AppSettingsReader();
string appId = "AURkzRw3k6YQyMexHr8XhEuS3cfEtXC5biYY9TXLLrTb";
string sdkKey64 = "9MqSe2Mf9SrTArYdy5uGZPCTPsDPmJgKyHfKcxTK1Yqx";
string sdkKey32 = "9MqSe2Mf9SrTArYdy5uGZPCTLcz9NuidSSbJY31GcqF7";
rgbCameraIndex = 0; //(int)reader.GetValue("RGB_CAMERA_INDEX", typeof(int));
irCameraIndex = 0; //(int)reader.GetValue("IR_CAMERA_INDEX", typeof(int));
//判断CPU位数
var is64CPU = false;//Environment.Is64BitProcess;
if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(is64CPU ? sdkKey64 : sdkKey32))
{
//禁用相关功能按钮
ControlsEnable(false, chooseMultiImgBtn, matchBtn, btnClearFaceList, chooseImgBtn);
MessageBox.Show(string.Format("请在App.config配置文件中先配置APP_ID和SDKKEY{0}!", is64CPU ? "64" : "32"));
return;
}
//在线激活引擎 如出现错误,1.请先确认从官网下载的sdk库已放到对应的bin中,2.当前选择的CPU为x86或者x64
int retCode = 0;
try
{
retCode = ASFFunctions.ASFActivation(appId, is64CPU ? sdkKey64 : sdkKey32);
}
catch (Exception ex)
{
//禁用相关功能按钮
ControlsEnable(false, chooseMultiImgBtn, matchBtn, btnClearFaceList, chooseImgBtn);
if (ex.Message.Contains("无法加载 DLL"))
{
MessageBox.Show("请将sdk相关DLL放入bin对应的x86或x64下的文件夹中!");
}
else
{
MessageBox.Show("激活引擎失败!");
}
return;
}
Console.WriteLine("Activate Result:" + retCode);
//初始化引擎
uint detectMode = DetectionMode.ASF_DETECT_MODE_IMAGE;
//Video模式下检测脸部的角度优先值
int videoDetectFaceOrientPriority = ASF_OrientPriority.ASF_OP_0_HIGHER_EXT;
//Image模式下检测脸部的角度优先值
int imageDetectFaceOrientPriority = ASF_OrientPriority.ASF_OP_0_ONLY;
//人脸在图片中所占比例,如果需要调整检测人脸尺寸请修改此值,有效数值为2-32
int detectFaceScaleVal = 16;
//最大需要检测的人脸个数
int detectFaceMaxNum = 5;
//引擎初始化时需要初始化的检测功能组合
int combinedMask = FaceEngineMask.ASF_FACE_DETECT | FaceEngineMask.ASF_FACERECOGNITION | FaceEngineMask.ASF_AGE | FaceEngineMask.ASF_GENDER | FaceEngineMask.ASF_FACE3DANGLE;
//初始化引擎,正常值为0,其他返回值请参考http://ai.arcsoft.com.cn/bbs/forum.php?mod=viewthread&tid=19&_dsign=dbad527e
retCode = ASFFunctions.ASFInitEngine(detectMode, imageDetectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, ref pImageEngine);
Console.WriteLine("InitEngine Result:" + retCode);
AppendText((retCode == 0) ? "引擎初始化成功!\n" : string.Format("引擎初始化失败!错误码为:{0}\n", retCode));
if (retCode != 0)
{
//禁用相关功能按钮
ControlsEnable(false, chooseMultiImgBtn, matchBtn, btnClearFaceList, chooseImgBtn);
}
//初始化视频模式下人脸检测引擎
uint detectModeVideo = DetectionMode.ASF_DETECT_MODE_VIDEO;
int combinedMaskVideo = FaceEngineMask.ASF_FACE_DETECT | FaceEngineMask.ASF_FACERECOGNITION;
retCode = ASFFunctions.ASFInitEngine(detectModeVideo, videoDetectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMaskVideo, ref pVideoEngine);
//RGB视频专用FR引擎
detectFaceMaxNum = 1;
combinedMask = FaceEngineMask.ASF_FACE_DETECT | FaceEngineMask.ASF_FACERECOGNITION | FaceEngineMask.ASF_LIVENESS;
retCode = ASFFunctions.ASFInitEngine(detectMode, imageDetectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, ref pVideoRGBImageEngine);
//IR视频专用FR引擎
combinedMask = FaceEngineMask.ASF_FACE_DETECT | FaceEngineMask.ASF_FACERECOGNITION | FaceEngineMask.ASF_IR_LIVENESS;
retCode = ASFFunctions.ASFInitEngine(detectMode, imageDetectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, ref pVideoIRImageEngine);
Console.WriteLine("InitVideoEngine Result:" + retCode);
initVideo();
}
摄像头初始化
///
/// 摄像头初始化
///
private void initVideo()
{
filterInfoCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
//如果没有可用摄像头,“启用摄像头”按钮禁用,否则使可用
if (filterInfoCollection.Count == 0)
{
btnStartVideo.Enabled = false;
}
else
{
btnStartVideo.Enabled = true;
}
}
///
/// 人脸库图片选择按钮事件
///
private void ChooseMultiImg1()
{
lock (locker)
{
strImageFile = m_ComIni.IniReadValue("ImageFile", "File");
//List imagePathListTemp = new List();
Dictionary imagePathListTemp = new Dictionary();
var numStart = imagePathList.Count;
int isGoodImage = 0;
//保存图片路径并显示
// string[] fileNames = Director(@"E:\曹镇代码备份\自助登记\8.0\自助机\D8FK01S\bin\Debug\IDCard\Capture").ToArray();//openFileDialog.FileNames;
string[] fileNames = Director(strImageFile).ToArray();
for (int i = 0; i < fileNames.Length; i++)
{
//图片格式判断
if (checkImage(fileNames[i]))
{
string imagename = fileNames[i].Split('\\')[fileNames[i].Split('\\').Length - 1];
imagePathListTemp.Add(imagename, fileNames[i]);
}
}
int a = 1;
//人脸检测以及提取人脸特征
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
Invoke(new Action(delegate
{
chooseMultiImgBtn.Enabled = false;
matchBtn.Enabled = false;
btnClearFaceList.Enabled = false;
chooseImgBtn.Enabled = false;
btnStartVideo.Enabled = false;
}));
foreach (var item in imagePathListTemp)
{
Image image = ImageUtil.readFromFile(item.Value);
if (image == null)
{
continue;
}
if (image.Width > 1536 || image.Height > 1536)
{
image = ImageUtil.ScaleImage(image, 1536, 1536);
}
if (image == null)
{
continue;
}
if (image.Width % 4 != 0)
{
image = ImageUtil.ScaleImage(image, image.Width - (image.Width % 4), image.Height);
}
//人脸检测
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pImageEngine, image);
//判断检测结果
if (multiFaceInfo.faceNum > 0)
{
imagePathList.Add(item.Value);
MRECT rect = MemoryUtil.PtrToStructure(multiFaceInfo.faceRects);
image = ImageUtil.CutImage(image, rect.left, rect.top, rect.right, rect.bottom);
}
else
{
if (image != null)
{
image.Dispose();
}
continue;
}
//显示人脸
this.Invoke(new Action(delegate
{
if (image == null)
{
image = ImageUtil.readFromFile(item.Value);
if (image.Width > 1536 || image.Height > 1536)
{
image = ImageUtil.ScaleImage(image, 1536, 1536);
}
}
isGoodImage += 1;
if (image != null)
{
image.Dispose();
}
}));
}
//提取人脸特征
for (int i = numStart; i < imagePathList.Count; i++)
{
ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo();
Image image = ImageUtil.readFromFile(imagePathList[i]);
if (image == null)
{
continue;
}
IntPtr feature = FaceUtil.ExtractFeature(pImageEngine, image, out singleFaceInfo);
this.Invoke(new Action(delegate
{
if (singleFaceInfo.faceRect.left == 0 && singleFaceInfo.faceRect.right == 0)
{
AppendText(string.Format("{0}号未检测到人脸\r\n", i));
}
else
{
AppendText(string.Format("已提取{0}张人脸特征值,[left:{1},right:{2},top:{3},bottom:{4},orient:{5}]\r\n", i, singleFaceInfo.faceRect.left, singleFaceInfo.faceRect.right, singleFaceInfo.faceRect.top, singleFaceInfo.faceRect.bottom, singleFaceInfo.faceOrient));
string imagename = fileNames[i].Split('\\')[fileNames[i].Split('\\').Length - 1];
imagesFeatureList.Add(imagename, feature);
m_ComIniFace.IniWriteValue(M_Section, imagename, imagename + "|" + GetIntPtrInt(feature).ToString());
}
}));
if (image != null)
{
image.Dispose();
}
}
Invoke(new Action(delegate
{
m_ImageCount = imagePathListTemp.Count;
AppendText(string.Format("{0}条人脸特征提取完成", imagePathList.Count));
IsMainStartFace = true;
}));
}));
}
}
///
/// RGB摄像头Paint事件,图像显示到窗体上,得到每一帧图像,并进行处理
///
///
///
private void videoSource_Paint(object sender, PaintEventArgs e)
{
if (rgbVideoSource.IsRunning)
{
//得到当前RGB摄像头下的图片
Bitmap bitmap = rgbVideoSource.GetCurrentVideoFrame();
if (bitmap == null)
{
return;
}
//检测人脸,得到Rect框
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(pVideoEngine, bitmap);
//得到最大人脸
ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo);
//得到Rect
MRECT rect = maxFace.faceRect;
//检测RGB摄像头下最大人脸
Graphics g = e.Graphics;
float offsetX = rgbVideoSource.Width * 1f / bitmap.Width;
float offsetY = rgbVideoSource.Height * 1f / bitmap.Height;
float x = rect.left * offsetX;
float width = rect.right * offsetX - x;
float y = rect.top * offsetY;
float height = rect.bottom * offsetY - y;
//根据Rect进行画框
g.DrawRectangle(Pens.Red, x, y, width, height);
if (trackRGBUnit.message != "" && x > 0 && y > 0)
{
//将上一帧检测结果显示到页面上
g.DrawString(trackRGBUnit.message, font, trackRGBUnit.message.Contains("活体") ? blueBrush : yellowBrush, x, y - 15);
}
//保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况
if (isRGBLock == false)
{
isRGBLock = true;
//异步处理提取特征值和比对,不然页面会比较卡
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0)
{
try
{
lock (rectLock)
{
allRect.left = (int)(rect.left * offsetX);
allRect.top = (int)(rect.top * offsetY);
allRect.right = (int)(rect.right * offsetX);
allRect.bottom = (int)(rect.bottom * offsetY);
}
bool isLiveness = false;
//调整图片数据,非常重要
ImageInfo imageInfo = ImageUtil.ReadBMP(bitmap);
if (imageInfo == null)
{
return;
}
int retCode_Liveness = -1;
//RGB活体检测
ASF_LivenessInfo liveInfo = FaceUtil.LivenessInfo_RGB(pVideoRGBImageEngine, imageInfo, multiFaceInfo, out retCode_Liveness);
//判断检测结果
if (retCode_Liveness == 0 && liveInfo.num > 0)
{
int isLive = MemoryUtil.PtrToStructure(liveInfo.isLive);
isLiveness = (isLive == 1) ? true : false;
}
if (imageInfo != null)
{
MemoryUtil.Free(imageInfo.imgData);
}
if (isLiveness)
{
//提取人脸特征
IntPtr feature = FaceUtil.ExtractFeature(pVideoRGBImageEngine, bitmap, maxFace);
float similarity = 0f;
//得到比对结果
int result = compareFeature(feature, out similarity);
MemoryUtil.Free(feature);
if (result > -1)
{
//将比对结果放到显示消息中,用于最新显示
trackRGBUnit.message = string.Format(" {0}号 {1},{2}", result, similarity, string.Format("RGB{0}", isLiveness ? "活体" : "假体"));
}
else
{
//显示消息
trackRGBUnit.message = string.Format("RGB{0}", isLiveness ? "活体" : "假体");
}
}
else
{
//显示消息
trackRGBUnit.message = string.Format("RGB{0}", isLiveness ? "活体" : "假体");
}
SetUpdate();
if (isLiveness)
{
matchBtn1();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (bitmap != null)
{
bitmap.Dispose();
}
isRGBLock = false;
}
}
else
{
lock (rectLock)
{
allRect.left = 0;
allRect.top = 0;
allRect.right = 0;
allRect.bottom = 0;
SetElecd(false);
}
}
isRGBLock = false;
}));
}
}
}
///
/// 匹配事件
///
///
///
[HandleProcessCorruptedStateExceptions]
private void matchBtn1()
{
try
{
List strFace = ReadFaceIni();
// if (imagesFeatureList.Count == 0)
if (strFace.Count == 0)
//if(ImagearrayList.Count==0)
{
AppendText("请注册人脸!");
Util_SpeakName("没有获取到人脸库信息");
//MessageBox.Show("请注册人脸!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
ChooseImg1(rgbVideoSource.GetCurrentVideoFrame());
if (image1Feature == IntPtr.Zero)
{
if (rgbVideoSource.GetCurrentVideoFrame() == null)
{
AppendText("未识别到人脸!");
Util_SpeakName("未识别到人脸");
//MessageBox.Show("请选择识别图!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
AppendText("验证失败,未识别图未提取到特征值!");
Util_SpeakName("验证失败未识别图未提取到特征值");
// MessageBox.Show("比对失败,识别图未提取到特征值!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return;
}
//标记已经做了匹配比对,在开启视频的时候要清除比对结果
isCompare = true;
float compareSimilarity = 0f;
int compareNum = 0;
//AppendText(string.Format("------------------------------开始比对,时间:{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
//for (int i = 0; i < imagesFeatureList.Count; i++)
//{
// IntPtr feature = imagesFeatureList[i];
// float similarity = 0f;
// int ret = ASFFunctions.ASFFaceFeatureCompare(pImageEngine, image1Feature, feature, ref similarity);
// //增加异常值处理
// if (similarity.ToString().IndexOf("E") > -1)
// {
// similarity = 0f;
// }
// AppendText(string.Format("与{0}号比对结果:{1}\r\n", i, similarity));
// // imageList.Items[i].Text = string.Format("{0}号({1})", i, similarity);
// if (similarity > compareSimilarity)
// {
// compareSimilarity = similarity;
// compareNum = i;
// }
//}
int i = 0;
Dictionary dicFace = new Dictionary();
for (int FaceCount = strFace.Count; FaceCount >= 1; FaceCount--)
// foreach (var item in imagesFeatureList)
// foreach(MianImage item in ImagearrayList)
{
// IntPtr feature = item.ImageInPtr;
string strFaceData = m_ComIniFace.IniReadValue(M_Section, strFace[FaceCount - 1]);
string[] FaceMain = strFaceData.Split('|');
IntPtr feature = GetIntPtr(Convert.ToInt32(FaceMain[1])); //item.Value;
float similarity = 0f;
int ret = 0;
try
{
ret = ASFFunctions.ASFFaceFeatureCompare(pImageEngine, image1Feature, feature, ref similarity);
}
catch (Exception ex)
{
}
finally
{
GC.Collect();
}
//增加异常值处理
if (similarity.ToString().IndexOf("E") > -1)
{
similarity = 0f;
}
//AppendText(string.Format("与{0}比对结果:{1}\r\n", item.Key, similarity));
// imageList.Items[i].Text = string.Format("{0}号({1})", i, similarity);
if (similarity > compareSimilarity)
{
compareSimilarity = similarity;
string strGuid = FaceMain[0].Split(')')[0].Replace("(", "").Trim();
dicFace.Add(strGuid + "|" + FaceMain[0], similarity);
compareNum = i;
}
i++;
}
if (compareSimilarity > 0.9f)
{
foreach (var item in dicFace)
{
if (item.Value.Equals(compareSimilarity))
{
string strrun = "";
string strGUID = item.Key.Split('|')[0];
string IamgeFile = item.Key.Split('|')[1];
string strsql = string.Format("select * from UserTable where UserID='{0}'", strGUID);
DataSet _ds = null;
if (AppSettings.GetIsSqlLite())
{
_ds = new DataSet();
_ds.Tables.Add(manager.GetData(strGUID));
}
else
{
_ds = db.Execute(strsql, "UserTable", ref strrun);
}
if (_ds != null && _ds.Tables != null && _ds.Tables[0].DefaultView.Count > 0)
{
this.Invoke(new MethodInvoker(delegate ()
{
AppendText("验证成功!");
Util_SpeakName(string.Format("验证成功{0}欢迎回来", _ds.Tables[0].DefaultView[0]["UserName"].ToString()));
SetElecd(true);
lab_Name.Text = _ds.Tables[0].DefaultView[0]["UserName"].ToString();
lab_Age.Text = _ds.Tables[0].DefaultView[0]["UserAge"].ToString();
Lab_Dpt.Text = _ds.Tables[0].DefaultView[0]["UserDpt"].ToString();
panImage.BackgroundImage = Image.FromFile(string.Format("{0}\\{1}", strImageFile, IamgeFile));
SetUpdate();
}));
}
//lblCompareInfo.Text = " " + item.Key + "号," + compareSimilarity;
}
}
}
//AppendText(string.Format("------------------------------比对结束,时间:{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
}
catch (Exception ex)
{
}
}