[C#]_Demo_4线程虹软人脸识别注册开发全过程

摘要:
效率有点低。我们在哪里可以节省时间?源代码:https://github.com/catzhou2002/ArcFaceDemo老实说,整个项目是使用虹膜技术开发的。为了提高识别效率,我已经尽力做了很多自我思考的优化。如果你感兴趣,请听我说。第一部分单线程中的各种胜利:1.胜利LPASVLOFFSCREEN:LPASVLFFSCREEN的结果没有在文档中描述,或者我找不到它们。我不知道去哪里

效率有点低,大家看看哪里开可以节省时间?
源代码:https://github.com/catzhou2002/ArcFaceDemo
整个项目使用虹软技术完成开发
说实话,为了提高识别效率,我也是竭尽所能,干了不少自认为的优化,如有兴趣听我说说。


第一部分 单线程时候的各种折腾


一、折腾LPASVLOFFSCREEN
话说这个LPASVLOFFSCREEN的结果文档里面没有说明,或者是我没找到。
我也不知道从哪里复制来的,主要折腾的是ppu8Plane[0]地址,一般操作是

锁定图片内存
ppu8Plane[0]分配制定长度的内存
把图片内存中的字节复制到一个临时数组
然后用Marshal.Copy复制到指定的地址
解锁图片内存

我改成:

锁定图片内存
ppu8Plane[0]指向图片地址
等不需要LPASVLOFFSCREEN时(人脸检测、获取特征值、性别判断、年龄估算等结束后)解锁图片内存

就晚一点解锁,省了好多事情,耗时由4毫秒没成2微妙。当时就发了个帖:C# Bitmap转ASVLOFFSCREEN的最佳方式?
后来觉得这名字实在记不住,也不C#,改成了ImageData,整个转换过程如下:

var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            var imageData = new ImageData
            {
                PixelArrayFormat = 513,//Rgb24,
                Width = bitmap.Width,
                Height = bitmap.Height,
                Pitch = new int[4] { bmpData.Stride, 0, 0, 0 },
                ppu8Plane = new IntPtr[4] { bmpData.Scan0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero }
            };
....
            bitmap.UnlockBits(bmpData);

其实如果是视频图片的话,图片的宽度和高度都是固定的,想了想,没折腾。

二、单线程时将获取到的FaceModel直接做人脸比对的参数

ExtractFeature(_FaceMatchEngine, ref imageData, ref faceFeatureInput, out var <font color="#ff8c00">faceModel</font>);
FacePairMatch(_FaceMatchEngine, ref fm, ref <font color="#ff8c00">faceModel</font>, out float score);

一般操作是faceModel里面的字节复制到临时字节数组,然后创建新的FaceModel,分配内存,在将临时字节数组复制到FaceModel。

三、人脸库直接用FaceModel

/// <summary>
    /// 人脸库
    /// </summary>
    public class FaceLib
    {
        public List<Item> Items { get; set; } = new List<Item>();
        public class Item
        {
            /// <summary>
            /// 用于排序
            /// </summary>
            public long OrderId { get; set; }
            /// <summary>
            /// 文件名作为ID
            /// </summary>
            public string ID { get; set; }
            /// <summary>
            /// 人脸模型
            /// </summary>
<font color="#ff8c00">            public FaceModel FaceModel { get; set; }</font>  
        }
    }

四、比对结果>0.5就算成功
五、人脸库增加OrderId
识别成功后再次比对就很快,应该是首发命中。
六、将人脸比对和结果显示分开
一开始没想太多,将人脸比对和结果显示放在新视频帧事件里面,流程是:

新视频帧(30帧/秒)
获取检测和识别的结果(人脸框和ID)
显示检测和识别的结果

结果视频卡顿,获取人脸特征的200毫秒成为瓶颈,改成:

人脸比对

 Task.Factory.StartNew(() =>
            {
                Task.Delay(1000).Wait();
                while (!_CancellationTokenSource.IsCancellationRequested)
                {
                    #region 200毫秒左右
                    MatchFrame(); 
                    #endregion
                }
            }, _CancellationTokenSource.Token);

结果显示

 private void VideoPlayer_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawRectangle(Pens.White, _FaceResult.Rectangle);
            e.Graphics.DrawString(_FaceResult.ID , this.Font, Brushes.White, _FaceResult.Rectangle.Left, _FaceResult.Rectangle.Top - 20);
        }

第二部分 多线程的折腾


一、确定4线程为最佳
各种测试后得出的结论,也不知道对不对,也不知道为什么,哎。
因网友的要求,同步到了github
二、删除了单线程
有了更快的,就不要慢的了。
三、n张脸如何分配给4个线程获取特征值?
动了不少脑筋,Interlocked.Increment是关键。
最终有改了下面的内容

