OpenCV结合V4l2实现人脸检测以及人脸识别

来源:互联网 发布:java权限控制设计 编辑:程序博客网 时间:2024/04/29 12:23

该Demo的基础是之前的OpenCV人脸检测以及V4l2摄像头驱动程序,在此基础上添加人脸识别功能,由于需要鉴别特定人脸,因此需要进行训练生成xml格式的级联分类器,然后加载此分类器即可实现特定人脸的识别。

说明
本Demo使用的是基于LBPH的FaceRecongnizer,思路为首先构造LBPHFaceRecognizer,然后进行训练并将训练结果保存以便下次使用,最后传入图像进行鉴别,每张图片会对应一个label,如果鉴别结果与某张图片吻合,就会返回该图片的下标,通过下标与label数组即可确定识别结果,思路清晰,不过这种鉴别算法已经是上古时代的了,以后打算使用神经网络实现人脸识别。

代码
需要下载Qt工程(点我下载)

#include "facerecognize.h"FaceRecognize::FaceRecognize(){    LBPHRecog = createLBPHFaceRecognizer(1, 8 ,3, 3, 50);//构造LBPH人脸识别类的对象并初始化    faceDetect.load("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml");}void FaceRecognize::loadLBPHState(){    if(access("./customCascade/face_lbph.xml", F_OK) == 0)        LBPHRecog->load("./customCascade/face_lbph.xml");//加载LBPH识别器的状态,避免重复训练    else        train();}void FaceRecognize::train(){    Mat src;    string pic;    for(int i = 0; i<filesName.size(); i++)    {        pic = filesName[i];        src = imread(pic);        cvtColor(src, src, CV_RGB2GRAY);        trainPic.push_back(src);        labelsInfo.insert(make_pair(i, filesName[i]));        labels.push_back(i);    }    //LBPHRecog->setLabelsInfo(labelsInfo);    LBPHRecog->train(trainPic, labels);         //LBP人脸识别训练函数    LBPHRecog->save("./customCascade/face_lbph.xml");           //保存LBPH识别器的状态}void FaceRecognize::printdir(const char *dir, int depth){    cout<<"start find file name"<<endl;    string filepath = dir;    DIR *dp;    struct dirent *entry;    struct stat statbuf;    if((dp = opendir(dir)) == NULL) {        fprintf(stderr,"cannot open directory: %s\n", dir);        return;    }    chdir(dir);    while((entry = readdir(dp)) != NULL) {        lstat(entry->d_name,&statbuf);        if(S_ISDIR(statbuf.st_mode)) {            if(strcmp(".",entry->d_name) == 0 ||                strcmp("..",entry->d_name) == 0)                continue;            //printf("%*s%s/\n",depth,"",entry->d_name);            //printdir(entry->d_name,depth+4);//如果需要递归,可以加上这句话        }        else        {            cout<<"file path is"<<filepath + entry->d_name<<endl;            filesName.push_back(filepath + entry->d_name);        }    }    chdir("..");    closedir(dp);}void FaceRecognize::getFilesName(string path)//获取path目录中的所有图片作为训练资源{    //filesName.push_back("./trainPic/WangRui1.jpg");    printdir(path.c_str(), 0);    for(int i=0; i<filesName.size(); i++)        cout<<filesName[i]<<endl;}Mat FaceRecognize::recognizeAndDraw(Mat frame){    //flip(frame, frame, 1);    recogPic = Mat::zeros(200, 200, frame.type());    double t = (double)getTickCount();//检测的时间    faces = FaceDetector(frame);//获取该帧中检测到的脸部的具体位置    t = ((double)getTickCount() - t)/getTickFrequency();    cout<<t<<endl;    DrawFace(frame, faces);//给脸部画上矩形框    for(size_t i = 0; i<faces.size(); i++)    {        facePic = frame(Rect(faces[i]));        resize(facePic, recogPic, recogPic.size());        cvtColor(recogPic, recogPic, CV_RGB2GRAY);        //equalizeHist(recogPic, recogPic);        result = LBPHRecog->predict(recogPic);//进行识别        //将识别结果显示在实时画面上        if(result ==-1)            putText(frame, "unknow", Point(faces[i].x, faces[i].y), 3, 0.5, Scalar(0, 255, 255), 1);        else            putText(frame, filesName[result], Point(faces[i].x, faces[i].y), 3, 0.5, Scalar(0, 255, 255), 1);    }    return frame;}vector<Rect> FaceRecognize::FaceDetector(Mat img){    Mat src = Mat::zeros(240, 320, img.type());    vector<Rect> faces;    cvtColor(img, img, CV_RGB2GRAY);    resize(img, src, src.size());    faceDetect.detectMultiScale(src, faces, 1.2, 6, 0,Size(30,30));    for(int i=0; i<faces.size(); i++)    {        faces[i].x=faces[i].x*2;        faces[i].y=faces[i].y*2;        faces[i].width=faces[i].width*2;        faces[i].height=faces[i].height*2;    }    return faces;}void FaceRecognize::DrawFace(Mat img, vector<Rect> faces){    for(size_t num = 0; num<faces.size(); num++)    {        rectangle(img, Point(faces[num].x, faces[num].y),                  Point(faces[num].x + faces[num].width, faces[num].y + faces[num].height), Scalar(0, 255, 0), 1, 8);    }}
0 0