opencv人脸识别

opencv人脸识别

  • 环境:VS2015
  • 版本:opencv3.3.0

人脸训练集的获取与制作

在人脸识别之前需要获取人脸的训练集,这里利用的是The ORL Database of Faces’数据库,也可以自己采集人脸图像进行检测然后调整大小,具体的过程可以参照:http://blog.csdn.net/wanghz999/article/details/78751406

cvs文件获取

人脸识别的过程就是对人脸图像进行训练然后读取人脸并进行识别。在训练时,计算机会对每张人脸的多张图像进行特征提取,然后根据特征值来区分不同的人脸。然而计算机并不知道两种不同的人脸彼此是哪张,因此需要告诉预先告诉计算机一个标签——区分不同的人脸。cvs文件就是包含人脸图像路径和标签的文件,格式如下:

D:/workspace/VS/opencv/face_recg/face_recg/face/s1/1.pgm;0
D:/workspace/VS/opencv/face_recg/face_recg/face/s1/10.pgm;0
D:/workspace/VS/opencv/face_recg/face_recg/face/s1/2.pgm;0
D:/workspace/VS/opencv/face_recg/face_recg/face/s1/3.pgm;0
D:/workspace/VS/opencv/face_recg/face_recg/face/s1/4.pgm;0
...

;之前的表示人脸图像的路径,;之后的0表示标签。opencv官方提供了create_cvs.py,该文件位于源码目录(OPENCV_SOURCE_DIR)的opencv_contrib模块目录下:

OPENCV_SOURCE_DIR/opencv_contrib/modules/face/samples/etc

也可以直接从github上获取:https://github.com/opencv/opencv_contrib/tree/master/modules/face/samples/etc

这里给出我使用的(python3.*适用):
#!/usr/bin/env python

import sys  
import os.path  

# This is a tiny script to help you creating a CSV file from a face  
# database with a similar hierarchie:  
#  
#  philipp@mango:~/facerec/data/at$ tree  
#  .  
#  |-- README  
#  |-- s1  
#  |   |-- 1.pgm  
#  |   |-- ...  
#  |   |-- 10.pgm  
#  |-- s2  
#  |   |-- 1.pgm  
#  |   |-- ...  
#  |   |-- 10.pgm  
#  ...  
#  |-- s40  
#  |   |-- 1.pgm  
#  |   |-- ...  
#  |   |-- 10.pgm  
#  

if __name__ == "__main__":  

    #if len(sys.argv) != 2:  
    #    print "usage: create_csv <base_path>"  
    #    sys.exit(1)  

    #BASE_PATH=sys.argv[1]  
    BASE_PATH="D:/workspace/VS\opencv/face_recg/face_recg/face/"  

    SEPARATOR=";"  

    fh = open("at.txt",'w')  

    label = 0  
    for dirname, dirnames, filenames in os.walk(BASE_PATH):  
        for subdirname in dirnames:  
            subject_path = os.path.join(dirname, subdirname)  
            for filename in os.listdir(subject_path):  
                abs_path = "%s/%s" % (subject_path, filename)  
                print ("%s%s%d" % (abs_path, SEPARATOR, label))  
                fh.write(abs_path)  
                fh.write(SEPARATOR)  
                fh.write(str(label))  
                fh.write("\n")        
            label = label + 1  
    fh.close()  

其中,BASE_PATH表示存放人脸图像的文件夹,在该文件夹下,每个文件夹代表一个人脸,一个人脸应该有多张大小一样的图。该文件夹如下:

opencv人脸识别模块简介

opencv支持3种人脸识别的算法,分别是:

  1. Eigen Faces
  2. Fisher Faces
  3. Local Binary Pattern Histograms(局部二值模式直方图)

自opencv3.0开始,人脸识别的模块也有许多变动,实现跟以前一些很多不一样。上述的3种算法在opencv3.*中对应三个类:EigenFaceRecognizerFisherFaceRecognizerLBPHFaceRecognizer,它们都是从BasicFaceRecognizer继承过来的子类。这三个类有相似的API函数(以EigenFaceRecognizer为例):

