Qt5.7+Opencv2.4.9人脸识别(三)人脸处理_IT1995的博客-程序员宅基地

技术标签: 小项目集合  C/C++  人脸检测  Qt  毕业设计  OpenCV  CC++  

【注意】本博文的档次适合OpenCV初学者,和要做本科生毕业设计这类档次。

上一节是人脸采集,链接如下:

http://blog.csdn.net/qq78442761/article/details/71158472


源码的下载地址和原理理论部分请走下面连接

http://blog.csdn.net/qq78442761/article/details/71157980


本节讲解Opencv中的人脸处理,

功能如下:

当我们点击了功能里面的照片处理后,如下所示:


并且在Data目录下,可以看见生成了一个对应的文件夹,这个文件夹和peopel.txt里面的标识对应,如下图所示:


下面来看代码

void AddPeople::disposePic()
{
    file.CreateFile(QString::number( MaxNumAboutPeople,10));
    QString sourceFilePath="addData\\";
    QString targetFilePath="Data\\"+QString::number(MaxNumAboutPeople,10);
    targetFilePath.append("\\");
    QString sourceFile;
    QString targetFile;
    for(int i=0;i<10;i++)
    {
        sourceFile.append(sourceFilePath+QString::number(i+1,10));
        sourceFile.append(".jpg");
        targetFile.append(targetFilePath);
        targetFile.append(QString::number(i,10));
        targetFile.append(".jpg");
        this->detectAndDisplay(sourceFile,targetFile);
        sourceFile.clear();
        targetFile.clear();
    }
}
这是创建文件夹的代码,是不是很简单呢?其实就是调用了file.h,我们现在进入file.h和file.cpp来看看

如果创建文件夹:

void MyFILE::CreateFile(QString fileName)
{
    PicFile=new QDir;
    QString path="Data\\"+fileName;
    if(PicFile->exists(path))
    {
        QMessageBox about;
        about.setText(tr("文件夹创建失败"));
        about.exec();
    }
    else
    {
        if(PicFile->mkdir(path))
        {
            QMessageBox about;
            about.setText(tr("文件夹创建成功"));
            about.exec();
        }
    }
}

而关于存储图像和处理在detectAndDisplay(sourceFile,targetFile);这个函数中。

现在来看此函数:

void AddPeople::detectAndDisplay(QString source, QString target)
{
    std::string face_cascade_name = "haarcascade_frontalface_alt.xml";
    cv::CascadeClassifier face_cascade;   //定义人脸分类器

    cv::Mat frame = cv::imread(source.toStdString());
    if(!frame.data)
    {
        qDebug()<<source;
        QMessageBox::warning(this,tr("提示"),tr("frame读取失败"),QMessageBox::Ok);
        return;
    }
    if (!face_cascade.load(face_cascade_name))
    {
        QMessageBox::warning(this,tr("错误"),tr("haarcascade_frontalface_alt.xml加载失败"),QMessageBox::Ok);
        return;
    }
    std::vector<cv::Rect> faces;
    cv::Mat img_gray;

    cv::cvtColor(frame, img_gray, cv::COLOR_BGR2GRAY);
    cv::equalizeHist(img_gray, img_gray);

    face_cascade.detectMultiScale(img_gray, faces, 1.1, 3, CV_HAAR_DO_ROUGH_SEARCH, cv::Size(50, 50));

    for (int j = 0; j < (int)faces.size(); j++)
    {
        cv::Mat faceROI = frame(faces[j]);
        cv::Mat MyFace;
        cv::Mat gray_MyFace;
        if (faceROI.cols > 100)
        {
            cv::resize(faceROI, MyFace, cv::Size(92, 112));
            cv::cvtColor(MyFace, gray_MyFace, CV_BGR2GRAY);
            imwrite(target.toStdString(), gray_MyFace);
        }
    }
}

这里的代码说白了就是调用haarcascade找人脸,分割人脸,然后进行灰度处理,和直方图均衡化,然后进行imwrite保存文件。

进行灰度处理,和直方图均衡化是为了训练模型时减少计算,减少冗余信息对识别的影响,提供识别准确度。


10张图片处理完毕了,下面我们生成csv文件。

csv也就是逗号分割的文件,也就是说,我们有10张图,如果10个人就100张图,为了操作方便,为何不用一个文件把这些图的路径和人脸的标号放在一起,让Opencv直接读取,这样才方便。

当点击生成csv后如下图所示:

这个at.txt文件是预先创建好的。

其实功能就是把相对路径换成绝对路径,方便Opencv进行读取。这里有个坑要注意,Opencv中读取csv文件只能是ASCII编码,如果不是ASCII将读取不了,如下图所示:


现在来看代码,如何完成这样的工作:

void AddPeople::AddCSV()
{
    file.MakecsvFile();
}
在Addpeople中AddCSV调用了file.MakecsvFile,现在进去看他具体的代码:

void MyFILE::MakecsvFile()
{
    QDir csvFile("./Data/at.txt");
    QString csvPath=csvFile.absolutePath();
    QString csvFilePath=csvPath;
    csvPath.chop(6);
    QString path=csvPath+QString::number(MaxNumAboutPeople,10)+"/";
    for(int i=0;i<10;i++)
    {
        QString filepath=path;
        filepath.append(QString::number(i,10));
        filepath.append(".jpg;");
        filepath.append(QString::number(MaxNumAboutPeople,10));
        //this->AddPeople(csvFilePath,filepath);
        QFile file(csvFilePath);
        if(!file.open(QIODevice::WriteOnly|QIODevice::Append))
        {
            QMessageBox about;
            about.setText(tr("添加人员时文件打开失败"));
            about.exec();
            return;
        }
        QTextStream in(&file);
        //in.setCodec("UTF-8");
        in<<filepath<<"\r\n";
        file.close();
    }
}

