QT(9.5)QT连接OpenCV库完成人脸识别,c语言中的static和c++中的static的用法,在c和c++中const关键字的用法,Qt中基于TCP通信中的服务器和客户端的操作

news2024/11/26 1:52:08

1.QT完成人脸识别

pro文件:

头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include<opencv2/face.hpp>
#include <vector>
#include <map>
#include <QMessageBox>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTimerEvent>
#include<QtSerialPort/QtSerialPort>
#include<QtSerialPort/QSerialPortInfo>
using namespace  cv;
using namespace cv::face;
using namespace std;

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_openCamerBtn_clicked();

    void on_closeCamerBtn_clicked();

    void on_inputFaceBtn_clicked();

private:
    Ui::Widget *ui;
    /***************第一模块:关于摄像头的相关组件*******************/
    VideoCapture v;     //视频流对象
    Mat src;            //原图像
    Mat rgb;            //存放rgb图像,因为QT能识别的图像色彩空间位rgb
    Mat gray;           //灰度图
    Mat dst;            //均衡化图像
    CascadeClassifier c;//级联分类器
    vector<Rect>faces;  //存储人脸矩形区域的容器
    int cameraId;       //摄像头的定时器
    void timerEvent(QTimerEvent *event); //定时器事件处理函数

    /**************第二模块:录入人脸的先关组件*********************/
    Ptr<FaceRecognizer> recognizer;      //人脸识别器
    vector<Mat> study_face;              //要录入的人脸容器
    vector<int> study_lab;               //要录入的人脸的标签
    int studyId;                         //人脸录入的定时器
    int flag;                            //标识是否正在录入人脸
    int count;                           //记录学习的次数
    /*************第三模块:人脸检测相关组件*********************/
    int checkId;  //人脸检测定时器
};

#endif // WIDGET_H

自定义函数:

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    //将登录按钮设为不可用
    ui->loginBtn->setEnabled(false);

    //启动摄像头
    if(!v.open(0))
    {
        QMessageBox::information(this,"错误","打开摄像头失败");
        return;
    }

    //将级联分类器加载进来
    if(!c.load("D:/opencv/res/haarcascade_frontalface_alt2.xml"))
    {
        QMessageBox::information(this,"失败","人脸识别模型装载失败");
        return ;
    }

    //配置人脸识别器
    QFile file("D:/opencv/res/myFace.xml");
    //判断文件是否存在,如果存在则直接下载,如果文件不存在,则创建一个人脸识别器
    if(file.exists())
    {
        //人脸模型存在,直接下载
        recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("D:/opencv/res/myFace.xml");
    }else
    {
        //人脸不存在,则需要创建
        recognizer = LBPHFaceRecognizer::create();
    }

    //启动人脸检测的定时器
    checkId = this->startTimer(3000);

    //设置人脸识别的可信度
    recognizer->setThreshold(100);
    flag = 0;  //开始时就处于检测

}

Widget::~Widget()
{
    delete ui;

}

//打开摄像头对应的槽函数
void Widget::on_openCamerBtn_clicked()
{
    //启动定时器
    cameraId = this->startTimer(20);
    ui->cameraLab->show();

}

//关闭摄像头
void Widget::on_closeCamerBtn_clicked()
{
    //关闭定时器
    this->killTimer(cameraId);
    ui->cameraLab->hide();
}