/*创建人脸识别的模型,若该两个参数为空,会以默认值创建
@param num_components:进行训练的人脸图片数
@param threshold: 阈值*/
Ptr<EigenFaceRecognizer> EigenFaceRecognizer::create(int num_components, 
                                                double threshold);
/*对模型进行训练
@param src:进行训练的人脸图像
@param labels:标签值,每张相同的人脸都有标签值来区分*/
void train(InputArrayOfArrays src, InputArray labels);

/*利用训练好的模型进行人脸识别,返回标签值
@param src:需要进行识别的图像/
CV_WRAP_AS(predict_label) int predict(InputArray src) const;

opencv人脸识别代码实现

#include<iostream>
#include<fstream>
#include<sstream>
#include<math.h>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui.hpp>
#include<cv.h>
#include<objdetect.hpp>
#include<opencv2/face.hpp>

using namespace cv::face;
using namespace std;
using namespace cv;

vector<Mat> faces;
vector<int> labels;

//使用CVS文件读取图片和标签
void read_cvs(const string& filename, vector<Mat>& img, vector<int>& lable, char separator = ';')
{
    Mat tmp_img;
    ifstream cvs_file(filename.c_str());
    assert(cvs_file);
    string line, path, tag;
    while (getline(cvs_file, line))
    {
        stringstream lines(line);
        getline(lines, path, separator);
        getline(lines, tag);
        if (!path.empty() && !tag.empty())
        {
            tmp_img = imread(path, IMREAD_GRAYSCALE);   //读入图像时转成灰度图
            assert(!tmp_img.empty());
            img.push_back(tmp_img);
            lable.push_back(atoi(tag.c_str()));
        }
    }
    tmp_img.release();
}
int main()
{
    string cvs_path = "./face/at.txt";
    Mat test_face;
    int test_label,p_label;
    int sample_num = 0;
    try 
    {
        read_cvs(cvs_path, faces, labels);  //读取人脸图像和标签
    }
    catch (cv::Exception& e) 
    {
        cerr << "Error opening file.Reason:" << e.msg << endl;
        exit(1);
    }

    if (faces.size() <= 1)
    {
        cout << "Too few face images" << endl;
        return -1;
    }
    /*从训练集中取出一张图片作为测试图*/
    sample_num = faces.size();
    test_face = faces[sample_num - 1];
    test_label = labels[sample_num - 1];
    faces.pop_back();
    labels.pop_back();

    /* 创建人脸识别的模型,并进行训练,之后保存训练结果*/
    Ptr<EigenFaceRecognizer> eigen_model = EigenFaceRecognizer::create();
    eigen_model->train(faces, labels);
    eigen_model->save("my_eigen_face_model.xml");

    Ptr<FisherFaceRecognizer> fisher_model = FisherFaceRecognizer::create();
    fisher_model->train(faces, labels);
    fisher_model->save("my_fisher_face_model.xml");

    Ptr<LBPHFaceRecognizer> lbph_model = LBPHFaceRecognizer::create();
    lbph_model->train(faces, labels);
    lbph_model->save("my_lbph_face_model.xml");

    /*对人脸进行测试,查看是否能够识别*/
    p_label = eigen_model->predict(test_face);
    cout << "Test label is:" << test_label << ",predict label is:"<< p_label << endl;
    p_label = fisher_model->predict(test_face);
    cout << "Test label is:" << test_label << ",predict label is:" << p_label << endl;
    p_label = lbph_model->predict(test_face);
    cout << "Test label is:" << test_label << ",predict label is:" << p_label << endl;
    return 0;
}

人脸识别程序说明

训练和测试使用灰度图。EigenFaceRecognizerFisherFaceRecognizer两个类在调用train训练时可以使用BGR图像,但是训练结果中保存的是单通道的灰度图结果。可以查看生成的训练结果文件my_eigen_face_model.xml

可以看到在训练结果中保存的训练集是1*10304大小的图片,而我训练集图片大小为92 * 112(92 * 112 = 10304)。在对测试图进行人脸识别时,必须确保测试图大小与保存的训练集大小一致,否则会报错。而LBPHFaceRecognizer类必须使用灰度图进行训练,不然也会报错。

结果

可以看到程序可以对人脸进行识别,正确给出标签值。

  • 1
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值