qt+opencv+dlib 人脸识别,可以存储人脸数据

原本是想做一个类似windown hello的人脸识别解锁项目,先做了一个简单的人脸识别的小项目,很多内容其实很多其它博主都做过了,做了一个资源的整合。做的比较垃圾,求指点。

功能演示:

主界面

 录入界面

最后识别界面

 

项目框架

input_face:录入新的人脸信息(录入并存储人脸照片,设置人脸姓名,并保存为csv数据格式)

mainwindow:主界面

my_camera:摄像头模块(摄像头的开闭,获取帧)

my_dlib:包含对人脸数据的全部操作(将人脸数据转化为128D的数据,检查人脸差异)

主要代码:

人脸识别块

//接受人脸mat 返回是否是指定人脸的姓名
QString my_dlib::recognition_face(const cv::Mat &cap)
{


    QString name="Unkown";

    if(data_csv.size() == 0)
        return name;

    //在传过来的cap帧上识别人脸
    cv::Mat grep_cap;
    cv::cvtColor(cap,grep_cap,cv::COLOR_RGBA2GRAY);

    //dlib::cv_image<rgb_pixel> dlib_img(grep_cap);      //将cv中的Mat转化为dlib中的 image
    dlib::cv_image<unsigned char> dlib_img(grep_cap);
    auto rects = detector(dlib_img);

    //获得脸部的特征点
    auto shape = sp(dlib_img, rects[0]);

    dlib::matrix<rgb_pixel> face_chip;

    extract_image_chip(dlib_img, get_face_chip_details(shape, 150, 0.25), face_chip);

    std::vector<dlib::matrix<rgb_pixel>> faces;
    faces.clear();
    faces.push_back(face_chip);

    //利用该人脸获得数据
    //每个vector<matrix<float, 0, 1>>里面就有128个float数据
    std::vector<matrix<float, 0, 1>> face_descriptor = net(faces); //获得脸部数据

    QVector<float> face_data;
    matrix_To_Qvector(face_descriptor,face_data);
    //用获得的数据和csv中的数据判断差异
    QVector<double> e_distance_list;
    e_distance_list.clear();
    for(int i = 0; i< data_csv.size(); i++)
    {
        std::vector<matrix<float, 0, 1>> data_csv_matrix;

        //Qvector_to_Matrix(data_csv[i],data_csv_matrix);
        //double dis=(double)length(face_descriptor[0]-data_csv_matrix[0]);

        double dis =get_distance(data_csv[i],face_data);        //计算距离差距
        if(dis == -1) continue;
        e_distance_list.push_back(dis);         //将差距结果存放起来

    }

    auto min = std::min_element(std::begin(e_distance_list), std::end(e_distance_list));     //找到最小值
    //最大值和最小值的位置的表示方式:
    auto positionmin = std::distance(std::begin(e_distance_list),min);  //找到最小值所在的下标
    //qDebug()<<"Minimum e distance with person"<<int(positionmin) + 1;

    //如果差异小于0.4则证明该人脸为csv文件内的一张脸
    if(*min < 0.4)
    {
        name = folder_name[positionmin];
        qDebug()<<"recognition face name :"<<name;
        return name;
    }

    return name;
}

保存人脸数据到csv

//将从dlib中解析的人脸数据 保存到csv
bool save_to_csv(std::vector<std::vector<matrix<float, 0, 1>>> &data)
{
    std::string filename = QString("D:/QT_file/opencv_test/face_camera/model/%0.csv").arg("face").toStdString();

    if(data.size()==0)
    {
        return false;
    }


    std::ofstream outfile(filename, std::ofstream::out);

    for(auto descriptors:data)
    {
        for (const auto& desc : descriptors)
        {
            for (long r = 0; r < desc.nr(); ++r)
            {
                for (long c = 0; c < desc.nc(); ++c)
                {
                    outfile << desc(r, c) << ',';
                }
            }
            outfile << '\n';
        }
    }
    outfile.close();

    qDebug()<<"save csv ok!";

    return true;

}

获取视频帧:

//获得当前摄像头的一帧
QPixmap &my_camera::get_pixmap()
{

    capture>>cap; //读取当前帧

    ShowFPS_Method(cap);        //显示帧率

    if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
    {
        //对图像进行预处理
        cvtColor(cap, cap_gray, cv::COLOR_BGR2GRAY);   //转为灰度图
        equalizeHist(cap_gray, cap_gray);       //直方图均衡化,增加对比度方便处理

        //进行识别
        face_cascade.detectMultiScale(cap_gray, faceRect, 1.1, 3, 0 | cv::CASCADE_DO_ROUGH_SEARCH, cv::Size(50, 50));//检测,检测的结果会放到faceRect中


        //开始画框 faceRect.size表示检测到的人脸个数
        for (size_t i = 0; i < faceRect.size(); i++)
        {
            cv::rectangle(cap, faceRect[i], cv::Scalar(0, 255, 0));      //用绿色矩形画出检测到的位置

            //在此处要判判断人脸,获取name
            QString reco_name = d->recognition_face(cap);

            //给图片加文字
            cv::putText(cap, reco_name.toStdString(), cv::Point(faceRect[i].x,faceRect[i].y-1), cv::FONT_HERSHEY_COMPLEX, 1, cv::Scalar(255, 0, 0),2,2, 0);

            //如果脸部大于10张,就不保存了
            cv::Mat faceROI = cap_gray(faceRect[i]);        //保存脸部图片
            cv::resize(faceROI,faceROI,cv::Size(92, 112));
            face_mat = faceROI;

        }

        //将每一帧的画面添加到label中
        imag = Mat2QImage(cap);     // 将Mat转换成QImage对象来显示
        imag = imag.scaled(m_width, m_height,
                           Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致

        pm_cam = QPixmap::fromImage(imag);
        //ui->cam->setPixmap(QPixmap::fromImage(imag));  // 将图片显示到label上


    }
    else
        qDebug("can not ");



    return pm_cam;      //将每一帧的图片传回

}

开源地址:

https://gitee.com/linye2830/face_camera.git

总结:

这个项目还有很多需要改进的地方:

1,视频中人像移动太快,会导致程序直接崩溃。。。。(感觉这个没思路解决)

2,帧率太低,尤其是在识别出已有的人脸时,帧数会特别低(这个我感觉可以用多线程解决,主要是计算过程很耗时)

3,我自己编译的dlib库时release版本的,比较头疼,用qt编译的时候要用release

求大佬指点

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值