javaee论坛

普通会员

225648

帖子

334

回复

348

积分

楼主
发表于 2017-09-30 11:49:06 | 查看: 2247 | 回复: 1
本文由:姚磊岳(leiyue_yao@163.com)于2016-6-9撰,转载请保留作者信息。

  最近需要实现一个基于生理特征的门禁准入系统,其中一个环节就是要用到人脸识别。虽说人脸识别的算法已经非常成熟,网络上也有很多专业的介绍,但从零做起工作量还是太大,所以想找一些现成的控件。上网一搜,还真发现了不少:如果是基于移动端的Android开发,科大讯飞的人脸识别插件应该是个不错的选择;百度也提供人脸识别的插件(没深入看,不知道要不要收费)。对比再三,发现如果是要做C/S程序,精度又不是要求非常高非常高的话,开源的Emgu.CV是最好的选择。但比较无语的是Emgu.CV各版本之间的函数变化较大,目前网上的案例资料基本都是v2.4版本的,最新版V3.1版本的资料可谓少之又少。经过4天的摸索,终于比较完美地实现了人脸识别并对部分方法进行了封装。中间过程由于缺乏相关资料,非常痛苦,所以感觉非常有必要写一篇技术文章。

一、准备工作
1、 摄像头
2、 下载最新版Emgu.CV(http://sourceforge.net/projects/emgucv/files/),我下载的是V3.1版本的,这里一定要注意,不同版本的Emgu.CV某些函数用法相差会比较大。当然熟悉后自然会发现大同小异,但在初用的时候还是比较痛苦的。
3、 安装(安装是傻瓜式的,一路下一步即可),安装完毕后需要通过“我的电脑à属性à高级系统设置à环境变量à系统环境变量”找到“Path”,点击编辑,在最后面增加EMGU的bin目录路径,我的是:C:\Emgu\emgucv-windesktop 3.1.0.2282\bin(你安装在哪个目录,就增加这个目录下bin的路径)
4、 Copy必要的dll至程序运行目录(就是你程序编译后的那个Debug目录)。如图所示:
图片
这些文件都在C:\Emgu\emgucv-windesktop 3.1.0.2282\bin目录下面,其中:x86文件夹是做32位系统时要拷贝的,如果需要做64位的,那就拷贝x64这个目录即可。
5、 在项目工程下引用Emgu.CV和Emgu.CV.word

6、 在工具栏添加Emgu.CV.UI.dll

这时,工具栏会出现4个控件,其中我们这是要用的是“ImageBox”

7、 在Debug目录下建一个文件夹“trainedFaces”。名字可以根据自己喜好,用来存放人脸样本。

至此,准备工作完毕!我的Debug目录下的文件清单如下:

二、界面设计
这个比较简单,拖控件就可以,我的界面如下:
图片
三、代码设计
首先,为方便程序实现,自定义几个必要的类

这个类是用来存放所有人脸样本的,和Emgu.CV v1.0版本不同,从V2.4版本开始,进行样本训练后,得到的不再是直接的名字,而是返回一个识别后的人脸顺号。

这个类主要是用来存放训练好的人脸识别器,我是为了方便将样本文件打包在一起了。

这个类用来存放识别后相关信息,包括:originalImg(原始图片),facesRectangle(识别后的人脸矩形框,包括坐标和大小),names(识别出来的人的姓名)

这是一个枚举,Emgu.CV从v2.4版本开始,为人脸识别器提供了三种实现类型,我这里为少打字,定义了个枚举。待会用switch case的时候可以看到。仅此而已。

其次,创建识别类及方法
1、 Using必要的类

2、 几个重要类型和方法的介绍

获取指定目录下所有的样本文件,并添加到之前自定义的TrainedFileList类。

根据人脸识别器的类型进行不同的参数设定,并进行训练。Emgu.CV中的faceRecognizer为抽象类,提供了三种具体的实现方式,分别为:EigenFaceRecognizer、FisherFaceRecognizer、LBPHFaceRecognizer,V2.4版本中默认为EigenFaceRecognizer,但在最新的V3.1版本中,是必须制定具体类实现的。(没有深入研究Emgu.CV的源代码,但应该用的是抽象方法工厂模式)。

每个类的初始化值,是从网上找的建议值,如果有兴趣可以自己标定,重新设置。

此方法用来将特定图片中的人脸识别出来,过程很简单:
1)灰度化图片
这里切记要将灰度化后的图片EqualizeHist(灰度均衡化),否则会出现问题。其中:faceClassifier是Emgu.CV提供的名为:CascadeClassifier的人脸检测类,在类创建的时候,我初始化了(源代码文后附上,一看就明白)。这里值得注意的是CascadeClassifier好像是在V3.1版本中提供的,之前的版本貌似有类似的类,具体名字不记得了。
2)通过CascadeClassifier检测人脸
这里仅仅是检测到人脸,具体这个人叫什么还是不知道的。检测后,返回的是一个Rectangle类型的数组。

关键的人脸识别程序,其实也就是用到了Emgu.CV.Face.FaceRecognizer.PredictionResult,这个类的用法和V2.4版本有一个比较大的方法名变化,v2.4版本中不是叫predict,而是叫recognise。返回值也不同,v2.4版本是直接返回名称,而v3.1版本返回的是样本人脸在list中的顺号。
至于怎么在图片上画出姓名,直接看代码即可,此处不再赘述。
最后,程序实现
代码封装好后,实现起来就非常方便了。总共代码157行,呵呵~~也就是说157行代码就可以实现人脸识别程序了:)
几个关键的代码段如下:

Capture是Emgu.CV提供的摄像头控制类,里面的ImageGrabbed事件表示的是获取到图片后触发。可以用来实现模拟摄像头视频获取(其实是在picturebox中显示图片,由于很快,就跟视频一样)
Capture另一个非常关键的方法是QueryFrame()这个方法是用来获取当前的摄像头捕捉到的图面。

特别注意:样本图片的大小一定要和比对图片的大小一致,否则程序不会报错,但会卡死。这个问题在我初做的时候让我几乎抓狂。后来灵感突发,直觉可能是图片大小不一致的问题,结果一试还真是!这里要鄙视下Emgu.CV,好歹也抛出个异常啊。
我的程序中采用的是100*100像素。不宜过大,否则影响程序效率。

由于文档不全,参考了很多其他版本的代码,因为各版本之间的函数、类型相差又比较大,中间过程相当痛苦。上述总结,应该算是最新v3.1版本的第一篇中文文档了。看在辛苦写文档的份上,大家在转载的时候记得保留作者信息:)最后祝愿各位猿门2016端午节快乐。源代码和效果如下:

源代码及可执行文件:http://download.csdn.NET/detail/u011616825/9545230
DEBUG下的文件可以COPY出来先执行,里面有必要的DLL,避免直接打开工程编译后被删除。


普通会员

0

帖子

323

回复

349

积分
沙发
发表于 2023-05-18 07:06:02

这个方法是用来幸运飞艇直播福彩双色球结果幸运时时彩走势图获取当前的摄像头捕捉到的图面

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017