//定时器事件处理函数
void Widget::timerEvent(QTimerEvent *event)
{
    //判断是哪个定时器到位
    if(event->timerId() == cameraId)
    {
        //1.从摄像头中读取一张图像
        v.read(src);//得到一张原图

        //2.将图像翻转
        flip(src,src,1);//按照y轴翻转

        //3.将src的bgr图像转换成rgb图像
        cvtColor(src,rgb,CV_BGR2RGB);

        //4.重新设置大小
        cv::resize(rgb,rgb,Size(311,201));

        //5.灰度处理
        cvtColor(rgb,gray,CV_RGB2GRAY);

        //6.均衡化处理
        equalizeHist(gray,dst);

        //7.使用级联分类器获取人脸矩形区域
        c.detectMultiScale(dst,faces);

        //8.将矩形框绘制到rgb图像上
        for(int i=0;i<(int)faces.size();i++)
        {
            rectangle(rgb,faces[i],Scalar(255,0,0));
        }

        //9.使用rgb图像,将Mat图构造出一个QT能识别的图像
        QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
        //功能:通过其他图像构造一个QImage图像
        //参数1:其他图像的数据
        //参数2:图像的宽度
        //参数3:图像的高度
        //参数4:每一行的字节数
        //参数5:图像格式,24位图,每一中颜色用8位表示

        //10.将图像展示到lab中
        ui->cameraLab->setPixmap(QPixmap::fromImage(img));
    }

    //判断是否是人脸录入定时器到位
    if(event->timerId() == studyId)
    {
        //判断ui界面是否有矩形框
        if(faces.empty()) return;

        //判断脸识别器是否存在
        if(recognizer.empty()) return;

        //提示正在录入人脸
        qDebug() << "正在录入人脸" ;

        //获取ui界面中矩形框框起来的人脸区域
        Mat face = src(faces[0]);

        //将该图像进行重新设置大小
        cv::resize(face,face,Size(100,100));

        //灰度处理
        cvtColor(face,face,CV_BGR2GRAY);

        //均衡化处理
        equalizeHist(face,face);

        //将人脸放入学习容器中
        study_face.push_back(face);
        study_lab.push_back(1);

        count++;//完成一次人脸的存放
        if(count == 50) //已经收集50张人脸进行学习
        {
            count = 0;//以于下一次录入

            //更新人脸模型
            //参数1:要进行更新的人脸数组
            //参数2:要更新的人脸标签数组
            //返回值:无
            recognizer->update(study_face,study_lab);

            //将数据模型保存到本地磁盘中
            recognizer->save("D:/opencv/res/myFace.xml");

            //殿后工作
            study_face.clear();   //清空人脸数组
            study_lab.clear();    //清空标签数组
            flag = 0;             //表明录入以及结束,可以进行人脸检测
            ui->inputFaceBtn->setEnabled(true); //按钮设置成可用状态
            this->killTimer(studyId); //关闭人脸录入的定时器
            QMessageBox::information(this,"成功","人脸录入成功");
        }


    }

    //判断是否是人脸检测的定时器到位
    if(event->timerId() == checkId)
    {
        qDebug() << "正在检测...";

        //判断是否处于检测
        if(flag == 0)
        {
            QFile file("D:/opencv/res/myFace.xml");
            if(file.exists())  //表明人脸模型存在的基础上进行识别
            {
               if(faces.empty() || recognizer->empty()) return;//ui界面无矩形框或者没有人脸识别器

                //到此表明可以进行检测
               Mat face = src(faces[0]);

               //重新设置大小,保持跟保存人脸时一致
               cv::resize(face,face,Size(100,100));

               //灰度处理
               cvtColor(face,face,CV_BGR2GRAY);

               //均衡化处理
               equalizeHist(face,face);

               //定义记录检测后返回结果的变量
               int lab = -1;         //返回图像的标签
               double conf = 0.0;    //返回图像的可信度

               //将该人脸进行预测
               recognizer->predict(face,lab,conf);

               qDebug() << "lab=" << lab << "conf=" << conf;

               //对人脸识别后的结果进行判断
               if(lab!= -1)
               {
                   ui->loginBtn->setEnabled("true");
                   QMessageBox::information(this,"成功","识别成功");
               }


            }
        }
    }
}

//录入人脸按钮对应的槽函数
void Widget::on_inputFaceBtn_clicked()
{
    //启动人脸录入的定时器
    qDebug() << "开始录入...";
    studyId = this->startTimer(30);

    //将按钮设置成不可用状态
    ui->inputFaceBtn->setEnabled(false);

    //将flag设置成1,表示正在录入人脸,不要进行人脸检测了
    flag = 1;
    count = 0;//清空计数器
}

