基于OPencv LBP的人脸识别代码

分为图像采集,训练,及辨认:

#include "mainwindow.h"
#include <opencv.hpp>
#include "face.hpp"
#include "ui_mainwindow.h"
#include "QMediaRecorder"
#include <QDebug>
#include<iostream>
#include<direct.h>//创建目录等
#include<io.h>//文件是否存在
#include "qDebug"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
    ,capture(0)
{
    ui->setupUi(this);
std::thread t(&MainWindow::findImageByXML,this);
t.detach();
}

static Scalar randomColor(RNG& rng)
{
    int icolor = (unsigned)rng;
    return Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
}
MainWindow::~MainWindow()
{
    destroyAllWindows();
    capture.release();

    delete ui;
}
//bool pointTrackingFlag = false;
//Point2f currentPoint;

// Function to detect mouse events
//void onMouse(int event, int x, int y, int, void*)
//{
//    // Detect the mouse button down event
//    if(event == EVENT_LBUTTONDOWN)
//    {
//        // Assign the current (x,y) position to currentPoint
//        currentPoint = Point2f((float)x, (float)y);

//        // Set the tracking flag
//        pointTrackingFlag = true;
//    }
//}
Point originPoint;
Rect selectedRect;
bool selectRegion = false;
int trackingFlag = 0;
void drawOpticalFlow(const Mat& flowImage, Mat flowImageGray)
{
int stepSize = 16;
Scalar color = Scalar(0, 255, 0);
// Draw the uniform grid of points on the input image along with the motion vectors
for(int y = 0; y < flowImageGray.rows; y += stepSize)
{
for(int x = 0; x < flowImageGray.cols; x += stepSize)
{
// Circles to indicate the uniform grid of points
int radius = 2;
int thickness = -1;
circle(flowImageGray, Point(x,y), radius, color, thickness);
// Lines to indicate the motion vectors
Point2f pt = flowImage.at<Point2f>(y, x);
line(flowImageGray, Point(x,y), Point(cvRound(x+pt.x), cvRound(y+pt.y)), color);
}
}
}
// Function to track the mouse events
void onMouse(int event, int x, int y, int, void* image)
{
    if(selectRegion)
    {
        selectedRect.x = MIN(x, originPoint.x);
        selectedRect.y = MIN(y, originPoint.y);
        selectedRect.width = std::abs(x - originPoint.x);
        selectedRect.height = std::abs(y - originPoint.y);
        auto originMat=static_cast<Mat*>(image);
        selectedRect &= Rect(0, 0, originMat->cols, originMat->rows);
    }
    switch(event)
    {
        case cv::EVENT_LBUTTONDOWN:
            originPoint = Point(x,y);
            selectedRect = Rect(x,y,0,0);
            selectRegion = true;
            break;

        case EVENT_LBUTTONUP:
            selectRegion = false;
            if( selectedRect.width > 0 && selectedRect.height > 0 )
            {
                trackingFlag = -1;
            }
            break;
    }
}

