前言
最近偶尔看到了虹软sdk开放了活体检测的功能,以前记得19年的时候就关注过虹软的人脸识别免费开放的消息。现在正好拿来玩玩。案例仅供参考
一、虹软是什么?
虹软是计算机视觉行业领先的算法服务提供商及解决方案供应商,服务于世界各地的客户,将领先的计算机视觉技术商业化应用在智能手机、智能汽车、智能家居、智能零售、互联网视频等领域,并且仍在不断探索新的领域与方向。
开放了人脸识别,人证核验和活体检测的sdk
二、使用步骤
1.引入库
1.使用C# 作为开发语言,选择了C++的sdk
去他们官网注册好账号后,可以选择不同的环境以及不同的sdk
2.
username 是人员名字
userfeature 是特征,特征值在虹软的2.2版本里面使用intptr存储的,3.0 则使用byte[ ]存储。3.0会比较方便。直接转换成basestring 存储即可。
userfeaturesize 是字符数量
2.读入数据
在注册人脸这,添加以下代码。
public class UserModel
{
public string username { get; set; }
public string userfeature { get; set; }
public int userfeaturesize { get; set; }
}
//创建数据库对象
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = ConnectionStringObject.ConnectionString,//连接符字串
DbType = DbType.Sqlite,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息
});
UserModel usermodel = new UserModel()
{
username = "women2",
userfeature = Convert.ToBase64String(feature.feature),
userfeaturesize = feature.featureSize
};
db.Insertable(usermodel).ExecuteCommand();
在后面,在demo的基础上添加了后台按钮。
//初始化的时候读取
public bool InitUserFaces()
{
try
{
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = ConnectionStringObject.ConnectionString,//连接符字串
DbType = DbType.Sqlite,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息
});
UserFaces = db.Queryable<UserModel>().ToList();
db.Close();
db.Dispose();
return true;
}
catch (Exception ex)
{
return false;
//throw;
}
}
public List<UserModel> UserFaces = new List<UserModel>();
try
{ 创建数据库对象
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig()
{
ConnectionString = ConnectionStringObject.ConnectionString,//连接符字串
DbType = DbType.Sqlite,
IsAutoCloseConnection = true,
InitKeyType = InitKeyType.Attribute//从特性读取主键自增信息
});
var facelist = db.Queryable<UserModel>().ToList();
//在点击开始的时候再坐下初始化检测,防止程序启动时有摄像头,在点击摄像头按钮之前将摄像头拔掉的情况
initVideo();
//必须保证有可用摄像头
if (filterInfoCollection.Count == 0)
{
MessageBox.Show("未检测到摄像头,请确保已安装摄像头或驱动!");
return;
}
if (rgbVideoSource.IsRunning || irVideoSource.IsRunning)
{
btnStartVideo.Text = "启用摄像头";
//关闭摄像头
if (irVideoSource.IsRunning)
{
irVideoSource.SignalToStop();
irVideoSource.Hide();
}
if (rgbVideoSource.IsRunning)
{
rgbVideoSource.SignalToStop();
rgbVideoSource.Hide();
}
//“选择识别图”、“开始匹配”按钮可用,阈值控件禁用
ControlsEnable(true, chooseImgBtn, matchBtn, chooseMultiImgBtn, btnClearFaceList);
txtThreshold.Enabled = false;
exitVideoRGBFR = true;
exitVideoRGBLiveness = true;
}
else
{
if (isCompare)
{
//比对结果清除
for (int i = 0; i < imagesFeatureList.Count; i++)
{
imageList.Items[i].Text = string.Format("{0}号", i);
}
lblCompareInfo.Text = string.Empty;
isCompare = false;
}
//“选择识别图”、“开始匹配”按钮禁用,阈值控件可用,显示摄像头控件
txtThreshold.Enabled = true;
rgbVideoSource.Show();
irVideoSource.Show();
ControlsEnable(false, chooseImgBtn, matchBtn, chooseMultiImgBtn, btnClearFaceList);
btnStartVideo.Text = "关闭摄像头";
//获取filterInfoCollection的总数
int maxCameraCount = filterInfoCollection.Count;
//如果配置了两个不同的摄像头索引
if (rgbCameraIndex != irCameraIndex && maxCameraCount >= 2)
{
//RGB摄像头加载
rgbDeviceVideo = new VideoCaptureDevice(filterInfoCollection[rgbCameraIndex < maxCameraCount ? rgbCameraIndex : 0].MonikerString);
rgbVideoSource.VideoSource = rgbDeviceVideo;
rgbVideoSource.Start();
//IR摄像头
irDeviceVideo = new VideoCaptureDevice(filterInfoCollection[irCameraIndex < maxCameraCount ? irCameraIndex : 0].MonikerString);
irVideoSource.VideoSource = irDeviceVideo;
irVideoSource.Start();
//双摄标志设为true
isDoubleShot = true;
}
else
{
//仅打开RGB摄像头,IR摄像头控件隐藏
rgbDeviceVideo = new VideoCaptureDevice(filterInfoCollection[rgbCameraIndex <= maxCameraCount ? rgbCameraIndex : 0].MonikerString);
rgbVideoSource.VideoSource = rgbDeviceVideo;
rgbVideoSource.Start();
irVideoSource.Hide();
}
//启动两个检测线程
exitVideoRGBFR = false;
exitVideoRGBLiveness = false;
videoRGBLiveness();
//videoRGBFR();
videoRGBFRServer();
}
}
catch (Exception ex)
{
LogUtil.LogInfo(GetType(), ex);
}
private void videoRGBFRServer()
{
int index = 10000;
ThreadPool.QueueUserWorkItem(new WaitCallback(delegate {
while (true)
{
//index--;
//if (index == 0)
//{
// index = 10000;
// existNewFace = true;
//}
if (exitVideoRGBFR)
{
return;
}
try
{
//if (ableReadFaceInfo && existNewFace && handleQueue.Contains(faceIDTemp) && !livenessResult.Equals(livenessInitValue))
if (ableReadFaceInfo && existNewFace && !livenessResult.Equals(livenessInitValue))
{
ableReadFR = false;
if (livenessResult.Equals(1) && rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0)
{
int result = -1;
float similarity = 0f;
for (int i = 0; i < frMatchTime; i++)
{
if (exitVideoRGBFR)
{
break;
}
Console.WriteLine(string.Format("faceid:{0},特征搜索第{1}次\r\n", "999", i + 1));
Bitmap bitmapTemp = rgbVideoSource.GetCurrentVideoFrame();
if (bitmapTemp == null)
{
break;
}
//提取人脸特征
FaceFeature feature = FaceUtil.ExtractFeature(videoRGBImageEngine, bitmapTemp, maxFace);
similarity = 0f;
result = compareFeatureServer(feature, out similarity);
//得到比对结果
if (result > -1)
{
break;
}
}
if (!result.Equals(-1))
{
//将比对结果放到显示消息中,用于最新显示
trackRGBUnit.message = string.Format(" {0}号 {1},{2},Faceid:{3}", result, similarity, string.Format("RGB{0}", CommonUtil.TransLivenessResult(livenessResult)), UserFaces[result].username);
}
else
{
//显示消息
trackRGBUnit.message = string.Format("RGB{0},Faceid:{1}", CommonUtil.TransLivenessResult(livenessResult), result);
}
}
else
{
//显示消息
trackRGBUnit.message = string.Format("RGB{0},Faceid:{1}", CommonUtil.TransLivenessResult(livenessResult), "999");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
ableReadFR = true;
}
}
}));
}
/// <summary>
/// 得到feature比较结果
/// </summary>
/// <param name="feature"></param>
/// <returns></returns>
private int compareFeatureServer(FaceFeature feature, out float similarity)
{
int result = -1;
similarity = 0f;
try
{
//如果人脸库不为空,则进行人脸匹配
if (UserFaces != null && UserFaces.Count > 0)
{
for (int i = 0; i < UserFaces.Count; i++)
{
//调用人脸匹配方法,进行匹配
videoRGBImageEngine.ASFFaceFeatureCompare(feature,new FaceFeature() {feature = Convert.FromBase64String( UserFaces[i].userfeature),featureSize = UserFaces[i].userfeaturesize } , out similarity);
if (similarity >= threshold)
{
result = i;
break;
}
}
}
}
catch (Exception ex)
{
LogUtil.LogInfo(GetType(), ex);
}
return result;
}
ok 程序到这里就修改完成了。每次程序启动之后,会从bin文件夹下面的.db文件里面读取出所有的人脸。然后每次通过摄像头去匹配。 已测试,效果挺好,识别的很快。就是还有一些小问题。但是总体来说效果很好。
总结
gitee,代码地址:人脸识别
更新架构
这是官方的样例demo介绍,本文也是几乎差不多的原理,目前实现了小型智慧工地的人脸识别系统的设计。
以后有机会的话会更新成下图右边的c/s系统设计
更新数据库(增加图片存储)
总共两张表