主函数:

#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

ui界面

运行结果:(可进行人脸录入,人脸识别)

面试题1:

c语言中的static和c++中的static的用法:

在c语言中:

1.static修饰的全局变量作用域限制在当前文件,无法被外部文件所引用。2.static修饰的局部变量延长生命周期,但不改变作用域,同样无法被外部文件所引用。3.static修饰的指针不能指向auto类型的地址,因为static类型的指针先分配地址。4.static修饰函数使函数具有内部链接,只能在当前文件访问,避免了其他文件中的同名函数冲突。

在c++中:

1.static修饰的成员在文件编译时分配空间,不占用该成员的类对象中的空间,可以不实例化对象直接调用。2.static修饰成员函数时,该成员函数属于类中的,不属于类对象,可以不实例化对象直接通过类名加域限定符进行调用,该静态成员函数不能调用类中的非静态成员变量,只能调用静态成员变量。3.static修饰的成员函数相当于在类中定义了一个全局函数,对类中的同名非静态成员函数不构成函数重载,因为作用域的不同。4.static修饰的成员变量同样属于类,只在类中声明,必须在类外定义,所有类对象共享。未定义的静态成员变量默认值为0。5.static修饰的静态成员变量在被类的实例化对象调用时不占用类的内存空间,相当与在类中定义了一个全局变量,当多个类中都调用了静态成员变量时,相当于对静态成员变量的地址进行操作,一个类对象修改了其的值,其他所有类对象中的静态成员变量都相应改变。6.静态成员变量相对于全局变量,更体现了类的封装性。

面试题2:

在c和c++中const关键字的用法:

在c中:

1.const修饰的全局变量地址在堆区的只读段,不能修改变量的值,但需要定义时初始化。2.const修饰的局部变量值不能改变,地址在栈区。3.const修饰的指针时:当const在*左边时值不能改变,地址能改变。当const在*的右边是地址不能改变,值能改变。当const在*的两侧是地址和值都不能改变。

在c++中:

1.修饰的成员函数是常成员函数,不能修改数据成员。2.修饰的对象是常对象,所有数据成员都不能被改变,成对象只能调用常成员函数。非常对象可以调用常成员函数和非常成员函数,优先非常成员函数。常成员函数和非常成员函数构成函数重载,因为this指针类型不同。3.const修饰的变量可以用mutable关键字取消常属性,让其可以改变。

面试题3:

Qt中基于TCP通信中的服务器和客户端的操作:

服务器:

1.创建一个QTCPServer的类对象,作为一个服务器。

2.对该对象调用listen函数设置监听状态,可以监听指定ip地址,也可以监听所有主机地址,端口号可以指定也可以自动生成。

3.当有客户端发来连接请求时,服务器就会发射一个newConnect信号,我们可以将该信号连接到自定义槽函数进行操作逻辑操作。

4.在槽函数总可以调用nextPendingConnection函数来获取最新连接的客户端套接字的地址,将该套接字存到客户端容器中。

5.此时客户端与服务器已经建立连接请求,如果有客户端向服务器发来数据,客户端就会发射一个readyRead信号。

6.服务器可以用read,readLine,readALL函数来完成数据的读取。

7.向套接字中写数据,可以使用write函数完成。

8.用close函数关闭服务器.

客户端:

1.实例化一个QTCPSocket的类对象。

2.调用该对象的成员函数connectToHost连接到服务器,连接服务器时需要给定服务器的ip地址和端口号

3.如果连接服务器成功,那么该客户端就会自动发射一个connected的信号,我们可以将该信号连接到对应的槽函数中尽显逻辑操作

4.如果服务器有数据向客户端发来,那么客户端就会自动发射一个readyRead信号,我们可以在该信号对应的槽函数中处理数据。

5.可以使用read,readLine,readAll读取客户端套接字中的数据

6.可以使用write向服务器中发送数据

7.使用成员函数disConnectFromHost断开与服务器的连接