是不是和上一节创建文件一样简单呢!

下一节将说明模型训练!
源码和理论部分在本博文开头有提供。



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq78442761/article/details/71159013

智能推荐

response.resetBuffer();-程序员宅基地

response.resetBuffer();重置, 输出流。_resetbuffer

Activity之间返回结果-程序员宅基地

一 、实现:1、在MainActivity中:1)onCreate()中:Intent intent = new Intent(MainActivity.this,OtherActivity.class);startActivityForResult(intent,0); //startActivityForResult(Intent intent,int requestcode)2)重写onAc

C++学习笔记(二)内联函数、引用、默认参数、函数重载、函数模板、函数具体化-程序员宅基地

1、C++的返回值不能是数组,可以是其他任何类型,但是可以将数组作为结构或对象组成部分来返回 2、原型描述函数到编译器的接口 C++中原型是必不可少的 3、C++禁止将const变量的地址赋给非const的指针 将非const变量的地址赋给const的指针是允许的 4、内联函数是C++为了提高程序运行速度做出的改进,与普通函数的区别在于编译器如何将其组合到程...

5-程序员宅基地

package jp.co.test.logic;import java.io.File;import java.io.IOException;import java.util.List;import jp.co.test.common.Common;import jp.co.test.common.Constant;/** * モデル作成の基本処理クラス */

[C语言]二维图形基本几何变换的实现-程序员宅基地

任意给定一个三角形, 对它进行平移,放大,两种变换.(1)将三角形的坐标存放到数组中 (2)先画出原始的三角形,再进行变换,画出变换后的形状 (3)建议: a)左键双击屏幕,画出三角形 void CTranslationView::DrawPolyline(CPoint spt[],int n){RedrawWin

C/C++动态分配与释放内存的区别详细解析-程序员宅基地

转自http://www.jb51.net/article/41723.htm1. malloc()函数1.1 malloc的全称是memory allocation,中文叫动态内存分配。原型:extern void *malloc(unsigned int num_bytes); 说明:分配长度为num_bytes字节的内存块。如果分配成功则返回指向被分配内存的指针,分配失败返回

随便推点

Slackware Linux 切换Generic 内核_generic内核怎么换zen-程序员宅基地

说下怎么从默认的huge 内核切换到generic 内核(Slackware Linux 14.1 为例)_generic内核怎么换zen

call指令-X64X86指令区别-jmp指令-寄存器区别_jmp sub rsp, 8 call sub rsp, 8-程序员宅基地

  x64系统通用寄存器名称,第一个字母从“E”改为“R”,数量增加了8个,(R8-R15),增加了8个128位XMM寄存器(XMM寄存器用来优化代码)。  栈的基本入栈出栈操作和32位一样,需要注意就是在64位环境下,汇编指令对栈顶其值有要求,因此在VS编译器申请空间的时候,会尽力保证栈顶地址为对其值16。(被16整除) 在逆向中发现栈空间不使用的情况,可能为了实现对齐。  64位应用程序只有1种寄存器快速调用,前4个参数使用寄存器传递,超过4个参数就放到栈里,入栈的顺序是从右往左,前四个寄存器是固定的 _jmp sub rsp, 8 call sub rsp, 8

python操控微信 wxpy教程_wxpy python-程序员宅基地

一、首先安装wxpy库直接在pycharm输入命令即可pin install wxpy国内下载可能慢,推荐使用pip install -U wxpy -i "https://pypi.doubanio.com/simple/"二、基本命令1.导入登录模块from wxpy import *2.初始化机器人 扫码登陆bot = Bot()3.保存缓存 不用每次登录bot = Bot(cache_path=True)4.搜索好友my_fiend = bot.friends()_wxpy python

学习《LINUX就该这么学》第八天笔记_什么命令用于挂载文件系统,umount命令用于撤销已经什么的设备文件。-程序员宅基地

第五章 用户身份与文件权限一、su命令与sudo服务su命令可以解决切换用户身份的需求,使得当前用户在不退出登录的情况下,顺畅地切换到其他用户。sudo命令用于给普通用户提供额外的权限来完成原本root管理员才能完成的任务,格式为“sudo [参数] 命令名称”。总结来说,sudo命令具有如下功能:限制用户执行指定的命令:记录用户执行的每一条命令;配置文件(/etc/sudoers)..._什么命令用于挂载文件系统,umount命令用于撤销已经什么的设备文件。

Swift - 28 - 内部参数名和外部参数名-程序员宅基地

//: Playground - noun: a place where people can playimport UIKit// 外部参数的作用是为了让程序员调用代码的时候能清晰的看出所传参数代表的意思// 内部参数指的就是定义函数的时候所设定需要传入的参数func sayHello(nickName nickName:String, greeting...

Django Form表单组件详解_django中form组件详解-程序员宅基地

Django Form表单组件一.Forms组件二.传统写法三.使用Forms组件改进四.字段校验五.常用字段六.Django Form所有内置字段一.Forms组件使用Forms组件可以帮我们在前端生成form表单里面的一些标签,在后端可以进行一些数据校验功能:校验字段功能渲染标签功能渲染错误信息功能组件的参数配置局部钩子二.传统写法1.viewsdef register(request): error_msg = "" if request.method == _django中form组件详解

推荐文章

热门文章

相关标签