【C#】ArcFace2 视频人脸比对教程
请允许我大言不惭,叫做教程,特希望各位能指正。哦,我用的是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 视频人脸比对教程的更多相关文章
- ArcFace2 #C 视频人脸比对教程
请允许我大言不惭,叫做教程,特希望各位能指正.哦,我用的是vs2017.使用虹软技术 一.准备工作1.创建项目 2.添加EMGU.CV包 3.复制虹软的dll到项目 ,并设属性“复制到输出目录”为“如 ...
- [深度应用]·实战掌握Dlib人脸识别开发教程
[深度应用]·实战掌握Dlib人脸识别开发教程 个人网站--> http://www.yansongsong.cn/ 项目GitHub地址--> https://github.com/xi ...
- C++开发人脸性别识别教程(19)——界面美化
在这篇博文中将完毕<C++开发人脸性别识别>的收尾工作.主要内容分为两部分:加入视频暂定功能.界面规范化. 一 视频暂停功能 严格来说这个视频暂定功能算是视频人脸性别识别的一个遗留问题,本 ...
- 视频人脸检测——OpenCV版(三)
视频人脸检测是图片人脸检测的高级版本,图片检测详情点击查看我的上一篇<图片人脸检测——OpenCV版(二)> 实现思路: 调用电脑的摄像头,把摄像的信息逐帧分解成图片,基于图片检测标识出人 ...
- 视频人脸检测——Dlib版(六)
往期目录 视频人脸检测--Dlib版(六) OpenCV添加中文(五) 图片人脸检测--Dlib版(四) 视频人脸检测--OpenCV版(三) 图片人脸检测--OpenCV版(二) OpenCV环境搭 ...
- 2018-06-21 中文代码示例视频演示Python入门教程第五章 数据结构
知乎原链 续前作: 中文代码示例视频演示Python入门教程第四章 控制流 对应在线文档: 5. Data Structures 这一章起初还是采取了尽量与原例程相近的汉化方式, 但有些语义较偏(如T ...
- 2018-06-20 中文代码示例视频演示Python入门教程第四章 控制流
知乎原链 续前作: 中文代码示例视频演示Python入门教程第三章 简介Python 对应在线文档: 4. More Control Flow Tools 录制中出了不少岔子. 另外, 输入法确实是一 ...
- 阿里云视频直播PHP-SDK接入教程
阿里云视频直播PHP-SDK接入教程 阿里云 视频直播 配置 及 PHP-SDK 接入教程 准备工作 域名管理 配置鉴权 地址生成器及DEMO演 ...
- C++开发人脸性别识别教程(12)——加入性别识别功能
经过之前几篇博客的解说,我们已经成功搭建了MFC应用框架,并实现了主要的图像显示和人脸检測程序,在这篇博文中我们要向当中加入性别识别代码. 关于性别识别,之前已经专门拿出两篇博客的篇幅来进行解说.这里 ...
随机推荐
- centos安装hadoop(伪分布式)
在本机上装的CentOS 5.5 虚拟机, 软件准备:jdk 1.6 U26 hadoop:hadoop-0.20.203.tar.gz ssh检查配置 [root@localhost ~]# ssh ...
- react系列(四)Redux基本概念和使用
Redux基本概念和使用 先从Flux开始 先放一个Flux官网的链接.需要fq. Flux是Facebook提出的一种构建客户端网页应用的应用架构,它是一种抽象程度很高的设计模式,鼓励单向数据流. ...
- oracle 数据库密码生产同步模拟环境 ,随记常用命令
1.查看当前open用户 select username,account_status,expiry_date,profile from dba_users; 2.查看目前的密码过期策略 select ...
- jQuery.qrcode 生成二维码,并使用 jszip、FileSaver 下载 zip 压缩包至本地。
生成二维码 引用 jquery.qrcode.js :连接:https://files.cnblogs.com/files/kitty-blog/jquery.qrcode.js .https:// ...
- thinkphp5 rbac权限
thinkphp 5 rbac权限 一 先创建一个数据库; 例如:创建一个test数据库;然后创建3个 表分别为:test_admin (管理员表), test_role,test_auth. 这个是 ...
- laravel 安装添加多站点
官方文档如下 https://learnku.com/laravel/t/1160/laravel-nginx-multi-site-configuration
- Cab 安装不成功问题
使用 iexpress.exe 成功打包了cab文件. 可下面问题来了,用静态的html调用,提示安装. 确认安装之后,却提示找不到相应的*.ocx,导致无法安装文件到系统 分析具体原因:*.ocx ...
- IO流之字节流
IO流分类 按照数据流向 输入流:从外界(键盘.网络.文件…)读取数据到内存 输出流:用于将程序中的数据写出到外界(显示器.文件…) 数据源 目的地 交通工具 按照数据类型 字节流:主要用来处理字节或 ...
- java 用接口计算圆柱的体积和面积并添加颜色
import java.util.Scanner; class Test { public static void main(String[] args) { fangfa i = new fangf ...
- Docker入门系列01
前两篇写了 Docker 如何安装和相关的概念,当然概念的东西省略了很多,主要是自己水平有限,所以后期会可能增添.但以上内容都是用别人的建好的 镜像(Image) ,这怎么行,我们应该自己动手造轮子, ...