8.如果断开成功,套接字就会发射一个disconnected的信号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/977231.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STL】模拟实现map和set {map和set的封装;核心结构;插入和查找;红黑树的迭代器;STL中的红黑树结构}

模拟实现map和set map和set是红黑树的两种不同封装形式&#xff0c;底层使用同一颗泛型结构的红黑树&#xff0c;只是存储类型不同。set是红黑树的K模型&#xff0c;存储key&#xff1b;map是红黑树的KV模型&#xff0c;存储pair<key,value>。 下面的代码和讲解着重体现…

Vue进阶(三十三)Content-Security-Policy(CSP)详解

文章目录 一、前言二、XSS 攻击都有哪些类型&#xff1f;三、CSP介绍3.1 使用HTTP的 Content-Security-Policy头部3.2 使用 meta 标签 四、CSP 实施策略五、Vue中可使用的防XSS攻击方式六、拓展阅读 一、前言 作为前端工程师你真的了解 XSS 吗&#xff1f;越来越多超级应用基于…

预付费电表和断路器的连接方式及注意事项

随着智能电网技术的不断发展&#xff0c;预付费电表已经在我国得到了广泛应用。预付费电表不仅可以实现远程自动抄表、实时监控用电量等功能&#xff0c;还可以有效防止偷电行为&#xff0c;提高用电安全。断路器作为低压配电系统中的重要组成部分&#xff0c;具有保护电路、防…

详细介绍 弹性盒子(display:flex)

文章目录 什么是弹性盒子 如何使用弹性盒子flex系列flex-direction 对齐方向 水平对齐垂直对齐flex-wrap 换行flex-flowflex模型说明容器的属性 justify-content X轴对齐方式align-content Y轴对齐方式总结属性值Y轴对齐的另外一种&#xff1a;align-itemsalign-content和alig…

基于Springboot跟rabbitmq实现的死信队列

概述 RabbitMQ是流行的开源消息队列系统&#xff0c;使用erlang语言开发。为了保证订单业务的消息数据不丢失&#xff0c;需要使用到RabbitMQ的死信队列机制&#xff0c;当消息消费发生异常时&#xff0c;将消息投入死信队列中。但由于对死信队列的概念及配置不熟悉&#xff0…

自然语言处理实战项目17-基于多种NLP模型的诈骗电话识别方法研究与应用实战

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理实战项目17-基于NLP模型的诈骗电话识别方法研究与应用&#xff0c;相信最近小伙伴都都看过《孤注一掷》这部写实的诈骗电影吧&#xff0c;电影主要围绕跨境网络诈骗展开&#xff0c;电影取材自上万起真…

PPO代码研究(2)

好&#xff0c; 因为我没怎么看懂&#xff0c; 所以我决定再看一遍PPO的代码&#xff0c; 再研究一遍。 事实证明&#xff0c; 重复是一个非常好&#xff0c;非常好的方法。 学习方法。 世界上几乎没有任何新知识是你一遍就能学会的。 你只能学一遍&#xff0c;再来一遍&…

大剧院订座系统源码,大剧院订票,大剧院场馆租赁,大剧院订票系统完整源码

大剧院订座系统源码,大剧院订票&#xff0c;大剧院场馆租赁&#xff0c;大剧院订票系统完整源码 大剧院系统1、管理后台--系统说明2、订票小程序--系统说明3、验票端--系统说明4、系统源码说明 大剧院系统 1、管理后台–系统说明 项目管理&#xff1a;用于创建剧院演出项目 2…

【广州华锐互动】AR技术在配电系统运维中的应用

随着科技的不断发展&#xff0c;AR(增强现实)技术逐渐走进了我们的生活。在电力行业&#xff0c;AR技术的应用也为巡检工作带来了许多新突破&#xff0c;提高了巡检效率和安全性。本文将从以下几个方面探讨AR配电系统运维系统的新突破。 首先&#xff0c;AR技术可以实现虚拟巡检…

Qt应用开发(基础篇)——按钮基类 QAbstractButton

