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

一、准备工作

1.创建项目

2.添加EMGU.CV包

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

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

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

二、代码

  1. using Emgu.CV;
  2. using System;
  3. using System.Collections.Concurrent;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.IO;
  8. using System.Runtime.InteropServices;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. using System.Windows.Forms;
  12.  
  13. namespace ArcFace2Demo
  14. {
  15. public partial class Form1 : Form
  16. {
  17. #region ArcFaceConst
  18. const uint ASF_DETECT_MODE_VIDEO = 0x00000000; //Video模式,一般用于多帧连续检测
  19. const uint ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF; //Image模式,一般用于静态图的单次检测
  20.  
  21. const uint ASF_NONE = 0x00000000;
  22. const uint ASF_FACE_DETECT = 0x00000001; //此处detect可以是tracking或者detection两个引擎之一,具体的选择由detect mode 确定
  23. const uint ASF_FACERECOGNITION = 0x00000004;
  24. const uint ASF_AGE = 0x00000008;
  25. const uint ASF_GENDER = 0x00000010;
  26. const uint ASF_FACE3DANGLE = 0x00000020;
  27.  
  28. /// <summary>
  29. /// 结构ASF_FaceRect的长度
  30. /// 32位程序是16,64位程序需要改为32
  31. /// </summary>
  32. const int SizeOfASF_FaceRect = ;
  33.  
  34. #endregion
  35.  
  36. #region ArceDataStructure
  37. /// <summary>
  38. /// 人脸在图片中的位置
  39. /// </summary>
  40. [StructLayout(LayoutKind.Sequential)]
  41. internal struct ASF_FaceRect
  42. {
  43. public int Left;
  44. public int Top;
  45. public int Right;
  46. public int Bottom;
  47. public Rectangle GetRectangle()
  48. {
  49. return new Rectangle(Left, Top, Right - Left, Bottom - Top);
  50. }
  51. }
  52. /// <summary>
  53. /// 多人脸信息
  54. /// </summary>
  55. [StructLayout(LayoutKind.Sequential)]
  56. internal struct ASF_MultiFaceInfo
  57. {
  58.  
  59. public IntPtr PFaceRect;
  60. public IntPtr PFaceOrient;
  61. [MarshalAs(UnmanagedType.I4)]
  62. public int FaceNum;
  63. }
  64.  
  65. /// <summary>
  66. /// 单人脸信息
  67. /// </summary>
  68. [StructLayout(LayoutKind.Sequential)]
  69. internal struct ASF_SingleFaceInfo
  70. {
  71. public ASF_FaceRect FaceRect;
  72. public int FaceOrient;
  73.  
  74. }
  75.  
  76. /// <summary>
  77. /// 人脸特征
  78. /// </summary>
  79. [StructLayout(LayoutKind.Sequential)]
  80. internal struct ASF_FaceFeature
  81. {
  82. public IntPtr PFeature;
  83. [MarshalAs(UnmanagedType.I4)]
  84. public int FeatureSize;
  85. }
  86.  
  87. #endregion
  88.  
  89. #region ArcWrapper
  90.  
  91. /// <summary>
  92. /// 激活SDK
  93. /// </summary>
  94. /// <param name="appId"></param>
  95. /// <param name="sdkKey"></param>
  96. /// <returns>0:激活成功,0x16002表示已经激活</returns>
  97. [DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFActivation", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  98. private static extern int ASFActivation(string appId, string sdkKey);
  99.  
  100. /// <summary>
  101. /// 初始化引擎
  102. /// </summary>
  103. /// <param name="detectMode">long会返回scale错误0x16004</param>
  104. /// <param name="orientPriority"></param>
  105. /// <param name="scale"></param>
  106. /// <param name="maxFaceNumber"></param>
  107. /// <param name="combinedMask"></param>
  108. /// <param name="pEngine"></param>
  109. /// <returns></returns>
  110. [DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFInitEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  111. private static extern int ASFInitEngine(uint detectMode, int orientPriority, int scale, int maxFaceNumber, uint combinedMask, out IntPtr pEngine);
  112. /// <summary>
  113. /// 人脸检测
  114. /// </summary>
  115. /// <param name="pEngine"></param>
  116. /// <param name="width"></param>
  117. /// <param name="height"></param>
  118. /// <param name="format"></param>
  119. /// <param name="pImageData"></param>
  120. /// <param name="faceInfo"></param>
  121. /// <returns></returns>
  122. [DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFDetectFaces", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  123. private static extern int ASFDetectFaces(IntPtr pEngine, int width, int height, int format, IntPtr pImageData, out ASF_MultiFaceInfo faceInfo);
  124.  
  125. /// <summary>
  126. /// 单人脸特征提取
  127. /// </summary>
  128. /// <param name="pEngine"></param>
  129. /// <param name="width"></param>
  130. /// <param name="height"></param>
  131. /// <param name="format"></param>
  132. /// <param name="faceInfo"></param>
  133. /// <param name="faceFeature"></param>
  134. /// <returns></returns>
  135. [DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFFaceFeatureExtract", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  136. private static extern int ASFFaceFeatureExtract(IntPtr pEngine, int width, int height, int format, IntPtr pImageData, ref ASF_SingleFaceInfo faceInfo, out ASF_FaceFeature faceFeature);
  137. /// <summary>
  138. /// 脸特征比对
  139. /// </summary>
  140. /// <param name="pEngine"></param>
  141. /// <param name="faceFeature1"></param>
  142. /// <param name="faceFeature2"></param>
  143. /// <param name="result"></param>
  144. /// <returns></returns>
  145. [DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFFaceFeatureCompare", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  146. private static extern int ASFFaceFeatureCompare(IntPtr pEngine, ref ASF_FaceFeature faceFeature1, ref ASF_FaceFeature faceFeature2, out float result);
  147. /// <summary>
  148. /// 销毁引擎
  149. /// </summary>
  150. /// <param name="engine"></param>
  151. /// <returns></returns>
  152. [DllImport("libarcsoft_face_engine.dll", EntryPoint = "ASFUninitEngine", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  153. private static extern int ASFUninitEngine(IntPtr engine);
  154. #endregion
  155.  
  156. /// <summary>
  157. /// 特征库
  158. /// </summary>
  159. IntPtr _PFeatureLib;
  160. /// <summary>
  161. /// 特征库人脸数量
  162. /// </summary>
  163. int _FeatureLibFaceCount = ;
  164. /// <summary>
  165. /// 特征库人脸ID列表
  166. /// </summary>
  167. List<string> _FeatureLibIDList = new List<string>();
  168.  
  169. /// <summary>
  170. /// 人脸特征结构
  171. /// </summary>
  172. ASF_FaceFeature _FaceFeature = new ASF_FaceFeature { FeatureSize = };
  173.  
  174. /// <summary>
  175. /// 人脸识别的结果
  176. /// </summary>
  177. class FaceResult
  178. {
  179. /// <summary>
  180. /// 人脸框矩形
  181. /// </summary>
  182. public Rectangle Rectangle { get; set; }
  183. /// <summary>
  184. /// 人脸ID
  185. /// </summary>
  186. public string ID { get; set; }
  187. /// <summary>
  188. /// 比对结果
  189. /// </summary>
  190. public float Score { get; set; }
  191.  
  192. public override string ToString()
  193. {
  194. return [ DISCUZ_CODE_0 ]quot;ID:{ID}\r\n结果:{Score}";
  195. }
  196. }
  197. /// <summary>
  198. /// 多人脸识别结果集
  199. /// </summary>
  200. ConcurrentDictionary<int, FaceResult> _FaceResults = new ConcurrentDictionary<int, FaceResult>();
  201. /// <summary>
  202. /// 检测到的人脸数量
  203. /// </summary>
  204. int _DetectedFaceCount = ;
  205.  
  206. /// <summary>
  207. /// 视频捕获
  208. /// </summary>
  209. VideoCapture _VideoCapture;
  210. Mat _Frame = new Mat();
  211.  
  212. /// <summary>
  213. /// 虹软人脸引擎
  214. /// </summary>
  215. IntPtr _PEngine = IntPtr.Zero;
  216.  
  217. /// <summary>
  218. /// 比对一次总耗时
  219. /// </summary>
  220. long _TotalElapsedMilliseconds = ;
  221. /// <summary>
  222. /// 识别任务
  223. /// </summary>
  224. Task _TaskMatch;
  225. /// <summary>
  226. /// 向识别任务发送取消指令的东东
  227. /// </summary>
  228. CancellationTokenSource _CTS = new CancellationTokenSource();
  229.  
  230. /// <summary>
  231. /// 图像数据
  232. /// </summary>
  233. IntPtr _PImageData;
  234. /// <summary>
  235. /// 宽、高、图像数据长度
  236. /// </summary>
  237. int _ImageWidth, _ImageHeight, _ImageSize;
  238. /// <summary>
  239. /// 是否要保存当前人脸特征
  240. /// </summary>
  241. bool _SaveFlag = false;
  242.  
  243. PictureBox _PictureBox;
  244.  
  245. public Form1()
  246. {
  247. InitializeComponent();
  248.  
  249. _PictureBox = new PictureBox();
  250. _PictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
  251. _PictureBox.Dock = DockStyle.Fill;
  252. this.Controls.Add(_PictureBox);
  253.  
  254. this.Load += Form1_Load;
  255. this.FormClosing += Form1_FormClosing;
  256. }
  257.  
  258. private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  259. {
  260. if (_TaskMatch != null)
  261. {
  262. _CTS.Cancel();
  263. while (_TaskMatch.Status == TaskStatus.Running)
  264. Task.Delay().Wait();
  265. }
  266. _VideoCapture.Stop();
  267.  
  268. if (_PEngine != IntPtr.Zero)
  269. ASFUninitEngine(_PEngine);
  270.  
  271. if (_PFeatureLib != IntPtr.Zero)
  272. Marshal.FreeCoTaskMem(_PFeatureLib);
  273.  
  274. if (_PImageData != IntPtr.Zero)
  275. Marshal.FreeCoTaskMem(_PImageData);
  276. }
  277.  
  278. private unsafe void Form1_Load(object sender, EventArgs e)
  279. {
  280. var ret = ASFActivation("BKgqTWQPQQbomfqvyd2VJzTUqPp3JD8zjAzDcqsL1jLa", "2nkDTmnkpS53cpSY42fFS9nEUzg8x4MDGkAubSsebtm1");
  281. if (ret != && ret != 0x16002)
  282. {
  283. MessageBox.Show("SDK激活失败:0x" + ret.ToString("x2"));
  284. return;
  285. }
  286. ret = ASFInitEngine(ASF_DETECT_MODE_IMAGE, , , , ASF_FACE_DETECT | ASF_FACERECOGNITION, out _PEngine);
  287. if (ret != )
  288. {
  289. MessageBox.Show([ DISCUZ_CODE_0 ]quot;人脸识别引擎初始化失败:" + ret.ToString("x2"));
  290. return;
  291. }
  292. //初始化识别结果集
  293. for (int i = ; i < ; i++)
  294. _FaceResults[i] = new FaceResult();
  295. //初始化特征库
  296. _PFeatureLib = Marshal.AllocCoTaskMem( * + * * );
  297. var bytes = File.ReadAllBytes("Feature.dat");
  298. var ids = File.ReadAllLines("Id.txt");
  299. for (int i = ; i < * ; i++)
  300. {
  301. Marshal.Copy(bytes, , IntPtr.Add(_PFeatureLib, _FeatureLibFaceCount * ), bytes.Length);
  302. _FeatureLibIDList.AddRange(ids);
  303. _FeatureLibFaceCount += ids.Length;
  304. }
  305.  
  306. _VideoCapture = new VideoCapture();
  307.  
  308. //_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 1024);
  309. //_VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 768);
  310. _VideoCapture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps, );
  311. _VideoCapture.Start();
  312.  
  313. _VideoCapture.ImageGrabbed += (object oo, EventArgs es) =>
  314. {
  315. _VideoCapture.Retrieve(_Frame, );
  316. using (Graphics g = Graphics.FromImage(_Frame.Bitmap))
  317. {
  318. g.DrawString([ DISCUZ_CODE_0 ]quot;比对总耗时{_TotalElapsedMilliseconds}毫秒", this.Font, Brushes.White, 0, 0);
  319. for (int i = ; i < _DetectedFaceCount; i++)
  320. {
  321. if (_FaceResults.TryGetValue(i, out var faceResult))
  322. {
  323. g.DrawRectangle(Pens.Red, faceResult.Rectangle);
  324. g.DrawString(faceResult.ToString(), this.Font, Brushes.White, faceResult.Rectangle.Location);
  325. }
  326. }
  327. }
  328. this._PictureBox.Image = _Frame.Bitmap;
  329. };
  330.  
  331. _PictureBox.Click += (object oo, EventArgs es) =>
  332. {
  333. if (MessageBox.Show("您确定要保存人脸特征数据吗?", "确认信息", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
  334. _SaveFlag = true;
  335. };
  336.  
  337. _ImageSize = _VideoCapture.Width * _VideoCapture.Height * ;
  338. _PImageData = Marshal.AllocCoTaskMem(_ImageSize);
  339. _ImageWidth = _VideoCapture.Width;
  340. _ImageHeight = _VideoCapture.Height;
  341.  
  342. _TaskMatch = Task.Run(() =>
  343. {
  344. Task.Delay().Wait();
  345.  
  346. while (!_CTS.IsCancellationRequested)
  347. {
  348. try
  349. {
  350. Stopwatch sw = new Stopwatch();
  351. sw.Restart();
  352.  
  353. Marshal.Copy(_Frame.GetData(), , _PImageData, _ImageSize);
  354. ret = ASFDetectFaces(_PEngine, _ImageWidth, _ImageHeight, , _PImageData, out var faceInfo);
  355.  
  356. if (ret != || faceInfo.FaceNum == )
  357. {
  358. _DetectedFaceCount = ;
  359. continue;
  360. }
  361.  
  362. for (int detectedFaceIndex = ; detectedFaceIndex < faceInfo.FaceNum; detectedFaceIndex++)
  363. {
  364.  
  365. float score = ;
  366. string id = "";
  367. ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo
  368. {
  369. FaceRect = Marshal.PtrToStructure<ASF_FaceRect>(IntPtr.Add(faceInfo.PFaceRect, SizeOfASF_FaceRect * detectedFaceIndex)),
  370. FaceOrient = // Marshal.ReadInt32(IntPtr.Add(faceInfo.PFaceOrient, i * 4))
  371. };
  372.  
  373. ret = ASFFaceFeatureExtract(_PEngine, _ImageWidth, _ImageHeight, , _PImageData, ref singleFaceInfo, out var faceFeature);
  374. if (ret != )
  375. continue;
  376. _FaceResults[detectedFaceIndex].Rectangle = singleFaceInfo.FaceRect.GetRectangle();
  377.  
  378. if (_SaveFlag)
  379. {
  380. byte[] bufferSave = new byte[];
  381. Marshal.Copy(faceFeature.PFeature, bufferSave, , );
  382. var newId = DateTime.Now.Ticks.ToString();
  383.  
  384. FileStream fs = new FileStream("Feature.dat", FileMode.Append);
  385. fs.Write(bufferSave, , );
  386. fs.Close();
  387.  
  388. var streamWriter = File.AppendText("Id.txt");
  389. streamWriter.Write("\r\n" + newId);
  390. streamWriter.Close();
  391.  
  392. Marshal.Copy(bufferSave, , IntPtr.Add(_PFeatureLib, * _FeatureLibFaceCount), );
  393. _FeatureLibIDList.Add(newId);
  394. _FeatureLibFaceCount++;
  395.  
  396. if (detectedFaceIndex == faceInfo.FaceNum - )
  397. {
  398. MessageBox.Show("保存特征数据成功!");
  399. _SaveFlag = false;
  400. }
  401. continue;
  402. }
  403.  
  404. ConcurrentBag<int> needCompareFaceIndexs = new ConcurrentBag<int>();
  405.  
  406. Parallel.For(, _FeatureLibFaceCount, faceIndex =>
  407. {
  408.  
  409. byte* pLib = ((byte*)_PFeatureLib) + * faceIndex + ;
  410. byte* pCurrent = ((byte*)faceFeature.PFeature) + ;
  411. int count = ;
  412. for (int j = ; j < ; j++)
  413. {
  414. if (*pLib++ == *pCurrent++)
  415. count++;
  416. }
  417. if (count > )
  418. needCompareFaceIndexs.Add(faceIndex);
  419. });
  420.  
  421. foreach (var index in needCompareFaceIndexs)//650ms
  422. {
  423. _FaceFeature.PFeature = IntPtr.Add(_PFeatureLib, index * );
  424. ASFFaceFeatureCompare(_PEngine, ref faceFeature, ref _FaceFeature, out var r);
  425.  
  426. if (r > 0.8 && r > score)
  427. {
  428. score = r;
  429. id = _FeatureLibIDList[index];
  430. }
  431. }
  432.  
  433. _FaceResults[detectedFaceIndex].Score = score;
  434. _FaceResults[detectedFaceIndex].ID = id;
  435. }
  436.  
  437. _DetectedFaceCount = faceInfo.FaceNum;
  438.  
  439. sw.Stop();
  440. _TotalElapsedMilliseconds = sw.ElapsedMilliseconds;
  441.  
  442. }
  443. catch (Exception ex)
  444. {
  445.  
  446. }
  447. }
  448. }, _CTS.Token);
  449.  
  450. }
  451.  
  452. }
  453. }

三、下载测试用特征数据(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. centos安装hadoop(伪分布式)

    在本机上装的CentOS 5.5 虚拟机, 软件准备:jdk 1.6 U26 hadoop:hadoop-0.20.203.tar.gz ssh检查配置 [root@localhost ~]# ssh ...

  2. react系列(四)Redux基本概念和使用

    Redux基本概念和使用 先从Flux开始 先放一个Flux官网的链接.需要fq. Flux是Facebook提出的一种构建客户端网页应用的应用架构,它是一种抽象程度很高的设计模式,鼓励单向数据流. ...

  3. oracle 数据库密码生产同步模拟环境 ,随记常用命令

    1.查看当前open用户 select username,account_status,expiry_date,profile from dba_users; 2.查看目前的密码过期策略 select ...

  4. jQuery.qrcode 生成二维码,并使用 jszip、FileSaver 下载 zip 压缩包至本地。

    生成二维码 引用 jquery.qrcode.js  :连接:https://files.cnblogs.com/files/kitty-blog/jquery.qrcode.js .https:// ...

  5. thinkphp5 rbac权限

    thinkphp 5 rbac权限 一 先创建一个数据库; 例如:创建一个test数据库;然后创建3个 表分别为:test_admin (管理员表), test_role,test_auth. 这个是 ...

  6. laravel 安装添加多站点

    官方文档如下 https://learnku.com/laravel/t/1160/laravel-nginx-multi-site-configuration

  7. Cab 安装不成功问题

    使用 iexpress.exe 成功打包了cab文件. 可下面问题来了,用静态的html调用,提示安装. 确认安装之后,却提示找不到相应的*.ocx,导致无法安装文件到系统 分析具体原因:*.ocx ...

  8. IO流之字节流

    IO流分类 按照数据流向 输入流:从外界(键盘.网络.文件…)读取数据到内存 输出流:用于将程序中的数据写出到外界(显示器.文件…) 数据源 目的地 交通工具 按照数据类型 字节流:主要用来处理字节或 ...

  9. java 用接口计算圆柱的体积和面积并添加颜色

    import java.util.Scanner; class Test { public static void main(String[] args) { fangfa i = new fangf ...

  10. Docker入门系列01

    前两篇写了 Docker 如何安装和相关的概念,当然概念的东西省略了很多,主要是自己水平有限,所以后期会可能增添.但以上内容都是用别人的建好的 镜像(Image) ,这怎么行,我们应该自己动手造轮子, ...