美文网首页程序员干货Android
用10行代码自己写个人脸识别程序

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

作者: CloudsDocker | 来源:发表于2016-11-23 21:47 被阅读18633次

    The English version of this blog at here : http://www.jianshu.com/p/cba96dad5f24

    CV (Computer Vision)

    最近在研究CV的一些开源库(OpenCV),有一个体会就是在此领域,除了一些非常学术的机器学习, 深度学习等概念外,其实还有一些很有趣的现实的应用场景。比如之前很流行的微软的 https://how-old.net, 你使用自己指定或者上传的照片进行面部识别猜年龄。 如下图所示:

    细想一下这个很吸引眼球的程序,其实技术本身打散了就包括两大块,一是从图片中扫描并进行面部识别,二是对找到的人脸根据算法去猜个年龄。大家可以猜猜实现第一个功能需要多少核心代码量?其实不用上万行,在这里我就使用短短几行代码(去除空格换行什么的,有效代码只要10行)就实现一个高大上面部识别的功能。在此文容我细述一下具体实现代码以及我对机器识别图像领域技术的理解。

    面部识别,刷脸

    人脸识别技术大家应该都不陌生,之前大家使用的数码相机,或者现在很多手机自带的相机都有人脸识别的功能。其效果就像是下图这样。近的看,剁手节刚刚过了没有多久 , 背后的马老板一直在力推的刷脸支付也是一个此领域的所谓“黑科技”。比如在德国汉诺威电子展上,马云用支付宝“刷脸”买了一套纪念邮票。人脸识别应用市场也从爆发。随后,各大互联网巨头也纷纷推出了刷脸相关的应用。

    如果要加个定义,人脸识别又叫做人像识别、面部识别,是一种通过用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部的一系列相关技术。

    我的十行代码程序

    OK,长话短说,先上 干货 ,下面就是此程序的带注释 版本,完整的程序以及相关配套文件可以在 这个github库 https://github.com/CloudsDocker/pyFacialRecognition 中找到,有兴趣可以fork 下来玩玩。下面是整个程序的代码样子,后面我会逐行去解释分析。

    就这短短的十行代码代码?seriously?“有图有真相”,我们先来看下运行的效果:

    首先是原始的图片

    运行程序后识别出面部并高亮显示的结果

    请注意 K歌二人组 的脸上的红色框框,这就是上面十行代码的成果。

    代码解析

    准备工作

    因为此程序使用是的Python,因此你需要去安装Python。这里就不赘述了。除此之外,还需要安装 OpenCV (http://opencv.org/downloads.html)。
    多说一句,这个 OpenCV正如其名,是一个开源的机器识别的深度学习框架。这是Intel(英特尔)实验室里的一个俄罗斯团队创造的,目前在开源社区非常的活跃。

    特别提一下,对于Mac的用户,推荐使用brew去安装 (下面第一条语句可能会执行报错,我当时也是搞了好久。如果遇到第一条命令不过可以通过文尾的方式联系作者)

    brew tap homebrew/science
    brew install opencv
    

    安装完成之后,在python的命令行中输入如下代码验证,如果没有报错就说明安装好了。

    >>> import cv2
    

    程序代码“庖丁解牛”

    # -*- coding: utf-8 -*-
    import cv2,sys
    
    • 由于这里注释及窗口标题中使用了中文,因此加上utf-8字符集的支持
    • 引入Opencv库以及Python的sys内建库,用于解析输入的图片参数
    inputImageFile=sys.argv[1]
    
    • 在运行程序时将需要测试的照片文件名作为一个参数传进来
    faceClassifier=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
    
    • 加载OpenCV中自带预先培训好的人脸识别层级分类器 HAAR Casscade Classifier,这个会用来对我们输入的图片进行人脸判断。

    这里有几个在深度学习及机器图像识别领域中的几个概念,稍微分析一下,至于深入的知识,大家可以自行搜索或者联系作者。

    Classifer

    在机器深度学习领域,针对识别不同物体都有不同的classifier,比如有的classifier来识别洗车,还有识别飞机的classifier,有classifier来识别照片中的笑容,眼睛等等。而我们这个例子是需要去做人脸识别,因此需要一个面部识别的classifier。

    物体识别的原理

    一般来说,比如想要机器学习着去识别“人脸”,就会使用大量的样本图片来事先培训,这些图片分为两大类,positive和negative的,也就是分为包“含有人脸”的图片和“不包含人脸”的图片,这样当使用程序去一张一张的分析这些图片,然后分析判断并对这些图片“分类” (classify),即合格的图片与不合格的图片,这也就其为什么叫做 classifier , 这样学习过程中积累的"知识",比如一些判断时的到底临界值多少才能判断是positive还是negative什么的,都会存储在一个个XML文件中,这样使用这些前人经验(这里我们使用了 哈尔 分类器)来对新的图片进行‘专家判断'分析,是否是人脸或者不是人脸。

    Cascade

    这里的 Cascade是 层级分类器 的意思。为什么要 分层 呢?刚才提到在进行机器分析照片时,其实是对整个图片从上到下,从左到右,一个像素一个像素的分析,这些分析又会涉及很多的 特征分析 ,比如对于人脸分析就包含识别眼睛,嘴巴等等,一般为了提高分析的准确度都需要有成千上万个特征,这样对于每个像素要进行成千上万的分析,对于整个图片都是百万甚至千万像素,这样总体的计算量会是个天文数字。但是,科学家很聪明,就想到分级的理念,即把这些特征分层,这样分层次去验证图片,如果前面层次的特征没有通过,对于这个图片就不用判断后面的特征了。这有点像是系统架构中的 FF (Fail Fast),这样就提高了处理的速度与效率。

    objImage=cv2.imread(inputImageFile)
    
    • 使用OpenCV库来加载我们传入的测试图片
    cvtImage=cv2.cvtColor(objImage,cv2.COLOR_BGR2GRAY)
    
    • 首先将图片进行灰度化处理,以便于进行图片分析。这种方法在图像识别领域非常常见,比如在进行验证码的机器识别时就会先灰度化,去除不相关的背景噪音图像,然后再分析每个像素,以便抽取出真实的数据。不对针对此,你就看到非常多的验证码后面特意添加了很多的噪音点,线,就是为了防止这种程序来灰度化图片进行分析破解。
    foundFaces=faceClassifier.detectMultiScale(cvtImage,scaleFactor=1.3,minNeighbors=9,minSize=(50,50),flags = cv2.cv.CV_HAAR_SCALE_IMAGE)
    
    • 执行detectMultiScale方法来识别物体,因为我们这里使用的是人脸的cascade classifier分类器,因此调用这个方法会来进行面部识别。后面这几个参数来设置进行识别时的配置,比如
    • scaleFactor: 因为在拍照,尤其现在很多都是自拍,这样照片中有的人脸大一些因为离镜头近,而有些离镜头远就会小一些,因为这个参数用于设置这个因素,如果你在使用不同的照片时如果人脸远近不同,就可以修改此参数,请注意此参数必须要大于1.0
    • minNeighbors: 因为在识别物体时是使用一个移动的小窗口来逐步判断的,这个参数就是决定是不是确定找到物体之前需要判断多少个周边的物体
    • minSize:刚才提到识别物体时是合作小窗口来逐步判断的,这个参数就是设置这个小窗口的大小
    print(" 在图片中找到了 {} 个人脸".format(len(foundFaces)))
    
    • 显示出查找到多少张人脸,需要提到的识别物体的方法返回的一个找到的物体的位置信息的列表,因此使用 len 来打印出找到了多少物体。
    for (x,y,w,h) in foundFaces:
        cv2.rectangle(objImage,(x,y),(x+w,y+h),(0,0,255),2)
    
    • 遍历发现的“人脸”,需要说明的返回的是由4部分组成的位置数据,即这个“人脸”的横轴,纵轴坐标,宽度与高度。
    • 然后使用 OpenCV 提供的方法在原始图片上画出个矩形。其中 (0,0,255) 是使用的颜色,这里使用的是R/G/B的颜色表示方法,比如 (0,0,0)表示黑色,(255,255,255)表示白色,有些网页编程经验的程序员应该不陌生。
    cv2.imshow(u'面部识别的结果已经高度框出来了。按任意键退出'.encode('gb2312'), objImage)
    cv2.waitKey(0)
    
    • 接下来是使用 opencv 提供的imshow方法来显示这个图片,其中包括我们刚刚画的红色的识别的结果
    • 最后一个语句是让用户按下键盘任意一个键来退出此图片显示窗口

    总结

    好了,上面是这个程序的详细解释以及相关的知识的讲解。其实这个只是个抛砖引玉的作用,还用非常多的应用场景,比如程序解析网页上的图片验证码,雅虎前几个月开源的 NSFW, Not Suitable for Work (NSFW),即判断那些不适合工作场所的图片,内容你懂的。 :-)

    最后,再提一下,所有这些源代码及相关文件都开源在 https://github.com/CloudsDocker/pyFacialRecognition ,在fork并下载到本地后执行下面代码来测试运行

    git clone https://github.com/CloudsDocker/pyFacialRecognition.git
    cd pyFacialRecognition
    ./run.sh
    

    如果有任何建议或者想法,请联系我。

    联系我:

    Reference

    相关文章

      网友评论

      • 首席科学家:推荐一份 python深度学习Tensorflow人工智能AI机器学习 视频教程:https://blog.csdn.net/u012201811/article/details/81184113
      • 程序猿天璇:第一条命令过不去 肿么办?
      • 72afa13b2911:人脸识别应该是比人脸检测更深入的一个概念,人脸识别需要在人脸检测出来之后跟数据库的数据进行对比以判断是否为目标人物。
      • 72afa13b2911:很厉害,举重若轻的一篇文章。正在研究人脸识别,希望跟你多学习。
      • iPM0223:您好,我将您的代码拷到pycharm上运行,编译时出现;D:\Python27\python.exe D:/pythonWorkspace/pyFacialRecognition-master/recognizeFace.py
        ImportError: numpy.core.multiarray failed to import
        Traceback (most recent call last):
        File "D:/pythonWorkspace/pyFacialRecognition-master/recognizeFace.py", line 1, in <module>
        import cv2
        ImportError: numpy.core.multiarray failed to import
        该怎么办啊?
      • 鴻佛:opencv下载好慢啊
      • af89109aefea:您好,我运行run.sh这个文件的时候一闪而过,然后用pycharm运行这个项目的时候提示:
        Traceback (most recent call last):
        File "D:/workspace/pyFacialRecognition-master/recognizeFace.py", line 3, in <module>
        objImage=cv2.imread(sys.argv[1]) # use cv2 to load image file
        IndexError: list index out of range
        请问怎么解决?
      • 6b5ccba1ffe0: 不知道为什么在我的电脑上运行识别不出人脸
        CloudsDocker:@songweinan :smile:
        6b5ccba1ffe0:配置文件没加载正确,现在OK了,谢谢分享
      • 09ad4702c096:所谓的十行代码,是建立在别人的库上面的,几乎所有的算法都别人已经实现了的。
        CloudsDocker:@xiaochun嗯确实是的,不过没必要大家都去重复发明轮子。要不然在java里来个hello world,也可以说我用110万行代码实现了个hello world!因为我用的是JDK,其包含110万行代码。:smile:
      • 8ed58f7c509f:牛B了我大python
        CloudsDocker:@互联网发烧友 :smile:
      • 夏妍妍:和你聊天我成长了许多
      • 214742ee46cf:我也在研究opencv,参数的设置还是需要大量研究积累的 :smile:
        CloudsDocker:@florets 对的,一个参数的微调往往可能导致结果巨大差别
      • 牧馬放飏:把第一张图片换掉,想必更有前途
        CloudsDocker:@Jonyker 比如换个苍老师或者网红脸肯定,哈哈
      • JianChun1:小米相机就有啊
        CloudsDocker:@leo大魔王i 对的,这些库现在都是开源的,只要手机厂商或者APP实现这个功能就行了。这里只是分享下大家自己动手实现的功能
      • starfox寒流:iOS貌似可以用 CoreImage
      • Android逍遥郎:Android有吗
        CloudsDocker:@宋巍 这个是个程序library,目前貌似移动端还没有
      • beac843a6e6b:我也是研究人脸识别方向的,OpenCV作为世界上最有名的视觉开源库确实名副其实
        CloudsDocker:@卡其色的青春 对的,这个facial recognition只是其中很小的一部分,博大精深
      • f86a35357591:学习一下🙋‍♂️
        CloudsDocker:@奋男 共同学习进步
      • ecf60266e994:学习了
        CloudsDocker:@一只安静的美男子 :blush:

      本文标题:用10行代码自己写个人脸识别程序

      本文链接:https://www.haomeiwen.com/subject/jpnvpttx.html