OpenCV人脸识别之一:数据收集和预处理

本系列人脸识别文章用的是opencv2,最新版的opencv3.2的代码请参考文章:

《OpenCV之识别自己的脸——C++源码放送》;

《人脸识别源码运行指南》(小编附在文末)

前段时间对人脸检测进行了一些尝试:人脸检测(C++/Python)(http://www.jianshu.com/p/504c081d7397)但是检测和识别是不同的,检测解决的问题是图片中有没有人脸;而识别解决的问题是,如果一张图片中有人脸,这是谁的脸。人脸检测可以利用opencv自带的分类器,但是人脸识别就需要自己收集数据,自己训练分类器了。opencv给出的有人脸识别的教程:Face Recognition with OpenCV(https://docs.opencv.org/2.4/modules/contrib/doc/facerec/facerec_tutorial.html)。网上也可以找到中文版本的。

正所谓自己动手丰衣足食。站在巨人的肩膀上,参考前辈们的经验,终于能够识别出自己了。由于感觉内容较多,而且没有时间一次性写完,所以准备分阶段来写。每一篇博客是一个阶段的工作。初步设想分为数据收集和预处理、训练模型和人脸识别三个部分。今天先写第一部分。

1、背景数据集

本次用的数据集市opencv给出的教程里面的第一个数据集:The AT&T Facedatabase(http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html)。又称ORL人脸数据库,40个人,每人10张照片。照片在不同时间、不同光照、不同表情(睁眼闭眼、笑或者不笑)、不同人脸细节(戴眼镜或者不戴眼镜)下采集。所有的图像都在一个黑暗均匀的背景下采集的,正面竖直人脸(有些有有轻微旋转)。

下载下来之后是这样的:

可以看到每个人一个文件夹,每个文件夹下是这个人的十张照片,但是不是我们熟悉的BMP或者是PNG或者是JPEG格式的,而是PGM格式的。windows7自带的照片查看器和画图软件都不能打开这种格式的图片。

不过好在我昨天刚对imread()函数研究过:使用imread()函数读取图片的六种正确姿势。所以记得opencv文档里有这样的描述:

imread()还是很强大的,所以写个程序看看那这些人是什么样吧。

2、自己的人脸数据集

1、拍照程序

想要识别自己,单有别人的数据集还是不行的,还需要自己人脸的照片才行。这就需要我们收集自己的照片,然后和上面的那个数据集一起来训练模型。在拿着手机自拍的过程中我想到,问什么不写一个程序用电脑的摄像头自拍呢,随便还能研究下怎么用opencv实现拍照的功能。经过一番实验(其实还是费了好长时间),终于写了一个拍照程序。

程序的功能就是打开电脑摄像头,当P键按下(P是拍照的首字母?还是Photo的首字母?还是Picture的首字母?)的时候,保存当前帧的图像。简单到没朋友(竟然耗费了那么久!)。

while (1)        
 {             
char key = waitKey(100);             
cap >> frame;             
imshow("frame", frame);             
string filename = format("D:\\pic\\pic%d.jpg", i);              
switch (key)            
 {             
case'p':                 
i++;                 
imwrite(filename, frame);                 
imshow("photo", frame);                
 waitKey(500);                
 destroyWindow("photo");                
 break;             
default:                 
break;            
 }
    }

然后我们就可以运行程序,不停地按下p键对自己一通狂拍了。

2、预处理

在得到自己的人脸照片之后,还需要对这些照片进行一些预处理才能拿去训练模型。所谓预处理,其实就是检测并分割出人脸,并改变人脸的大小与下载的数据集中图片大小一致。

人脸检测在之前的博客中已经做了介绍,这里就不再赘述。详情参考:OpenCV人脸检测(C++/Python)(http://www.jianshu.com/p/504c081d7397)。用ROI分割即可。

检测出人脸之后改变大小使之与ORL人脸数据库人脸大小一致。通过加断点在Locals里面或者是ImageWatch可以看到ORL人脸数据库人脸的大小是92 x 112。

这里只需要对检测后得到的ROI做一次resize即可。

这两步的代码如下:

  std::vector<Rect> faces;             
Mat img_gray;              
cvtColor(img, img_gray, COLOR_BGR2GRAY);             
equalizeHist(img_gray, img_gray);              
//-- Detect faces             
face_cascade.detectMultiScale(img_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, Size(50, 50));              
for (size_t j = 0; j < faces.size(); j++)            
 {                 
Mat faceROI = img(faces[j]);                
 Mat MyFace;                
 if (faceROI.cols > 100)                 
{                     
resize(faceROI, MyFace, Size(92, 112));                    
 string  str = format("D:\\MyFaces\\MyFcae%d.jpg", i);                     
imwrite(str, MyFace);                     
imshow("ii", MyFace);                
 }                 
waitKey(10);

}

至此,我们就得到和ORL人脸数据库人脸大小一致的自己的人脸数据集。然后我们把自己的作为第41个人,在我们下载的人脸文件夹下建立一个s41的子文件夹,把自己的人脸数据放进去。就成了这样下面这样,最后一个文件夹里面是我自己的头像照片:

最后那个at.txt放到下一次再说,训练模型就靠它了。

这里有一点值得注意:我这里保存的图像格式是.jpg的,而不是跟原数据集一样是.pgm的。经测试仍然可以训练出可以正确识别我自己人脸的模型来。但是如果大小不一致会报错。

OpenCV之识别自己的脸——C++源码放送

前言

在将近一年之前,我在CSDN专栏《OpenCV实践之路》中连续发了三篇博客,完整地描述了基于OpenCV进行人脸识别的全过程。三篇都将近一万的阅读量和大量的评论的表明,人脸识别果然是大家在学习OpenCV过程中最感兴趣的课题,之一。当然,也有可能是本科生毕设老师最感兴趣的课题之一。

由于当时写的时候是按照前后流程来的,所以源码比较分散。加之我想当然地认为,很多源码是之前博客中已经放出来的,可以一句带过。这导致了很多同学学习的时候很不方面。但是我由于重装系统,导致当初的源码遗失,也一直没有抽出时间去重新整理一下。这个清明节,没有出门,根据之前的博客基于当下最新的OpenCV3.2重新整理了一遍源码。现在放出来,以飨读者。

小小的区别

当然了,重新整理也不是简单的把源码收集到一起,如果真的那么简单,也就不用去整理了,大家自行收集即可。因为OpenCV3.2人脸识别的内容也是有些小变动。所以现在的代码跟原来的三篇博客仍然是统一的,但是有一些细节不同。

1、自动拍照

之前采集自己的图像的时候,程序设定是运行之后按’p’键拍照并保存图像,然后需要自己手动的去把图像大小转化为跟ORL人脸数据库中的图片大小一样。

现在一切自动,只需要运行即可拍照,变化尺寸,并保存。默认设定拍10张照片,与ORL人脸数据库一致。

2、Python脚本生成at.txt

当时写博客的时候还不会用Python,所以生成的at.txt并不是s1文件夹对应的label就是1,s2就对应2。而是比较混乱的。谁是谁需要自己去记忆。

经过修改后的Python脚本可以是文件夹可label完美对应起来了。

3、训练代码

训练人脸识别模型的代码部分有些改动,主要是因为OpenCV的变动。

头文件和命名空间需要各加一句:

#include<opencv2\face.hpp>
using namespace cv::face;

创建模型部分的改变,原来的代码是

Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
Ptr<FaceRecognizer> model1 = createFisherFaceRecognizer();
Ptr<FaceRecognizer> model2 = createLBPHFaceRecognizer();

现在改为:

Ptr<BasicFaceRecognizer> model = createEigenFaceRecognizer(); 
Ptr<BasicFaceRecognizer> model1 = createFisherFaceRecognizer(); 
Ptr<LBPHFaceRecognizer> model2 = createLBPHFaceRecognizer();

其余部分没有太大变化。

下载办法

源码已经分别上传到Github、百度网盘。其中github由于大小限制,不含我训练好的模型。

Github:`https://github.com/LiuXiaolong19920720/recognise-your-own-face

百度网盘:链接:http://pan.baidu.com/s/1nuPFthR 密码:slh8

还要再强调的一点是:人脸识别源码运行指南

人脸识别的源码放出来之后,不少小伙伴下载之后仍然不能运行成功。于是被逼无奈,把源代码改成了我认为最容易运行成功的版本。即使如此,我认为写下这个指南还是有必要的。因为反复回答相同的问题实在是太累人了。

重复一遍,本文环境为win7+vs2015+opencv3.2_with_contrib

源码下载地址

网盘: http://pan.baidu.com/s/1b1J23O 密码:kv1e(谨记此网盘链接与密码,是该系列最新代码下载的地址)

几个问题

首先还是说明几个问题,虽然都说过,但是还是有人问。以后再有人问就直接给他这篇文章。

找不到FaceRecognizer

FaceRecognizer在opencv的contrib模块里的face模块里面。而opencv官方下载的opencv默认是不带contrib的,要实现人脸识别需要用编译了contrib模块的opencv。一般来说需要自己编译。但是自己编译比较麻烦,网上有人分享了编译好的opencv3.2的版本,下载地址如下:

链接:http://pan.baidu.com/s/1qYx3v8S 密码:i0c0

csv文件(也即at.txt)难以自动生成。

源码中我已经写了一个名为add_label.py的python脚本,运行此脚本可以自动生成at.txt。

有时程序崩溃但是黑窗无报错信息。

一个可能的原因是,添加附加依赖项的时候,debug模式最好只添加*d.lib。而release模式最好只添加*.lib。

运行指南

方便起见,下载的源码的文件夹下已经包含了需要用的ORL人脸数据库。在配置好opencv的情况下,需要以下几步。

1、首先用VS打开face-rec.sln。在解决方案管理器中的源文件下添加take_photos.cpp,如果源文件下还有其他cpp文件,请它们排除到项目之外。然后运行此拍照程序。如果拍照效果不好,请自动调整人脸与摄像头之间的距离,或者调节光照条件。拍好的照片会保存在att_faces\s41文件夹下。

2、生成csv文件。需要电脑上安装有Python2,如果是Python3的话需要把print语句注释掉,没有实际测试过。如果对python有了解,应该不难。在add_label.py所在文件夹下shift+右键然后选择在此处打开命令行窗口。在命令行输入命令:python add_label.py,Enter运行即可。

3、回到VS。把take_photos.cpp排除到项目之外,添加train.cpp到源文件,运行。最后输出3行类似下面的语句表示训练模型成功。此时打开工程文件夹可以看到生成的后缀为xml的模型文件。

Predicted class = 9 / Actual class = 9.

4、回到VS。把train.cpp排除到项目之外,添加rec-your-own-face.cpp到源文件,运行。此时应该会打开摄像头并识别自己的脸。

最后

此人脸识别程序只能做学习研究,因为这个正确率略低。有更高要求的小伙伴请自行探究更好的方法,在这方面我能指点内容的有限。

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-11-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ATYUN订阅号

OpenAI-人工反馈的深度学习

rl-teacher是“Deep Reinforcement Learning from Human Preferences”的实现。 这个系统允许你教一个强化...

3816
来自专栏量子位

腾讯开源智能运维项目,用机器学习减少人为失误

继开源800万中文词的NLP数据集之后,腾讯又开源了一个智能运维学件平台Metis,主要面向运维工程师。

742
来自专栏ATYUN订阅号

【学术】如何在15分钟内建立一个深度学习模型?

我们正在开源Lore,它是一个框架,可供机器学习研究人员使用。 Lore地址:https://github.com/instacart/lore 机器学习常常给...

4407
来自专栏机器之心

资源 | Facebook开源人工智能框架ParlAI:可轻松训练评估对话模型

选自GitHub 机器之心编译 参与:吴攀、晏奇 Facebook 近日在 GitHub 上开源了一个可用于在多种开放可用的对话数据集上训练和评估人工智能模型...

3148
来自专栏人工智能头条

你们都用 Python 做人脸识别,我就偏要用 Go!

做人脸识别用 Python 比较多,但是今天碰上一个另类,他就跟别人不一样,就不用 Python 用 Go。其实不管是 P 还是 G,能认出脸来就是好样的。

1622
来自专栏ATYUN订阅号

【实践操作】在iPhone上创建你的第一个机器学习模型

最近的苹果iPhone X发布会,你会看到iPhone X有一些很酷的功能,比如FaceID,Animoji和AR。我们需要弄明白建立这样一个系统需要什么。 当...

3616
来自专栏Fish

CUDA C最佳实践-CUDA Best Practices(一)

这文档堪称CUDA官方手册里最有用TOP3了。 ps:全文翻译会累死猿哒,意译意译,各位看官凑合一下啦 前言 文档的作用 这文档能干嘛,是用来帮助开发者从N...

3106
来自专栏机器之心

资源 | 基于Python的开源人脸识别库:离线识别率高达99.38%

选自Github 机器之心编译 参与:路雪 仅用 Python 和命令行就可以实现人脸识别的库开源了。该库使用 dlib 顶尖的深度学习人脸识别技术构建,在户外...

4378
来自专栏AI科技大本营的专栏

学术 | DeepMind最新研究:使用更简单的环境就能检测AI是否安全

随着人工智能系统在现实生活中变得通用和实用,确保系统的安全运行变得越来越重要。迄今为止,大部分技术人工智能安全研究都集中在,对不安全行为的性质和原因的理论学习上...

2765
来自专栏ATYUN订阅号

构建自定义人脸识别数据集的三种训练方法

在接下来的几篇文章中,我们将训练计算机视觉+深度学习模型来进行面部识别。在此之前,我们首先需要收集脸部数据集。

2043

扫码关注云+社区