C#人脸识别入门篇(Step by step 人脸识别)

C#人脸识别入门篇-Step ByStep人脸识别

引言

如今,基于人脸的技术和话题可以说是炙手可热,基于大数据和人工智能的人脸识别更是突破了我们的想象力的极限,如果应用中不能集成人脸识别,那就太跟不上潮流了。人脸识别是一个算法密集型的项目,如果自行开发,需要很深厚的数学功底和算法底蕴,成本较高,我一个做C#的,自问没有那么高的水平能够写出那么复杂的算法,即使能,我们的算法能和其它公司相比吗。不过好在现在是一个互联网时代,自己开发不行,那么使用其它现成的人脸识别引擎可行吗?答案当然是可行的。

本系列文章就将先从静态图片的人脸检测开始,逐步讲解C#是如何进行人脸识别的。共分为以下四篇

1.人脸识别入门—静态照片人脸检测

2.人脸识别入门—基于视频的人脸检测

3.人脸识别入门—人脸识别初应用

4.人脸识别入门—模拟简单的门禁系统应用

在开始之前,我们先来了解一些人脸识别的集成方式和基础知识,为下面的课程做准备。

选择人脸识别引擎的心路历程

通过搜索引擎,可以大致确定集成人脸识别的可选方式有以下几种

1. 集成WebAPI

目前以百度云,腾讯云为首的互联网公司提供了基于WEBAPI的集成方式,可以通过HTTP的方式提交识别请求,识别结果通过JSON串的方式返回。基于HTTP的方式识别人脸是比较慢的,慢的原因在于IO性能,相对来讲,离线版本的API则能够充分利用本机的机器资源,不用往返于所谓的算法云服务器,直接在本地就能完成人脸识别和标记工作。

2. 集成SDK

另一种是基于SDK的本地识别方式。本地识别的优点是速度快,集成度高。而且,作为C#,我们还可以搭建自己的云识别平台。 本人也尝试过主流开源的人脸识别SDK、如OpenCV、Dlib、Seetaface等等,但经过试用,都不太理想。最近在今日头条上看到有个商业公司免费提供人脸识别SDK,就想着去下载尝试试用一下。

下载引擎发现只C++

想到就要做到,于是赶紧打开电脑下载了SDK,吐槽下今日头条,做新闻不放链接太不厚道了。只能百度了,链接在这里http://www.arcsoft.com.cn/ai/arcface.html

下载后,发现SDK包括了人脸识别,人脸检测,人脸跟踪所有的API。不过美中不足的是,这SDK竟然只有C++版本的,Windows版本不出C#,这虹软有点不近人情啊。不过伤心归伤心,活还得做,没有C#,那我们就拿C++的包裹出C#来用。其实有了C++就等于有了C#,因为C#本身是兼容C++的,可以直接调用C++的库。

基础概念讲解

如何使用C#调用C++的库呢,C#提供了两种技术调用C++的DLL,静态调用(DCOM+)和动态调用(P/Invoke)。

第一种是我们可以将C或者C++的函数封装成COM组件,在C#中调用时比较方便,但是COM组件需要注册,而且多次注册可能也会导致一些问题,同时在处理C或者C++的类型与COM组件的类型转换的时候也可能有些麻烦

第二种采用动态的方式就是直接用C#调用C或者C++已经写好的动态链接库

这两种方式相对而言,P/Invoke要方便一些。

P/Invoke是什么?

  P/Invoke的全称是Platform Invoke (平台调用) 它实际上是一种函数调用机制,通过P/Invoke我们就可以调用非托管DLL中的函数 ,实际上很多NET基类库中定义的类 型内部部调用了从Kernel32.dll,User32.dll,gdi32.dll等非托管DLL中导出的函数。

看一个最简单的例子

  [DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")]

  [return: MarshalAsAttribute(UnmanagedType.Bool)]  //可写可不写,定义如何封送返回参数

  public static extern bool SetCursorPos(intX, int Y);

3) P/Invoke的过程

关于P/Invoke的过程,我找到了MSDN上的一张图,如下所示。

在使用P/Invoke调用C/C++方法时,会依次执行以下操作

