OpenCV实践之路——人脸识别之一数据收集和预处理

Posted 冰不语

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV实践之路——人脸识别之一数据收集和预处理相关的知识,希望对你有一定的参考价值。

本文由@星沉阁冰不语出品,转载请注明作者和出处。

文章链接:http://blog.csdn.net/xingchenbingbuyu/article/details/51386949

微博:http://weibo.com/xingchenbing 


前段时间对人脸检测和人脸标记进行了一些尝试:人脸检测(C++/Python)用Dlib库进行人脸检测和人脸标记。但是检测和识别是不同的,检测解决的问题是图片中有没有人脸;而识别解决的问题是,如果一张图片中有人脸,这是谁的脸。人脸检测可以利用opencv自带的分类器,但是人脸识别就需要自己收集数据,自己训练分类器了。opencv给出的有人脸识别的教程:Face Recognition with OpenCV。网上也可以找到中文版本的。

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


一、背景数据集


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

下载下来之后是这样的:






可以看到每个人一个文件夹,每个文件夹下是这个人的十张照片,但是不是我们熟悉的BMP或者是PNG或者是JPEG格式的,而是PGM格式的。windows7自带的照片查看器和画图软件都不能打开这种格式的图片。不过好在我昨天刚对imread()函数研究过:使用imread()函数读取图片的六种正确姿势。所以记得opencv文档里有这样的描述:




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





二、自己的人脸数据集


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;
			
		

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

2.预处理

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

人脸检测在之前的博客中已经做了介绍,这里就不再赘述。详情参考:OpenCV实践之路——人脸检测(C++/Python)。用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的。经测试仍然可以训练出可以正确识别我自己人脸的模型来。但是如果大小不一致会报错。


之后的内容放到下一次记录。未完待续......


-----------------------------------------------

更新:opencv3版本的代码有所改动,请参考较新的博客提示。

-----------------------------------------------

知识星球

除了平时发文章之外,也会发一些平时学习过程中其他的参考资料和代码,欢迎加入。


以上是关于OpenCV实践之路——人脸识别之一数据收集和预处理的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV实践之路——人脸识别之二模型训练

人脸识别《一》opencv人脸识别之收集人脸并学习

opencv学习之路(40)人脸识别算法——EigenFaceFisherFaceLBPH

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

人脸识别《一》opencv人脸识别之预处理

opencv学习之路(41)人脸识别