请允许我大言不惭,叫做教程,特希望各位能指正。哦,我用的是vs2017。了解更多详情可以访问虹软人工智能开放平台

一、准备工作

1.创建项目

2.添加EMGU.CV包

,并设属性“复制到输出目录”为“如果较新则复制”

3.添加程序集System.ServiceModel的引用(Emgu视频捕捉需要)

准备工作到此结束,按F7切换到代码,然后进入第二步。

二、代码

using Emgu.CV;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; namespace ArcFace2Demo
{
public partial class Form1 : Form
{
#region ArcFaceConst
const uint ASF_DETECT_MODE_VIDEO = 0x00000000; //Video模式,一般用于多帧连续检测
const uint ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF; //Image模式,一般用于静态图的单次检测 const uint ASF_NONE = 0x00000000;
const uint ASF_FACE_DETECT = 0x00000001; //此处detect可以是tracking或者detection两个引擎之一,具体的选择由detect mode 确定
const uint ASF_FACERECOGNITION = 0x00000004;
const uint ASF_AGE = 0x00000008;
const uint ASF_GENDER = 0x00000010;
const uint ASF_FACE3DANGLE = 0x00000020; /// <summary>
/// 结构ASF_FaceRect的长度
/// 32位程序是16,64位程序需要改为32
/// </summary>
const int SizeOfASF_FaceRect = ; #endregion #region ArceDataStructure
/// <summary>
/// 人脸在图片中的位置
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ASF_FaceRect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public Rectangle GetRectangle()
{
return new Rectangle(Left, Top, Right - Left, Bottom - Top);
}
}
/// <summary>
/// 多人脸信息
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ASF_MultiFaceInfo
{ public IntPtr PFaceRect;
public IntPtr PFaceOrient;
[MarshalAs(UnmanagedType.I4)]
public int FaceNum;
} /// <summary>
/// 单人脸信息
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ASF_SingleFaceInfo
{
public ASF_FaceRect FaceRect;
public int FaceOrient; } /// <summary>
/// 人脸特征
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct ASF_FaceFeature
{
public IntPtr PFeature;
[MarshalAs(UnmanagedType.I4)]
public int FeatureSize;
} #endregion #region ArcWrapper /// <summary>
/// 激活SDK
/// </summary>
/// <param name="appId"></param>
/// <param name="sdkKey"></param>
/// <returns>0:激活成功,0x16002表示已经激活</returns>
[DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFActivation", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int ASFActivation(string appId, string sdkKey); /// <summary>
/// 初始化引擎
/// </summary>
/// <param name="detectMode">long会返回scale错误0x16004</param>
/// <param name="orientPriority"></param>
/// <param name="scale"></param>
/// <param name="maxFaceNumber"></param>
/// <param name="combinedMask"></param>
/// <param name="pEngine"></param>
/// <returns></returns>
[DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFInitEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int ASFInitEngine(uint detectMode, int orientPriority, int scale, int maxFaceNumber, uint combinedMask, out IntPtr pEngine);
/// <summary>
/// 人脸检测
/// </summary>
/// <param name="pEngine"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="format"></param>
/// <param name="pImageData"></param>
/// <param name="faceInfo"></param>
/// <returns></returns>
[DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFDetectFaces", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int ASFDetectFaces(IntPtr pEngine, int width, int height, int format, IntPtr pImageData, out ASF_MultiFaceInfo faceInfo); /// <summary>
/// 单人脸特征提取
/// </summary>
/// <param name="pEngine"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="format"></param>
/// <param name="faceInfo"></param>
/// <param name="faceFeature"></param>
/// <returns></returns>
[DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFFaceFeatureExtract", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int ASFFaceFeatureExtract(IntPtr pEngine, int width, int height, int format, IntPtr pImageData, ref ASF_SingleFaceInfo faceInfo, out ASF_FaceFeature faceFeature);
/// <summary>
/// 脸特征比对
/// </summary>
/// <param name="pEngine"></param>
/// <param name="faceFeature1"></param>
/// <param name="faceFeature2"></param>
/// <param name="result"></param>
/// <returns></returns>
[DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFFaceFeatureCompare", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int ASFFaceFeatureCompare(IntPtr pEngine, ref ASF_FaceFeature faceFeature1, ref ASF_FaceFeature faceFeature2, out float result);
/// <summary>
/// 销毁引擎
/// </summary>
/// <param name="engine"></param>
/// <returns></returns>
[DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFUninitEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern int ASFUninitEngine(IntPtr engine);
#endregion /// <summary>
/// 特征库
/// </summary>
IntPtr _PFeatureLib;
/// <summary>
/// 特征库人脸数量
/// </summary>
int _FeatureLibFaceCount = ;
/// <summary>
/// 特征库人脸ID列表
/// </summary>
List<string> _FeatureLibIDList = new List<string>(); /// <summary>
/// 人脸特征结构
/// </summary>
ASF_FaceFeature _FaceFeature = new ASF_FaceFeature { FeatureSize = }; /// <summary>
/// 人脸识别的结果
/// </summary>
class FaceResult
{
/// <summary>
/// 人脸框矩形
/// </summary>
public Rectangle Rectangle { get; set; }
/// <summary>
/// 人脸ID
/// </summary>
public string ID { get; set; }
/// <summary>
/// 比对结果
/// </summary>
public float Score { get; set; } public override string ToString()
{
return [ DISCUZ_CODE_0 ]quot;ID:{ID}\r\n结果:{Score}";
}
}
/// <summary>
/// 多人脸识别结果集
/// </summary>
ConcurrentDictionary<int, FaceResult> _FaceResults = new ConcurrentDictionary<int, FaceResult>();
/// <summary>
/// 检测到的人脸数量
/// </summary>
int _DetectedFaceCount = ; /// <summary>
/// 视频捕获
/// </summary>
VideoCapture _VideoCapture;
Mat _Frame = new Mat(); /// <summary>
/// 虹软人脸引擎
/// </summary>
IntPtr _PEngine = IntPtr.Zero; /// <summary>
/// 比对一次总耗时
/// </summary>
long _TotalElapsedMilliseconds = ;
/// <summary>
/// 识别任务
/// </summary>
Task _TaskMatch;
/// <summary>
/// 向识别任务发送取消指令的东东
/// </summary>
CancellationTokenSource _CTS = new CancellationTokenSource(); /// <summary>
/// 图像数据
/// </summary>
IntPtr _PImageData;
/// <summary>
/// 宽、高、图像数据长度
/// </summary>
int _ImageWidth, _ImageHeight, _ImageSize;
/// <summary>
/// 是否要保存当前人脸特征
/// </summary>
bool _SaveFlag = false; PictureBox _PictureBox; public Form1()
{
InitializeComponent(); _PictureBox = new PictureBox();
_PictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
_PictureBox.Dock = DockStyle.Fill;
this.Controls.Add(_PictureBox); this.Load += Form1_Load;
this.FormClosing += Form1_FormClosing;
} private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (_TaskMatch != null)
{
_CTS.Cancel();
while (_TaskMatch.Status == TaskStatus.Running)
Task.Delay().Wait();
}
_VideoCapture.Stop(); if (_PEngine != IntPtr.Zero)
ASFUninitEngine(_PEngine); if (_PFeatureLib != IntPtr.Zero)
Marshal.FreeCoTaskMem(_PFeatureLib); if (_PImageData != IntPtr.Zero)
Marshal.FreeCoTaskMem(_PImageData);
} private unsafe void Form1_Load(object sender, EventArgs e)
{
var ret = ASFActivation("BKgqTWQPQQbomfqvyd2VJzTUqPp3JD8zjAzDcqsL1jLa", "2nkDTmnkpS53cpSY42fFS9nEUzg8x4MDGkAubSsebtm1");
if (ret != && ret != 0x16002)
{
MessageBox.Show("SDK激活失败:0x" + ret.ToString("x2"));
return;
}
ret = ASFInitEngine(ASF_DETECT_MODE_IMAGE, , , , ASF_FACE_DETECT | ASF_FACERECOGNITION, out _PEngine);
if (ret != )
{
MessageBox.Show([ DISCUZ_CODE_0 ]quot;人脸识别引擎初始化失败:" + ret.ToString("x2"));
return;
}
//初始化识别结果集
for (int i = ; i < ; i++)
_FaceResults[i] = new FaceResult();
//初始化特征库
_PFeatureLib = Marshal.AllocCoTaskMem( * + * * );
var bytes = File.ReadAllBytes("Feature.dat");
var ids = File.ReadAllLines("Id.txt");
for (int i = ; i < * ; i++)
{
Marshal.Copy(bytes, , IntPtr.Add(_PFeatureLib, _FeatureLibFaceCount * ), bytes.Length);
_FeatureLibIDList.AddRange(ids);
_FeatureLibFaceCount += ids.Length;
} _VideoCapture = new VideoCapture(); //_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1024);
//_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 768);
_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, );
_VideoCapture.Start(); _VideoCapture.ImageGrabbed += (object oo, EventArgs es) =>
{
_VideoCapture.Retrieve(_Frame, );
using (Graphics g = Graphics.FromImage(_Frame.Bitmap))
{
g.DrawString([ DISCUZ_CODE_0 ]quot;比对总耗时{_TotalElapsedMilliseconds}毫秒", this.Font, Brushes.White, 0, 0);
for (int i = ; i < _DetectedFaceCount; i++)
{
if (_FaceResults.TryGetValue(i, out var faceResult))
{
g.DrawRectangle(Pens.Red, faceResult.Rectangle);
g.DrawString(faceResult.ToString(), this.Font, Brushes.White, faceResult.Rectangle.Location);
}
}
}
this._PictureBox.Image = _Frame.Bitmap;
}; _PictureBox.Click += (object oo, EventArgs es) =>
{
if (MessageBox.Show("您确定要保存人脸特征数据吗?", "确认信息", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
_SaveFlag = true;
}; _ImageSize = _VideoCapture.Width * _VideoCapture.Height * ;
_PImageData = Marshal.AllocCoTaskMem(_ImageSize);
_ImageWidth = _VideoCapture.Width;
_ImageHeight = _VideoCapture.Height; _TaskMatch = Task.Run(() =>
{
Task.Delay().Wait(); while (!_CTS.IsCancellationRequested)
{
try
{
Stopwatch sw = new Stopwatch();
sw.Restart(); Marshal.Copy(_Frame.GetData(), , _PImageData, _ImageSize);
ret = ASFDetectFaces(_PEngine, _ImageWidth, _ImageHeight, , _PImageData, out var faceInfo); if (ret != || faceInfo.FaceNum == )
{
_DetectedFaceCount = ;
continue;
} for (int detectedFaceIndex = ; detectedFaceIndex < faceInfo.FaceNum; detectedFaceIndex++)
{ float score = ;
string id = "";
ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo
{
FaceRect = Marshal.PtrToStructure<ASF_FaceRect>(IntPtr.Add(faceInfo.PFaceRect, SizeOfASF_FaceRect * detectedFaceIndex)),
FaceOrient = // Marshal.ReadInt32(IntPtr.Add(faceInfo.PFaceOrient, i * 4))
}; ret = ASFFaceFeatureExtract(_PEngine, _ImageWidth, _ImageHeight, , _PImageData, ref singleFaceInfo, out var faceFeature);
if (ret != )
continue;
_FaceResults[detectedFaceIndex].Rectangle = singleFaceInfo.FaceRect.GetRectangle(); if (_SaveFlag)
{
byte[] bufferSave = new byte[];
Marshal.Copy(faceFeature.PFeature, bufferSave, , );
var newId = DateTime.Now.Ticks.ToString(); FileStream fs = new FileStream("Feature.dat", FileMode.Append);
fs.Write(bufferSave, , );
fs.Close(); var streamWriter = File.AppendText("Id.txt");
streamWriter.Write("\r\n" + newId);
streamWriter.Close(); Marshal.Copy(bufferSave, , IntPtr.Add(_PFeatureLib, * _FeatureLibFaceCount), );
_FeatureLibIDList.Add(newId);
_FeatureLibFaceCount++; if (detectedFaceIndex == faceInfo.FaceNum - )
{
MessageBox.Show("保存特征数据成功!");
_SaveFlag = false;
}
continue;
} ConcurrentBag<int> needCompareFaceIndexs = new ConcurrentBag<int>(); Parallel.For(, _FeatureLibFaceCount, faceIndex =>
{ byte* pLib = ((byte*)_PFeatureLib) + * faceIndex + ;
byte* pCurrent = ((byte*)faceFeature.PFeature) + ;
int count = ;
for (int j = ; j < ; j++)
{
if (*pLib++ == *pCurrent++)
count++;
}
if (count > )
needCompareFaceIndexs.Add(faceIndex);
}); foreach (var index in needCompareFaceIndexs)//650ms
{
_FaceFeature.PFeature = IntPtr.Add(_PFeatureLib, index * );
ASFFaceFeatureCompare(_PEngine, ref faceFeature, ref _FaceFeature, out var r); if (r > 0.8 && r > score)
{
score = r;
id = _FeatureLibIDList[index];
}
} _FaceResults[detectedFaceIndex].Score = score;
_FaceResults[detectedFaceIndex].ID = id;
} _DetectedFaceCount = faceInfo.FaceNum; sw.Stop();
_TotalElapsedMilliseconds = sw.ElapsedMilliseconds; }
catch (Exception ex)
{ }
}
}, _CTS.Token); } }
}

三、下载测试用特征数据(500张人脸)并解压到运行目录

 ArcFaceData.zip (463.7 KB, 下载次数: 0)

四、按F5运行

点击视频增加当前人脸的特征数据,基本上800毫秒可以从20万人脸中找到你。

【C#】ArcFace2 视频人脸比对教程的更多相关文章

  1. ArcFace2 #C 视频人脸比对教程

    请允许我大言不惭,叫做教程,特希望各位能指正.哦,我用的是vs2017.使用虹软技术 一.准备工作1.创建项目 2.添加EMGU.CV包 3.复制虹软的dll到项目 ,并设属性“复制到输出目录”为“如 ...

  2. [深度应用]·实战掌握Dlib人脸识别开发教程

    [深度应用]·实战掌握Dlib人脸识别开发教程 个人网站--> http://www.yansongsong.cn/ 项目GitHub地址--> https://github.com/xi ...

  3. C++开发人脸性别识别教程(19)——界面美化

    在这篇博文中将完毕<C++开发人脸性别识别>的收尾工作.主要内容分为两部分:加入视频暂定功能.界面规范化. 一 视频暂停功能 严格来说这个视频暂定功能算是视频人脸性别识别的一个遗留问题,本 ...

  4. 视频人脸检测——OpenCV版(三)

    视频人脸检测是图片人脸检测的高级版本,图片检测详情点击查看我的上一篇<图片人脸检测——OpenCV版(二)> 实现思路: 调用电脑的摄像头,把摄像的信息逐帧分解成图片,基于图片检测标识出人 ...

  5. 视频人脸检测——Dlib版(六)

    往期目录 视频人脸检测--Dlib版(六) OpenCV添加中文(五) 图片人脸检测--Dlib版(四) 视频人脸检测--OpenCV版(三) 图片人脸检测--OpenCV版(二) OpenCV环境搭 ...

  6. 2018-06-21 中文代码示例视频演示Python入门教程第五章 数据结构

    知乎原链 续前作: 中文代码示例视频演示Python入门教程第四章 控制流 对应在线文档: 5. Data Structures 这一章起初还是采取了尽量与原例程相近的汉化方式, 但有些语义较偏(如T ...

  7. 2018-06-20 中文代码示例视频演示Python入门教程第四章 控制流

    知乎原链 续前作: 中文代码示例视频演示Python入门教程第三章 简介Python 对应在线文档: 4. More Control Flow Tools 录制中出了不少岔子. 另外, 输入法确实是一 ...

  8. 阿里云视频直播PHP-SDK接入教程

    阿里云视频直播PHP-SDK接入教程 阿里云 视频直播 配置 及 PHP-SDK 接入教程        准备工作        域名管理        配置鉴权        地址生成器及DEMO演 ...

  9. C++开发人脸性别识别教程(12)——加入性别识别功能

    经过之前几篇博客的解说,我们已经成功搭建了MFC应用框架,并实现了主要的图像显示和人脸检測程序,在这篇博文中我们要向当中加入性别识别代码. 关于性别识别,之前已经专门拿出两篇博客的篇幅来进行解说.这里 ...

随机推荐

  1. Swift_枚举

    Swift_枚举 点击查看源码 空枚举 //空枚举 enum SomeEnumeration { // enumeration definition goes here } 枚举基本类型 //枚举基本 ...

  2. JS中some(),every(),fiflter(),map()各种循环的区别理解

    1.some():返回一个Boolean,判断是否有元素符合func条件const arr = [1,2,3,4]; arr.some((item)=>{return item>1}) 打 ...

  3. 微信网页授权-公众号支付(获取openid、用户信息等)

    名词解释: openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID 业务功能描述:实现H5页面可以在微信浏览器里面进行微信支付,所以需要 ...

  4. Struts2+Spring+Hibernate整合开发(Maven多模块搭建)

    Struts2+Spring+Hibernate整合开发(Maven多模块搭建) 0.项目结构 Struts2:web层 Spring:对象的容器 Hibernate:数据库持久化操作 1.父模块导入 ...

  5. pt-query-digest慢日志分析工具

    简介 pt-query-digest是用于分析mysql慢查询的一个工具,它可以分析binlog.General log.slowlog,也可以通过SHOW PROCESSLIST或者通过tcpdum ...

  6. 如何创建systemd定时任务

    1. 如何创建一个定时任务,通过systemd系统 1. 如何创建一个定时任务,通过systemd系统 1.1. systemd中的timer 1.2. 自定义定时任务 1.2.1. 具体步骤 1.2 ...

  7. 跨浏览器实现placeholder效果的jQuery插件

    曾经遇到这样一个问题,处理IE8密码框placeholder属性兼容性.几经周折,这个方案是可以解决问题的. 1.jsp页面引入js插件 <script type="text/java ...

  8. Jquery中绑定事件与普通事件的区别

    (“#panel”).bind(“click”,function(){ 与$(“#panel”).click(function(){ 有什么区别 ? 绑定可以同时加多个事件 如:$(“#panel”) ...

  9. sample采样倾斜key并单独进行join代码

    /** * sample采样倾斜key单独进行join */ JavaPairRDD<Long, String> sampledRDD = userid2PartAggrInfoRDD.s ...

  10. 应用性能管理(APM, Application Performance Management)

    当下成熟的互联网公司都建立有从基础设施到应用程序的全方位监控系统,力求及时发现故障进行处理并为优化程序提供性能数据支持,降低整体运维成本.国内外商业的APM有Compuware.iMaster.博睿B ...