用10行代码自己写个人脸识别程序

lynnvip 8年前
   <h2>CV (Computer Vision)</h2>    <p>最近在研究CV的一些开源库(OpenCV),有一个体会就是在此领域,除了一些非常学术的 <em>机器学习</em> , <em>深度学习</em> 等概念外,其实还有一些很有趣的 <em>现实的</em> 应用场景。比如之前很流行的微软的 <a href="/misc/goto?guid=4959741395884755639" rel="nofollow,noindex">https://how-old.net</a> , 你使用自己指定或者上传的照片进行面部识别 <em>猜年龄</em> 。 如下图所示:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/68a62489dde254d67125b4f456bb4239.jpg"></p>    <p>细想一下这个很吸引眼球的程序,其实技术本身打散了就包括两大块,一是从图片中扫描并进行面部识别,二是对找到的人脸根据算法去猜个年龄。大家可以猜猜实现第一个功能需要多少核心代码量?其实不用</p>    <p>上万行 ,在这里我就使用短短 <strong>几行代码</strong> (去除空格换行什么的,有效代码只要10行)就实现一个 <em>高大上</em></p>    <p>面部识别的功能。在此文容我细述一下具体实现代码以及我对机器识别图像领域技术的理解。</p>    <h3>面部识别,刷脸</h3>    <p><em>人脸识别</em> 技术大家应该都不陌生,之前大家使用的数码相机,或者现在很多手机自带的相机都有人脸识别的功能。其效果就像是下图这样。近的看, <em>剁手节</em> 刚刚过了没有多久 , 背后的马老板一直在力推的刷脸支付也是一个此领域的所谓“黑科技”。比如在德国汉诺威电子展上,马云用支付宝“刷脸”买了一套纪念邮票。人脸识别应用市场也从爆发。随后,各大互联网巨头也纷纷推出了刷脸相关的应用。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/33b9b3ab60c05126401a3565df87bf19.jpg"></p>    <p>如果要加个定义,人脸识别又叫做人像识别、面部识别,是一种通过用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部的一系列相关技术。</p>    <h2>我的十行代码程序</h2>    <p>OK,长话短说,先上 <em>干货</em> ,下面就是此程序的 <em>带注释</em> 版本,完整的程序以及相关配套文件可以在 <a href="/misc/goto?guid=4959741395970220866" rel="nofollow,noindex">这个github库</a> <a href="/misc/goto?guid=4959741395970220866" rel="nofollow,noindex">https://github.com/CloudsDocker/pyFacialRecognition</a> 中找到,有兴趣可以 <em>fork</em> 下来玩玩。下面是整个程序的代码样子,后面我会逐行去解释分析。</p>    <p><img src="https://simg.open-open.com/show/f8a5a14e5173587c60acb52ca6a6ea0b.png"></p>    <p>就这短短的十行代码代码?seriously?“有图有真相”,我们先来看下运行的效果:</p>    <h3>首先是原始的图片</h3>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/50778ef6affb1165ee9925613511f63f.jpg"></p>    <h3>运行程序后识别出面部并高亮显示的结果</h3>    <p>请注意 <em>K歌二人组</em> 的脸上的红色框框,这就是上面十行代码的成果。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2071f190fc9621e3120d937120160ee6.png"></p>    <h2>代码解析</h2>    <h3>准备工作</h3>    <p>因为此程序使用是的Python,因此你需要去安装Python。这里就不赘述了。除此之外,还需要安装 <a href="/misc/goto?guid=4959548929948439278" rel="nofollow,noindex">OpenCV</a> ( <a href="/misc/goto?guid=4959741396096905150" rel="nofollow,noindex">http://opencv.org/downloads.html)。</a></p>    <p>多说一句,这个 OpenCV正如其名,是一个开源的机器识别的深度学习框架。这是Intel(英特尔)实验室里的一个俄罗斯团队创造的,目前在开源社区非常的活跃。</p>    <p>特别提一下,对于Mac的用户,推荐使用brew去安装 (下面第一条语句可能会执行报错,我当时也是搞了好久。如果遇到第一条命令不过可以通过文尾的方式联系作者)</p>    <pre>  brew tap homebrew/science  brew install opencv</pre>    <p>安装完成之后,在python的命令行中输入如下代码验证,如果没有报错就说明安装好了。</p>    <pre>  >>> import cv2</pre>    <h3>程序代码“庖丁解牛”</h3>    <pre>  # -*- coding: utf-8 -*-  import cv2,sys</pre>    <ul>     <li>由于这里注释及窗口标题中使用了中文,因此加上utf-8字符集的支持</li>     <li>引入Opencv库以及Python的sys内建库,用于解析输入的图片参数</li>    </ul>    <pre>  inputImageFile=sys.argv[1]</pre>    <ul>     <li>在运行程序时将需要测试的照片文件名作为一个参数传进来</li>    </ul>    <pre>  faceClassifier=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')</pre>    <ul>     <li>加载OpenCV中自带预先培训好的人脸识别层级分类器 HAAR Casscade Classifier,这个会用来对我们输入的图片进行人脸判断。</li>    </ul>    <p>这里有几个在深度学习及机器图像识别领域中的几个概念,稍微分析一下,至于深入的知识,大家可以自行搜索或者联系作者。</p>    <h3>Classifer</h3>    <p>在机器深度学习领域,针对识别不同物体都有不同的classifier,比如有的classifier来识别洗车,还有识别飞机的classifier,有classifier来识别照片中的笑容,眼睛等等。而我们这个例子是需要去做人脸识别,因此需要一个面部识别的classifier。</p>    <h3>物体识别的原理</h3>    <p>一般来说,比如想要机器学习着去识别“人脸”,就会使用大量的样本图片来事先培训,这些图片分为两大类,positive和negative的,也就是分为包“含有人脸”的图片和“不包含人脸”的图片,这样当使用程序去一张一张的分析这些图片,然后分析判断并对这些图片“分类” (classify),即合格的图片与不合格的图片,这也就其为什么叫做 <em>classifier</em> , 这样学习过程中积累的"知识",比如一些判断时的到底临界值多少才能判断是positive还是negative什么的,都会存储在一个个XML文件中,这样使用这些前人经验(这里我们使用了 <em>哈尔</em> 分类器)来对新的图片进行‘专家判断'分析,是否是人脸或者不是人脸。</p>    <h3>Cascade</h3>    <p>这里的 Cascade是 <em>层级分类器</em> 的意思。为什么要 <em>分层</em> 呢?刚才提到在进行机器分析照片时,其实是对整个图片从上到下,从左到右,一个像素一个像素的分析,这些分析又会涉及很多的 <em>特征分析</em> ,比如对于人脸分析就包含识别眼睛,嘴巴等等,一般为了提高分析的准确度都需要有成千上万个特征,这样对于每个像素要进行成千上万的分析,对于整个图片都是百万甚至千万像素,这样总体的计算量会是个天文数字。但是,科学家很聪明,就想到分级的理念,即把这些特征分层,这样分层次去验证图片,如果前面层次的特征没有通过,对于这个图片就不用判断后面的特征了。这有点像是系统架构中的 <em>FF (Fail Fast)</em> ,这样就提高了处理的速度与效率。</p>    <pre>  objImage=cv2.imread(inputImageFile)</pre>    <ul>     <li>使用OpenCV库来加载我们传入的测试图片</li>    </ul>    <pre>  cvtImage=cv2.cvtColor(objImage,cv2.COLOR_BGR2GRAY)</pre>    <ul>     <li>首先将图片进行灰度化处理,以便于进行图片分析。这种方法在图像识别领域非常常见,比如在进行验证码的机器识别时就会先灰度化,去除不相关的背景噪音图像,然后再分析每个像素,以便抽取出真实的数据。不对针对此,你就看到非常多的验证码后面特意添加了很多的噪音点,线,就是为了防止这种程序来灰度化图片进行分析破解。</li>    </ul>    <pre>  foundFaces=faceClassifier.detectMultiScale(cvtImage,scaleFactor=1.3,minNeighbors=9,minSize=(50,50),flags = cv2.cv.CV_HAAR_SCALE_IMAGE)</pre>    <ul>     <li>执行detectMultiScale方法来识别物体,因为我们这里使用的是人脸的cascade classifier分类器,因此调用这个方法会来进行面部识别。后面这几个参数来设置进行识别时的配置,比如      <ul>       <li>scaleFactor: 因为在拍照,尤其现在很多都是自拍,这样照片中有的人脸大一些因为离镜头近,而有些离镜头远就会小一些,因为这个参数用于设置这个因素,如果你在使用不同的照片时如果人脸远近不同,就可以修改此参数,请注意此参数必须要大于1.0</li>       <li>minNeighbors: 因为在识别物体时是使用一个移动的小窗口来逐步判断的,这个参数就是决定是不是确定找到物体之前需要判断多少个周边的物体</li>       <li>minSize:刚才提到识别物体时是合作小窗口来逐步判断的,这个参数就是设置这个小窗口的大小</li>      </ul> </li>    </ul>    <pre>  print(" 在图片中找到了 {} 个人脸".format(len(foundFaces)))</pre>    <ul>     <li>显示出查找到多少张人脸,需要提到的识别物体的方法返回的一个找到的物体的位置信息的列表,因此使用 <em>len</em> 来打印出找到了多少物体。</li>    </ul>    <pre>  for (x,y,w,h) in foundFaces:      cv2.rectangle(objImage,(x,y),(x+w,y+h),(0,0,255),2)</pre>    <ul>     <li>遍历发现的“人脸”,需要说明的返回的是由4部分组成的位置数据,即这个“人脸”的横轴,纵轴坐标,宽度与高度。</li>     <li>然后使用 <em>OpenCV</em> 提供的方法在原始图片上画出个矩形。其中 <em>(0,0,255)</em> 是使用的颜色,这里使用的是R/G/B的颜色表示方法,比如 (0,0,0)表示黑色,(255,255,255)表示白色,有些网页编程经验的程序员应该不陌生。</li>    </ul>    <pre>  cv2.imshow(u'面部识别的结果已经高度框出来了。按任意键退出'.encode('gb2312'), objImage)  cv2.waitKey(0)</pre>    <ul>     <li>接下来是使用 <em>opencv</em> 提供的imshow方法来显示这个图片,其中包括我们刚刚画的红色的识别的结果</li>     <li>最后一个语句是让用户按下键盘任意一个键来退出此图片显示窗口</li>    </ul>    <h2>总结</h2>    <p>好了,上面是这个程序的详细解释以及相关的知识的讲解。其实这个只是个 <em>抛砖引玉</em> 的作用,还用非常多的应用场景,比如程序解析网页上的图片验证码,雅虎前几个月开源的 <a href="/misc/goto?guid=4959741396181138020" rel="nofollow,noindex">NSFW</a> , Not Suitable for Work (NSFW),即判断那些不适合工作场所的图片,内容你懂的。 :-)</p>    <p> </p>    <pre>  git clone https://github.com/CloudsDocker/pyFacialRecognition.git  cd pyFacialRecognition  ./run.sh</pre>    <h2>Reference</h2>    <ul>     <li><a href="/misc/goto?guid=4959741396254820897" rel="nofollow,noindex">OpenCV</a></li>     <li> <p><a href="/misc/goto?guid=4959741396354041278" rel="nofollow,noindex">HAAR 哈尔特征</a></p> </li>     <li> <p><a href="/misc/goto?guid=4959741396423751647" rel="nofollow,noindex">Face Detection using Haar Cascades</a></p> </li>     <li><a href="/misc/goto?guid=4959741396181138020" rel="nofollow,noindex">NSFW</a></li>    </ul>    <p> </p>    <p>来自:http://www.jianshu.com/p/9aef6f4db349</p>    <p> </p>