void MainWindow::imageCapture()
{
    string cascade_file = "‪haarcascade_frontalface_alt.xml";//定义级联文件路径
    string save_path = "C:/Users/104005162/Desktop/face/%d/";//保存图片路径
        //定义摄像头设备
        VideoCapture capture(0);
        //调整摄像头分辨率
        //capture.set(CV_CAP_PROP_FRAME_WIDTH,1024);//设置宽
        //capture.set(CV_CAP_PROP_FRAME_HEIGHT,768);//设置高
        if (!capture.isOpened()) {//未打开,报错
            cout << "capture open fault!" << endl;
            return;
        }
        //定义必要的变量
        CascadeClassifier cascade_face = CascadeClassifier("F:/image-recognition/visionAlgorithm/haarcascades/haarcascade_frontalface_alt.xml");//定义级联变量并读取级联文件
        vector<Rect> faces;//定义人脸位置矩形向量
        Mat frame;//定义帧图,用于U读取
        int count = 0;//定义统计数量
        long current_tick_count = 0;//记录子目录名的数字
        bool save_state = false;//保存状态,用于用于控制
        //循环读取帧图
        while (capture.read(frame)){
            //printf("width=%d,height=%d\n",frame.cols,frame.rows);//打印提示
            //左右翻转,参数:(原图,目标图,反转代码)
            flip(frame,frame,1);
            //级联发现脸,参数:(图,矩形向量,尺度系数,高斯金字塔最小临近值,标记(0),最小尺寸,最大尺寸)
            cascade_face.detectMultiScale(frame,faces,1.09,1,0,Size(200,200),Size(400,400));
            //保存脸和绘制脸位置
            for (int i = 0; i < faces.size();i++) {//循环脸向量位置
                //获得人脸部分矩形
                Rect rect = faces[i];
                rect.x = rect.x + rect.width*0.16;//重定x
                rect.y = rect.y + rect.height*0.10;//重定y
                rect.width = rect.width*0.70;//重定宽
                rect.height = rect.height*0.78;//重定高
                //当为保存状态,且为10的倍数,且为小于401时,保存图片(保存40张图)
                if (save_state&&count%10==0&&count<401){
                    Mat dst;//定义新图
                    //调整脸图片大小,128*128,参数:(原图,目标图,尺寸,x比例,y比例,线性插值类型)
                    cv::resize(frame(rect),dst,Size(128,128),0,0,INTER_LINEAR);
                    //保存到指定位置
                    string path = format(save_path.c_str(), current_tick_count);//获得完整路径,以当前时间数的决定值为子目录名
                    //判断路径是否存在
                    /*
                        R_OK 只判断是否有读权限
                        W_OK 只判断是否有写权限
                        X_OK 判断是否有执行权限
                        F_OK 只判断是否存在
                        在宏定义里面分别对应:
                        0x00 只存在
                        0x02 写权限
                        0x04 读权限
                        0x06 读和写权限
                    */
                    if (_access(path.c_str(), _A_NORMAL)==-1) {//当路径不存在(-1),创建路径
                        _mkdir(path.c_str());//创建路径
                    }
                    path = path + string(format("%d.jpg",count/10));//添加路径文件名
                    imwrite(path.c_str(),dst);//保存图片,参数:(路径名,矩阵图)
                    //提示正在保存图片,头不要动,以眼睛作为基准线,变换表情。
                    string content("Don't move your head. Use your eyes as a baseline to change your expression.");//指定文本
                    //添加文本到图片,参数:(图,文本,原点,字体,缩放比,颜色,线宽,线型,左底起源状态(倒置效果))
                    putText(frame,content, Point(20, 30), 0, 0.5, Scalar(0,255, 0), 1, 8, false);
                }
                else if (save_state&& count<401) {//当保存状态为真,且统计数小于401时,说明在记录范围内,只提示
                    //提示正在保存图片,头不要动,以眼睛作为基准线,变换表情。
                    string content("Don't move your head. Use your eyes as a baseline to change your expression.");//指定文本
                    //添加文本到图片,参数:(图,文本,原点,字体,缩放比,颜色,线宽,线型,左底起源状态(倒置效果))
                    putText(frame, content, Point(20, 30), cv::FONT_HERSHEY_PLAIN, 0.5, Scalar(0, 255, 0), 1, 8, false);
                }else {//否则提示等待状态
                    //添加文本到图片,参数:(图,文本,原点,字体,缩放比,颜色,线宽,线型,左底起源状态(倒置效果))
                    putText(frame,"Wait for the key to be pressed.",Point(20,30),cv::FONT_HERSHEY_PLAIN,1.0,Scalar(255,0,0),1,8,false);
                }
                //绘制矩形,参数:(图,矩形变量,颜色,线宽,线型,偏移量)
                rectangle(frame, rect, Scalar(0, 255, 0), 1, 8, 0);
            }
            //显示图
            imshow("frame",frame);
            //按键判断
            char c = waitKey(33);//等待33毫秒并获得按键值,-1时表示没有输入
            if (c==27) {//当为ESC(27)时,退出循环
                break;
            }else if(c!=-1) {//当用户点击除ESC的任意键时,应拍照保存人脸部分或改变状态
                save_state = (save_state ? false : true);//反转保存状态,当保存状态为真时,给假,否则给真
                count = 0;//统计数量给0,从新计数
                current_tick_count = (save_state?abs(getTickCount()):0);//当保存状态为真是,获得当前时间统计值的绝对值,否则为0
            }
            count++;//统计变量加1
        }
        //释放摄像头资源
        capture.release();

}