一、前言 QAbstractButton类&#xff0c;继承于QWidget&#xff0c;是Qt按钮小部件的抽象基类&#xff0c;提供按钮常用的功能。 QAbstractButton按钮基类&#xff0c;它的子类(pushbutton、checkbox、toolbutton等)处理用户操作&#xff0c;并指定按钮的绘制方式。QAbstractBu…

el-table中加图标文字提示

<el-table :data"tableData" style"width: 100%" max-height"250"><el-table-column fixed prop"aaa" label"日期" width"150" /><el-table-column prop"bbb" label"日期" wi…

英语语法基础--思维导图

思维导图通常用于可视化和整理信息&#xff0c;而英文语法非常广泛且复杂&#xff0c;无法在一个简单的思维导图中完整表示。然而&#xff0c;我可以提供一个简化版本的英文语法思维导图&#xff0c;列出一些主要的语法概念和部分示例。 请注意&#xff0c;这只是一个基本的概…

多个pdf怎么合并在一起?跟着我的步骤一起合并

多个pdf怎么合并在一起&#xff1f;利用PDF文档合并功能可以帮助您更有效地管理文件&#xff0c;将多个相关文件整合成一个文件&#xff0c;避免分散在多个文件中。此外&#xff0c;合并后的文件更便于共享和传输&#xff0c;因为只需共享一个文件而不是多个文件。虽然合并文件…

自学Python01-创建文件写入内容

此处省去安装和前言&#xff0c;需要两个东西 一个去下载安装python官方库 Welcome to Python.org 一个是编译器pycharm PyCharm 安装教程&#xff08;Windows&#xff09; | 菜鸟教程 PyCharm: the Python IDE for Professional Developers by JetBrains 第一节 练习print…

18--Elasticsearch

一 Elasticsearch介绍 1 全文检索 Elasticsearch是一个全文检索服务器 全文检索是一种非结构化数据的搜索方式 结构化数据&#xff1a;指具有固定格式固定长度的数据&#xff0c;如数据库中的字段。 非结构化数据&#xff1a;指格式和长度不固定的数据&#xff0c;如电商网站…

rocky(centos) 安装redis,并设置开机自启动

一、下载并安装 1、官网下载Redis 并安装 Download | RedisRedisYou can download the last Redis source files here. For additional options, see the Redis downloads section below.Stable (7.2)Redis 7.2 …https://redis.io/download/ 2、上传下载好的redis压缩包到 /…

电气工程中重要的测量术语:“kVRMS” | 百能云芯

在电气工程和电子领域&#xff0c;术语“kVRMS”至关重要。它是工程师和技术人员用来准确评估电气系统电压的关键测量方法。在这篇综合文章中&#xff0c;我们将深入探讨 kVRMS 的含义、其意义、应用。 kVRMS 代表“千伏均方根”。为了理解这个术语&#xff0c;我们来分解一下&…

【Java Web】统一处理异常

一个异常处理的ControllerAdvice类。它用于处理Controller注解的控制器中发生的异常。 具体代码功能如下&#xff1a; 导入相关类和方法。声明一个Logger对象&#xff0c;用于日志记录。使用ExceptionHandler注解标记handleException方法&#xff0c;用于处理所有异常。 -嘛在…

管网水位监测的必要性

城市燃气、桥梁、供水、排水、热力、电力、电梯、通信、轨道交通、综合管廊、输油管线等&#xff0c;担负着城市的信息传递、能源输送、排涝减灾等重要任务&#xff0c;是维系城市正常运行、满足群众生产生活需要的重要基础设施&#xff0c;是城市的生命线。基础设施生命线就像…

centos+jenkins+pycharm

思路&#xff1a;架构 一. 在centos上搭建jenkins环境 二. pycharm与gitee建立连接 三. 访问jenkins&#xff0c;添加任务 3.1 添加一个自由风格的任务 3.2 添加git项目路径及访问git的账号和密码 3.3 执行start.sh脚本 四. 浏览器访问jenkins执行任务