前面文章写了基于c#+虹软进行的人脸识别,最后获取到人脸的特征值(byte[]数组)将其保存起来(人脸识别之虹软_苜蓿草的博客-CSDN博客),接下来在登录的时候与其进行比较。
程序是基于winform实现的人脸自动检测,因此可以借助于VideoSourcePlayer的Paint方法来实现,Paint主要是控件重绘时调用。
private void VideoSourcePlayer1_Paint(object sender, PaintEventArgs e){
//逻辑实现
}
程序的内容主要包括以下功能:
- 判断摄像头状态
只有状态时running的时候才进入程序
if (videoSourcePlayer1.IsRunning&& resultShowImgRect){
}
- 获取摄像头图像
Bitmap source = videoSourcePlayer1.GetCurrentVideoFrame();
- 图像的处理,对于特别大的图像需要处理到响应范围内
/// <summary>
/// 最大宽度
/// </summary>
private int maxWidth = 1536;
/// <summary>
/// 最大高度
/// </summary>
private int maxHeight = 1536;
/// <summary>
/// 检查图片宽高
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
private void CheckBitmapWidthAndHeight(ref Bitmap bitmap)
{
if (bitmap == null)
{
return;
}
try
{
if (bitmap.Width > maxWidth || bitmap.Height > maxHeight)
{
bitmap = (Bitmap)ImageUtil.ScaleImage(bitmap, maxWidth, maxHeight);
}
}
catch { }
}
- 检测人脸并标识出来
//检测人脸,得到Rect框
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(engine.ImageEngine, bitmap);
ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo);
MRECT rect = maxFace.faceRect;
Graphics g = e.Graphics;
float offsetX = videoSourcePlayer1.Width * 1f / bitmap.Width;
float offsetY = videoSourcePlayer1.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);
- 提取特征
ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo();
image1Feature = FaceUtil.ExtractFeature(engine.ImageEngine, bitmap, out singleFaceInfo);
- 与数据库里的图像进行比较,设置阈值来进行辅助判断
int ret = ASFFunctions.ASFFaceFeatureCompare(engine.ImageEngine, image1Feature, feature, ref similarity);
if (similarity > threshold)
{
LogUtil.WriteLog("检测成功");
}
完整代码
private void VideoSourcePlayer1_Paint(object sender, PaintEventArgs e)
{
try
{
if (videoSourcePlayer1.IsRunning&& resultShowImgRect)
{
//得到当前RGB摄像头下的图片
Bitmap source = videoSourcePlayer1.GetCurrentVideoFrame();
//校验图片宽高
if (source == null)
{
return;
}
Bitmap bitmap = new Bitmap(source.Width, source.Height, source.PixelFormat);
CheckBitmapWidthAndHeight(ref bitmap);
CopyBitmap(source, bitmap);
//检测人脸,得到Rect框
ASF_MultiFaceInfo multiFaceInfo = FaceUtil.DetectFace(engine.ImageEngine, bitmap);
//得到最大人脸
ASF_SingleFaceInfo maxFace = FaceUtil.GetMaxFace(multiFaceInfo);
//得到Rect
MRECT rect = maxFace.faceRect;
//检测RGB摄像头下最大人脸
Graphics g = e.Graphics;
float offsetX = videoSourcePlayer1.Width * 1f / bitmap.Width;
float offsetY = videoSourcePlayer1.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 (!isRGBLock)
{
if (multiFaceInfo.faceNum <= 0)
{
LogUtil.WriteLog("没有人脸\r\n");
return;
}
if (multiFaceInfo.faceNum > 1)
{
LogUtil.WriteLog("检测到多个人脸\r\n");
return;
}
LogUtil.WriteLog("开始检测人脸");
//保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况
isRGBLock = true;
//异步处理提取特征值和比对,不然页面会比较卡
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
{
ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo();
image1Feature = FaceUtil.ExtractFeature(engine.ImageEngine, bitmap, out singleFaceInfo);
//获取用户
String sql = "select * from members where face_feature is not null";
DataTable dt = MySqlHelper.GetDataSet(CommandType.Text, sql, null).Tables[0];
Boolean issuccess = false;
foreach (DataRow dr in dt.Rows)
{
byte[] bs = (byte[])dr["face_feature"];
String name = dr["name"].ToString();
String memberid = dr["id"].ToString();
IntPtr feature = MemoryUtil.Malloc(MemoryUtil.SizeOf<ASF_FaceFeature>());
float similarity = 0f;
try
{
ASF_FaceFeature localFeature = new ASF_FaceFeature();
localFeature.feature = MemoryUtil.Malloc(bs.Length);
MemoryUtil.Copy(bs, 0, localFeature.feature, bs.Length);
localFeature.featureSize = bs.Length;
MemoryUtil.StructureToPtr(localFeature, feature);
int ret = ASFFunctions.ASFFaceFeatureCompare(engine.ImageEngine, image1Feature, feature, ref similarity);
//增加异常值处理
if (similarity.ToString().IndexOf("E") > -1)
similarity = 0f;
}
catch (Exception eee)
{
LogUtil.WriteErrorLog("byte转换指针", eee.Message);
}
finally
{
if (feature != null)
MemoryUtil.Free(feature);
}
if (similarity > threshold)
{
LogUtil.WriteLog("检测成功");
issuccess = true;
resultShowImgRect = false;
//保存图片
String imgPath = System.Configuration.ConfigurationManager.AppSettings["FTImg"];
if (!System.IO.Directory.Exists(imgPath)) System.IO.Directory.CreateDirectory(imgPath);
break;
}
}
if (!issuccess)
{
LogUtil.WriteLog("人脸检测失败,没有匹配的!");
Thread.Sleep(2000);
isRGBLock = false;
}
bitmap.Dispose();
}));
}
}
}
catch (Exception ex)
{
LogUtil.WriteErrorLog("检测1!", ex.Message);
}
}