1 查找包含该函数的非托管DLL

2 将该非托管DLL加载到内存中

3 查找函数在内存中的地址并将其参数按照函数的调用约定压栈  

4 将控制权转移给非托管函数

注意:只在第一次调用函数时,才会查找和加载非托管DLL并查找函数在内存中的地址。当非托管函数产生异常时,P/Invoke会将异常传递给托管调用方

看起来很复杂,但使用起来却很简单,只需要在C#中重新声明函数的定义就可以了,然后可以像其它函数一样调用。

但是,这里面最棘手的问题是处理要调用函数的签名,还有最难处理的指针和内存问题。我们需要根据SDK的提供方的函数说明来定义函数的签名。C#的自动内存管理机制让我们几乎忘记了C++中很司空见惯的琐碎细节,如果你以前没有玩过P/Invoke,也没有关系,我会给大家尽可能的讲解这里面需要注意的细节。

人脸识别入门—静态照片人脸检测

现在开始我们的项目,基于静态照片的人脸检测。我们希望我们的程序能够打开一张照片,告诉我们这张照片中是否有人脸,如果有,就需要识别并显示出来,如果没有,就提示照片中没有人脸。

我们的项目使用WinForm,C#版本采用的是4.0版本,IDE我使用的是VS2013的英文版。

建立项目

这一步比较简单,我们使用WinFrom的项目,我们使用.net 2.0或者4.0都可以,直接下一步就可以搞定。

上图中的AFD和dll文件夹我们后面就会用到,刚建项目时是没有这两个文件夹的。

建立视图

通过设计器和工具箱,我们可以建立我们的视图界面,包括一个按钮两个PictureBox.

大的那个我们用来显示完整的图片,小的用来显示识别到的人脸信息。

我们把大PicturesBox的那个命名为pictureBox1,小的命名为pictureBox2,然后设置两个的SizeMode均为Zoom, 以方便我们自动显示照片。

 

加载DLL

好了,如果刚才你还没有下载需要用的到SDK,那么在接下来之前,你需要下载它了。访问http://www.arcsoft.com.cn/ai/arcface.html。在这个页面找到

我们下载Windows版本的。接下来会要求你登录,注册,选择行业blabla~~.一切结束后,会告诉你申请成功,并且给出下载链接和SDK的Key。

请确保牢记这些Key,因为接下来的程序中你将需要这些Key,如果忘记了,就登录刚才的那个地址,在用户中心里面可以看到这些Key,当然,你也可以在邮件中查找。BTW,现在我们打开下载的包。

使用解压工具打开后,我们可以看到三个包。

我们选择Face_Detection这个包,解压之。

这里面的文件夹对我们比较重要。首先,我们需要把lib拖到我们的项目中。然后在选中这个dll文件,在属性设置中我们把它设置为始终拷贝。

由于我们的SDK是32位版本的,因此我们需要设置编译版本为x86

至此,创建项目工作正式完成。

一步一步,根据人脸识别的SDK代码示例来完善项目

现在我们回到上一章节的四个文件夹,我们打开doc文件夹。这里面的pdf文件是我们接下来课程的基础。通读一遍,发现4个函数,3个结构体,然后2个枚举,两个变量类型,还有一段示例代码。我们来一步步定义它们

基本类型

C/C++ 可以定义自己的类型,打开SDK文档可以发现,这里面几乎没有我们熟悉的int,long,char*这些类型,取而代之是的Mint以及一些其它AFD开头的类型,SDK文档开篇引入了两个基础类型。

typedef MInt32AFD_FSDK_OrientPriority;

typedef MInt32AFD_FSDK_OrientCode;

所有基本类型在平台库中有定义。定义规则是在ANSIC 中的基本类型前加上字母“M”同时将类型的第一个字母改成大写。例如“long” 被定义成“MLong”

这段比较明朗了,就是说凡是下面遇到AFD_FSDK_OrientPriority就认为是Mint32,对应C#就是int,全部的定义在inc文件夹afdcommdef.h头文件中

定义结构体。