如果只有一张脸(窃以为一张脸的概率比较高),也用Task,影响效率,增加了 if (detectResult.FaceCount ==
1)
Intptr之间复制字节用CopyMemory比较快
两三张脸的时候开4个线程不好,改成 new Task[TaskNum < detectResult.FaceCount ?
TaskNum : detectResult.FaceCount]

四、识别结果(集)的折腾

弄了个结果集,按最大人脸数设了个List( Items = new List();)
增加了FaceFeatureInput FFI,省的每次都去创建
并将人脸方向设成1(Orient = 1)(因为是视频图片,其他方向的人脸,呵呵),人脸检测后都不要去获取人脸方向的值
增加并初始化了FaceModel(FaceModel FaceModel = new FaceModel() { Size =
22020, PFeature = Marshal.AllocCoTaskMem(22020) };),获取到的特征字节直接复制过来便可

五、保存特征值到人脸库的时候同时保存头像
因为虹软说了,sdk升级的时候,特征值也有可能变化。那咱先把头像保存起来,到时候重新生成一下。
主要的操作是把矩形放大一点(Inflate((int)(r.Width * 0.5), (int)(r.Height * 0.5))),咱保存的头像怎么着得是个人头吧。
(想来条分割线,居然只有华丽的分割线,算了。顺便吐槽一下,这个论坛的编辑器实在是让人无语_)
各种折腾后,黔驴技穷了,10,000人脸的库得出10张不认识的脸的结论,需要10秒钟。当然,换好一点的电脑可以提高效率,如我的台式机(i5-7500),输入图片只有1张脸的时候,遍历

1万张人脸仅需390毫秒
5万张人脸也就1525毫秒
10万张人脸说我内存不够,可能是我的程序是32位的缘故,换成64位的sdk估计3秒钟也能搞定(太麻烦,不折腾了)

结论是:虹软中型sdk用于考勤、小区门禁、写字楼门禁等场所完全没问题。
下一步我打算(其实已经差不多完成,我公司的项目——酒店自助机)改成单脸多线程识别,增加以下功能:

40次检测人脸数为0,则确认为没人,识别频率降低
是否换人了?
同一个人3、4次识别不出ID后,确认为陌生人,不在遍历
刷身份证获取照片人脸比对后存入人脸库

免责声明:文章转载自《[C#]_Demo_4线程虹软人脸识别注册开发全过程》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇从数学到密码学(十五)iOS定位元素下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

opencv学习之路(41)、人脸识别

一、人脸检测并采集个人图像 //take_photo.cpp #include<opencv2/opencv.hpp> using namespacecv; using namespacestd; voidtake_photo() { VideoCapture cap(0); //打开摄像头 if (!cap...

人脸识别的会遇到的问题及解决方法

参考:https://blog.csdn.net/duan19920101/article/details/50683988/?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242 注:以前做过基于KNN算法的人脸识别,但是未做这样的总结,这...

【C#】虹软Arc人脸识别 ArcFace 2.0 demo

环境: win7以上 VS2013以上 sdk版本:ArcFace v2.0 x86 x64平台Debug、Release配置都已通过编译下载地址:https://github.com/ArcsoftEscErd/ArcfaceDemo_CSharp.git 配置过程: 1. 到[虹软官网](https://ai.arcsoft.com.cn/index....

【新品】Face X2人脸识别一体机:新增刷卡、扫码、测温、语音播报等功能

采用高性能硬件配置,高效人脸识别算法,支持身份证、IC卡、二维码、条形码快速识别,内置双声道喇叭,实现语音播报、语音提醒;支持非接触快速测温,减少近距离接触传染,配套完善的后台管理系统,可应用于各种人脸识别智能场景中。 智能芯片,性能强劲 采用六核64位“服务器级”处理器RK3399,芯片性能强悍,主频高达1.8GHz,集成四核Mali-T860 GPU...

虹软ArcFace人脸识别 与 Dlib 人脸识别对比

我司最近要做和人脸识别相关的产品,原来使用的是某在线人脸识别平台,识别率和识别速度很满意,但是随着量起来的话,成本也是越来越不能接受(目前该功能我们是免费给用户使用的),而且一旦我们的设备掉线了就无法使用人脸识别功能。基于这些考虑,我司需要寻找其他的方案。 通过搜索,目前发现,开源或免费支持离线的方案也有不少。目前初步考虑虹软 ArcFace和Dlib。通...

人脸识别手机端APK分享 | 极速体验人脸识别功能 创建一个简单的人脸识别手机APP程序

1.前言 虹软公司提供免费离线人脸识别,对于开发者提供了比较友好、完整的可配置demo。但是如需直接体验功能,还是要花一点时间去完成项目编译、配置等一系列工作,对于初学者、不怎么熟悉整个项目的人来说可能会踩不少坑。 本文是基于虹软人脸识别SDK V3.0 Android Java的demo,封装后输出的一个简单的的APK程序,直接安装到手机即可体验功能,...