void getFiles(string path, vector<string>& files)
{
    intptr_t   hFile = 0;//文件句柄,过会儿用来查找
    struct _finddata_t fileinfo;//文件信息
    string p;
    if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)
     //如果查找到第一个文件
    {
        do
        {
            if ((fileinfo.attrib &  _A_SUBDIR))//如果是文件夹
            {
                if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                    getFiles(p.assign(path).append("\\").append(fileinfo.name), files);
            }
            else//如果是文件
            {
                files.push_back(p.assign(path).append("\\").append(fileinfo.name));
            }
        } while (_findnext(hFile, &fileinfo) == 0); //能寻找到其他文件

        _findclose(hFile);  //结束查找,关闭句柄
    }
}
void MainWindow::trainImage()
{
vector<string> filesPath,filesPath1;
//此处80的训练阈值可由正确识别时人物置信度所处大致范围决定
cv::Ptr<cv::face::LBPHFaceRecognizer> model =  cv::face::LBPHFaceRecognizer::create(1,8,8,8,80);
std::vector<cv::Mat>referceneImage;
std::vector<int>labels;
getFiles("C:\\Users\\104005162\\Desktop\\face\\liu",filesPath);
getFiles("C:\\Users\\104005162\\Desktop\\face\\zhu",filesPath1);
for(auto each:filesPath)
{
    qDebug()<<QString::fromStdString(each);
    referceneImage.push_back(cv::imread(each,cv::IMREAD_GRAYSCALE));
    labels.push_back(1);
}

for(auto each:filesPath1)
{
    qDebug()<<QString::fromStdString(each);
    referceneImage.push_back(cv::imread(each,cv::IMREAD_GRAYSCALE));
    labels.push_back(2);
}
model->train(referceneImage,labels);
model->save(".\\myfirst3.xml");
qDebug()<<"6666666666";
//int label=-1;
//double confidence=0;
//model->predict(cv::imread("C:\\Users\\104005162\\Desktop\\face\\liu\\1.jpg",cv::IMREAD_GRAYSCALE),
//             label,confidence);
//qDebug()<<label<<"con:"<<confidence;
}

void MainWindow::predictImage()
{
    int label=-1;
    double confidence=-1;
    string name="myfirst3.xml";
    FileStorage fs("myfirst3.xml", FileStorage::READ);
    CV_Assert(fs.isOpened());


   cv::Ptr<cv::face::LBPHFaceRecognizer> model=Algorithm::
           load<cv::face::LBPHFaceRecognizer>(name);
   if(model.empty()){qDebug()<<"ok";};
   model->predict(cv::imread("C:\\Users\\104005162\\Desktop\\face\\zhu\\5.jpg",cv::IMREAD_GRAYSCALE),
                  label,confidence);
   qDebug()<<label<<"con:"<<confidence;
}

