请允许我大言不惭,叫做教程,特希望各位能指正。哦,我用的是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. Oracle创建聚簇表

    创建聚簇表过程: 创建簇(cluster)----创建簇表(基本类似创建一般表但有区别)----创建簇索引(index)----数据管理 创建簇: create cluster stu_ach(sid ...

  2. 06 hash join (Oracle里的哈希连接原理)

    hash join (Oracle里的哈希连接原理) 2015年09月25日 17:00:28 阅读数:2188 哈希连接(HASH JOIN)是一种两个表在做表连接时主要依靠哈希运算来得到连接结果集 ...

  3. zabbix 3.x 监控日志文件

    1.启用zabbix主动模式 在zabbix agent端,修改/etc/zabbix/zabbix_agentd.conf ServerActive=服务端IP Hostname=tspnginx0 ...

  4. ubuntu14.04安装qt-4.8.4

    题记:因为工作中用到qt的qmake工具生成x项目的Makefile文件,因为原有工程用的是4.8.4版本的,因此在此基础之上安装此版本. 用安装包工具进行安装qt不能直接安装到4.8.4版本的,因此 ...

  5. 在vue中如何实现购物车checkbox的三级联动

    最近用vue写一个电商项目,自然就少不了要写一个购物车的相关页面,功能完整的购物车的checkbox应该是三级联动的,1级checkbox是选中购物车中所有的商品,2级checkbox是选中某个店铺下 ...

  6. css:文章标题过长时,使用省略号

    html代码 <ul> <li><a href="" target="_blank">我是文章1,现在标题过长,使用css加 ...

  7. nuxt 优化项:禁用js的预加载

    这里有个nuxt和vue不同的地方,这个地方很有意思,官方的中文文档说得蜜汁自信 ------------------------------- In production, nuxt.js uses ...

  8. thinkphp5实现定位功能

    一.所需资源链接:百度网盘.主要包含一个ip地址库和一个ip类文件. 二.下载好后,在extend目录下面创建一个location的目录,将下载的文件解压到该目录.给类文件增加一个命名空间,便于我们使 ...

  9. spark成长之路(1)spark究竟是什么?

    今年6月毕业,来到公司前前后后各种事情折腾下来,8月中旬才入职.本以为终于可以静下心来研究技术了,但是又把我分配到了一个几乎不做技术的解决方案部门,导致现在写代码的时间都几乎没有了,所以只能在每天下班 ...

  10. 网站用户行为分析——Linux的安装

    Linux的选择 在Linux系统各个发行版中,CentOS系统和Ubuntu系统在服务端和桌面端使用占比最高,网络上资料最是齐全,所以建议使用CentOS系统或Ubuntu. 一般来说,如果要做服务 ...