【opencv实践】人脸识别匹配——数据收集和预处理

参考自@星沉阁冰不语出品,转载请注明作者和出处。

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

本人女学渣一枚研一,所有过程参考上面的大神,记录一下我的历程。

毕业论文将做【基于opencv的课堂点名和监控系统】,之前一直在做人脸检测,如果各路大神有什么好点子请在下方留言。下面开始。

人脸检测可以利用opencv自带的分类器,但是人脸识别就需要自己收集数据,自己训练分类器了。opencv给出的有人脸识别的教程:Face Recognition with OpenCV。网上也可以找到中文版本的。

一、背景数据集

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

下载下来之后是这样的:

这里写图片描述

这里写图片描述

可以看到每个人一个文件夹,每个文件夹下是这个人的十张照片,但是不是我们熟悉的BMP或者是PNG或者是JPEG格式的,而是PGM格式的。windows7自带的照片查看器和画图软件都不能打开这种格式的图片!!所以我们将用强大的imread()函数读取,所以记得opencv文档里有这样的描述:

这里写图片描述

#include<opencv2\opencv.hpp>

using namespace cv;
int main()
{
    Mat img = imread("C:\\Users\\Apple\\Desktop\\ORL\\s40\\1.pgm");
    imshow("1", img);
    waitKey(0);
    return 0;
}

这里写图片描述这里写图片描述这里写图片描述

二、自己的人脸数据集

1.拍照程序

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

程序的功能就是打开电脑摄像头,当P键按下的时候,保存当前帧的图像。简单到没朋友。

#include<opencv2\opencv.hpp>

using namespace cv;

int main()
{
    VideoCapture cap(0);
    Mat frame;
    int i = 0;

    while (1)
    {
        char key = waitKey(100);
        cap >> frame;
        imshow("frame", frame);
        string filename = format("C:\\Users\\Apple\\Desktop\\hhh\\aaa%d.jpg", i);

        switch (key)
        {
        case'p':
            i++;
            imwrite(filename, frame);
            imshow("photo", frame);
            waitKey(500);
            destroyWindow("photo");
            break;
        default:
            break;
        }
    }
}

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

2.预处理

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

检测出人脸之后改变大小使之与ORL人脸数据库人脸大小一致。通过加断点在Locals里面或者是ImageWatch可以看到ORL人脸数据库人脸的大小是92 x 112。(这个也是根据博主博客学习的)

这里写图片描述

那么如何批量处理上面拍的照片呢?我给实验室每位同学都来了20连拍,这个工作量还是很大的。答主给的程序不太全,编了一下午才调好了代码。可以分割人脸并且变大小灰度与ORL数据库人脸大小一致,然后保存下来,保存的文件夹一定要注意先提前建好。

代码如下:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>

using namespace cv;

int main()
{
    char file_img[160];
    Mat t_img[160];
    vector<Rect> faces;
    CascadeClassifier face_cascade;
    face_cascade.load("haarcascade_frontalface_alt.xml");

    //Size dst_size;
    //读取训练样本
    for (int i = 0; i < 160; i++)
    {
        Mat img_gray;
        int d = i + 1;
        sprintf(file_img, "C:\\Users\\Apple\\Desktop\\头2\\%d.jpg", d);
        Mat img = imread(file_img, 1);
        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_CANNY_PRUNING, Size(60, 60),Size(240,240));
        if (faces.size() == 0)
        {

            continue;

        }
        Mat faceROI = img(faces[0]);
        Mat MyFace;
        resize(faceROI, MyFace, Size(90, 112));
        cvtColor(MyFace, MyFace, COLOR_BGR2GRAY);
        string  str = format("C:\\Users\\Apple\\Desktop\\头3\\%d.jpg", d);
        imwrite(str, MyFace);
        imshow("ii", MyFace);
        waitKey(10);
    }
}

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

这里写图片描述

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

跟着大神做了一天,十分疲惫。。

未完待续……

猜你喜欢

转载自blog.csdn.net/shangpapa3/article/details/60763634