void MainWindow::findImageByXML()
{
    int label=-1;
    double confidence=-1;
    string name="myfirst3.xml";
   cv::Ptr<cv::face::LBPHFaceRecognizer> model=Algorithm::
           load<cv::face::LBPHFaceRecognizer>(name);
   if(model.empty()){qDebug()<<"ok";};

    //定义摄像头设备
    VideoCapture capture(0);
    //调整摄像头分辨率
    //capture.set(CV_CAP_PROP_FRAME_WIDTH,1024);//设置宽
    //capture.set(CV_CAP_PROP_FRAME_HEIGHT,768);//设置高
    if (!capture.isOpened()) {//未打开,报错
        cout << "capture open fault!" << endl;
        return;
    }
    //定义必要的变量
    CascadeClassifier cascade_face = CascadeClassifier("F:/image-recognition/visionAlgorithm/haarcascades/haarcascade_frontalface_alt.xml");//定义级联变量并读取级联文件
    vector<Rect> faces;//定义人脸位置矩形向量
    Mat frame;//定义帧图,用于U读取
    //循环读取帧图
    while (capture.read(frame)){
        //printf("width=%d,height=%d\n",frame.cols,frame.rows);//打印提示
        //左右翻转,参数:(原图,目标图,反转代码)
        flip(frame,frame,1);
        //级联发现脸,参数:(图,矩形向量,尺度系数,高斯金字塔最小临近值,标记(0),最小尺寸,最大尺寸)
        cascade_face.detectMultiScale(frame,faces,1.09,1,0,Size(200,200),Size(400,400));
        //保存脸和绘制脸位置
        for (int i = 0; i < faces.size();i++) {//循环脸向量位置
            //获得人脸部分矩形
            Rect rect = faces[i];
            rect.x = rect.x + rect.width*0.16;//重定x
            rect.y = rect.y + rect.height*0.10;//重定y
            rect.width = rect.width*0.70;//重定宽
            rect.height = rect.height*0.78;//重定高
            //当为保存状态,且为10的倍数,且为小于401时,保存图片(保存40张图)
            Mat dst;//定义新图
            //调整脸图片大小,128*128,参数:(原图,目标图,尺寸,x比例,y比例,线性插值类型)
            cv::resize(frame(rect),dst,Size(128,128),0,0,INTER_LINEAR);
            //保存到指定位置
            cvtColor(dst,dst,COLOR_BGR2GRAY);
            model->predict(dst,label,confidence);
            if(label==1&&confidence<85)
            {
                QString text="liuhao"+QString::number(confidence);
               putText(frame,text.toStdString(), Point(rect.x, rect.y), 0, 0.5, Scalar(0,255, 0), 1, 8, false);
            }
            else if(label==2&&confidence<85)
            {
                QString text="zhongdong"+QString::number(confidence);
               putText(frame,text.toStdString(), Point(rect.x, rect.y), 0, 0.5, Scalar(0,255, 0), 1, 8, false);
            }
            else
            {
                putText(frame,"unknown!", Point(rect.x, rect.y), 0, 0.5, Scalar(0,255, 0), 1, 8, false);
            }
        }
        //显示图
        imshow("frame",frame);
        //按键判断
        char c = waitKey(33);//等待33毫秒并获得按键值,-1时表示没有输入
        if (c==27) {//当为ESC(27)时,退出循环
            break;
        }
    }
    //释放摄像头资源
    capture.release();

}



QImage Mat2QImage(cv::Mat cvImg)
{
    QImage qImg;
    if(cvImg.channels()==3) //3 channels color image
    {
        cv::cvtColor(cvImg,cvImg,COLOR_BGR2RGB);
        qImg =QImage((const unsigned char*)(cvImg.data),cvImg.cols, cvImg.rows,cvImg.cols*cvImg.channels(),QImage::Format_RGB888);
    }
    else if(cvImg.channels()==1) //grayscale image
    {
        qImg =QImage((const unsigned char*)(cvImg.data),cvImg.cols,cvImg.rows,cvImg.cols*cvImg.channels(),QImage::Format_Indexed8);
    }
    else{
        qImg =QImage((const unsigned char*)(cvImg.data),cvImg.cols,cvImg.rows,cvImg.cols*cvImg.channels(),QImage::Format_RGB888);
    }
    return qImg;
}

训练好的xml文件:下载

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颢师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值