由于C并不是面向对象的语言,结构体作为可以自定义的类型,在一定程度的代替了我们C#中的类和对象,我们来一步步定义这些结构体。

AFD_FSDK_FACERES

这个结构体是用来存储脸部信息的,我们可以从文档中得到它的定义如下:

typedefstruct{

MRECT * rcFace;

MLong nFace;

AFD_FSDK_OrientCode * lfaceOrient;

}AFD_FSDK_FACERES, * LPAFD_FSDK_FACERES;

根据我们上一节中的内容,可以知道这个MLong类似于long,rcFace和lfaceOrient则是两个指针。那么在C#中如何使用指针呢,直接用unsafe code肯定是可以的,不过这里我们使用IntPtr.

我们来看一下有关IntPtr的简介

IntPtr用于表示指针或句柄的平台特定类型。这个其实说出了这样两个事实,IntPtr 可以用来表示指针或句柄、它是一个平台特定类型,它主要用在两个地方:

(1)C#调用WIN32 API时

(2)C#调用C/C++写的DLL时(其实和1相同,只是这个一般是我们在和他人合作开发时经常用到)

我们可以这样子理解,IntPtr就可以互换C++中的指针。因此我们转换后的C#格式为:

我们根据刚才所说的定义规则,换算成C#语言的定义如下:

类功能:定义检测到的脸部信息结构体

 public struct AFD_FSDK_FACERES

{

public int nFace;

public IntPtrrcFace;

public IntPtrlfaceOrient;

}

注意:nface虽然C++中是long,但对应到C#中可不long,而是int.在32位程序中int和long占用的内存大小都是4Byte=32bit,其表示的大小都是:-2147483648~2147483647。

MRECT

我们继续关注rcFace,首先注意到MRECT,这个类型在文档中没有。但它确实是一个自定义类型。

我们在inc文件下面的amcomdef.h下面找到了它的定义。

typedef struct__tag_rect

{

    MInt32 left;

    MInt32 top;

    MInt32 right;

    MInt32 bottom;

} MRECT,*PMRECT;

我们先来定义这个MRECT类型,这个类型比较简单,C#版定义如下:

public struct MRECT

    {

        public int left;

       

  • 8
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
一、主要内容:OpenCV能够实现强大丰富的图像处理,但是它缺少一个能够支持它运行的界面。Csharp经过多年的发展,得益于它的“所见及所得”能力,非常方便编写界面。这两者如果能够“双剑合璧”,将有效帮助实际工作产出。本课着重推荐GOCW采用“Csharp基于CLR直接调用Opencv编写的算法库”方法,能够将最新的OpenCV技术引入进来,同时保证生成程序的最小化。    为了进一步说明Csharp和OpenCV的结合使用,首先一个较为完整的基于winform实现答题卡识别的例子,相比较之前的实现,本次进一步贴近生产实际、内涵丰富,对算法也进行了进一步提炼。同时我们对WPF下对OpenCV函数的调用、OpenCV.js的调用进行相关教授。       二、课程结构1、 EmguCV、OpenCVSharp和GOCW之间进行比较(方便代码编写、能够融入最新的算法、速度有保障、方便调试找错、拒绝黑箱化);2、视频采集模块的构建,视频采集和图像处理之间的关系;3、视频采集专用的SDK和“陪练”系统的介绍;4、在视频增强类项目中和图像处理项目中,算法的选择;5、Csharp界面设计、图片的存储和其他构建设计;6、较为完整的答题卡识别例子,兼顾界面设计和算法分析;8、WPF基于GOCW也同样可以基于GOCW实现算法调用;webForm虽然也可以通过类似方法调用,但是OpenCV.JS的方法更现代高效。9、关于软件部署的相关要点和窍门。       三、知识要点:1、基本环境构建和程序框架;2、CLR基本原理和应用方法;3、接入、采集、模拟输入;4、图像处理,通过构建循环采集图片;5、增强和实时处理;6、基于投影等技术的答题卡识别算法;7、存储、转换;8、部署交付。        课程能够帮助你掌握Csharp调用Opencv的基本方法,获得相应框架代码和指导;从而进一步提升实现“基于图像处理”的解决方案能力。  

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值