基于OpenCV的人脸签到系统

效果图

在这里插入图片描述

目录文件

在这里插入图片描述

camerathread.h 功能实现全写在.h里了

class CameraThread : public QThread
{
    Q_OBJECT
public:
    CameraThread()
    {
        //打开序号为0的摄像头
        m_cap.open(0);
        if (!m_cap.isOpened()) {
            qDebug() << "Error: Cannot open camera";
        }

        //判断是否有文件,人脸识别模型,检测和识别用的
        if(!m_cascada.load("D:/research/CV/Opencv/haarcascade_frontalface_alt2.xml"))
        {
            QMessageBox::information(NULL,"失败", "人脸识别模型装载失败");
        }
        //实例化定时器,子线程中数据传输到中线程并显示出来
        m_timer = new QTimer(this);
        //绑定时间信号及获取图像帧的图像
        connect(m_timer,SIGNAL(timeout()),this,SLOT(readFarme()));
        //大概每秒24帧
        //开始定时器
        m_timer->start(42);

        //打卡模块
        // 定义 FisherFaceRecognizer 模型,训练用的模型
        m_model = LBPHFaceRecognizer::create();
        // 加载训练好的模型,自己训练的模型
        m_model->read("MyFaceLBPHModel.xml");

        if (m_model.empty())
        {
            qDebug() << "Error: Failed to load model!";
        }
        else
        {
            qDebug() << "Model loaded successfully!";
        }

        //录入时候的定时器,录入大概几秒,获取二十张灰色图像并保存,等待训练
        //实例化定时器
        m_Very_timer = new QTimer(this);

        //数据库的初始化部分
        //链接数据库
        m_db = QSqlDatabase::addDatabase("QMYSQL");
        m_db.setHostName("localhost");  // 主机名
        m_db.setDatabaseName("face");  // 数据库名
        m_db.setUserName("root");  // 用户名
        m_db.setPassword("31415926");  // 密码

    }
    ~CameraThread()
    {
        //释放摄像头
        m_cap.release();
    }
    void run() override
    {


    }


    //图像数据类型转换
    QImage MatImageToQt(const cv::Mat &src)
    {
        if(src.type() == CV_8UC1)
        {
            QImage qImage(src.cols,src.rows,QImage::Format_Indexed8);
            qImage.setColorCount(256);
            for(int i = 0; i < 256; i ++)
            {
                qImage.setColor(i,qRgb(i,i,i));
            }
            uchar *pSrc = src.data;
            for(int row = 0; row < src.rows; row ++)
            {
                uchar *pDest = qImage.scanLine(row);
                memcmp(pDest,pSrc,src.cols);
                pSrc += src.step;
            }
            return qImage;
        }
        else if(src.type() == CV_8UC3)
        {
            const uchar *pSrc = (const uchar*)src.data;
            QImage qImage(pSrc,src.cols,src.rows,src.step,QImage::Format_RGB888);
            return qImage.rgbSwapped();
        }
        else if(src.type() == CV_8UC4)
        {
            const uchar *pSrc = (const uchar*)src.data;
            QImage qImage(pSrc, src.cols, src.rows, src.step, QImage::Format_ARGB32);
            return qImage.copy();
        }
        else
        {
            return QImage();
        }
    }

    //人脸检测
    void Check(Mat &image, Mat &gray)
    {
        //直方图均匀化(改善图像的对比度和亮度)
        Mat equalizedImg;
        equalizeHist(gray,equalizedImg);
        int flags = CASCADE_SCALE_IMAGE; //检测多个人

        Size minFeatureSize(30,30);
        float searchScaleFactor = 1.1f; //默认1.1倍
        int minNeighbors = 4;

        m_cascada.detectMultiScale(equalizedImg,m_faces,searchScaleFactor,minNeighbors,flags,minFeatureSize);
        m_current_people = m_faces.size();
        //检测到的个数
        //qDebug() << "检测到人脸的个数:" << m_faces.size() << endl;
        QString str;
        str.setNum(m_faces.size());
        //qDebug() << m_current_people << endl;

//        //画矩形框
        Mat face;
//        for(int i = 0; i < m_faces.size(); i++)
//        {
//            if(m_faces[i].height > 0 && m_faces[i].width >0 )
//            {
//                face = gray(m_faces[i]);
//                m_text_lb = Point(m_faces[i].x,m_faces[i].y);
//                rectangle(image, m_faces[i], Scalar(50, 50, 150), 2, 8, 0); //线太细了会导致在QLabel上面丢失线框


//            }
//            int iP = Predict(image);

//        }



        // 画矩形框和显示姓名
        for(int i = 0; i < m_faces.size(); i++)
        {
            string name; // 从数据库中获取姓名
            if(m_faces[i].height > 0 && m_faces[i].width >0 )
            {
                face = gray(m_faces[i]);
                m_text_lb = Point(m_faces[i].x,m_faces[i].y);
                rectangle(image, m_faces[i], Scalar(50, 50, 150), 2, 8, 0); // 画矩形框

                //灰度图
                Mat tImagGray;
                cvtColor(image, tImagGray, COLOR_BGR2GRAY);
                // 识别人脸
                int id = Predict(tImagGray);


                if (!m_db.open())
                {
                    qDebug() << "Failed to connect to database:" ;
                }

                // 执行查询语句
                QSqlQuery query;
                QString queryString = QString("SELECT name FROM staff_info WHERE num = %1").arg(id);
                if (!query.exec(queryString))
                {
                    qDebug() << "Failed to execute query:";
                    m_db.close();
                }

                // 处理查询结果
                if (query.next())
                {
                    name = query.value(0).toString().toUtf8().constData();
                    m_db.close();
                }
                else
                {
                    m_db.close();
                    name = "Unknown";
                }
            }
                qDebug() << name.data();
                // 在图像上显示姓名
                Point textPosition(m_faces[i].x, m_faces[i].y - 10); // 文本位置在矩形框上方一点
                putText(image, name.data(), textPosition, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255), 1, LINE_AA);


        }

        m_faces.clear();
    }



    // 裁剪出的脸部区域的图像
    cv::Mat cropFace(const cv::Mat& faceImg, const cv::Rect& faceRect) {
        // 不再进行颜色空间转换,直接使用输入的 faceImg
        cv::Mat frame_gray = faceImg;

        // 确保矩形区域在图像范围内
        if (faceRect.x >= 0 && faceRect.y >= 0 &&
            faceRect.x + faceRect.width <= frame_gray.cols &&
            faceRect.y + faceRect.height <= frame_gray.rows)
        {
            // 使用区域选择功能提取矩形区域
            cv::Mat faceROI = frame_gray(faceRect).clone(); // 使用 clone() 来复制图像区域
            return faceROI;
        }
        else
        {
            // 处理矩形区域超出图像范围的情况
            // 这里可以选择合适的处理方式,比如调整矩形区域的大小或者放弃处理该脸部区域
            return cv::Mat();
        }
    }



    // 在文本文件末尾添加数据
    void appendToTextFile(const QString& filename, const QString& data)
    {
        QFile file(filename);
        if (file.open(QIODevice::Append | QIODevice::Text))
        {
            QTextStream out(&file);
            out << data << "\n";
            file.close();
        }
        else
        {
            qDebug() << "Failed to open file for appending.";
        }
    }

    //预测功能,检测输入的图像中的人脸是否在训练集中
    int Predict(Mat src_image)
    {
        Mat face_test;
        int ispredict = 0;
        //截取的ROI人脸尺寸调整
        if (src_image.rows >= 120)
        {
            //改变图像大小,使用双线性差值
            resize(src_image, face_test, Size(92, 112));

        }
        //判断是否正确检测ROI
        if (!face_test.empty())
        {
            //测试图像应该是灰度图
            ispredict = m_model->predict(face_test);
        }
        //cout << ispredict << endl;
        return ispredict;
    }


signals:
    //向主线程传输图像
    void Set_image(QImage *image);
    //打卡之后设置ui部分和数据库部分
    void Send_Card_Data(QSqlDatabase *m_db,QString num);

public slots:
    //摄像头读取函数
    void readFarme()
    {
        //读取一帧图像
        m_cap.read(m_src_image) ;
        //处理一下数据,人脸检测
        //生成灰度图
        Mat dst_gray;
        cvtColor(m_src_image, dst_gray, COLOR_BGR2GRAY);
        Check(m_src_image, dst_gray);

        //转换图像数据类型
        QImage imag = MatImageToQt(m_src_image);

        //发送图像
        Set_image(&imag);
    }

    //执行二十次检测人脸并保存下来的功能
    void Verity()
    {
        //判断目前摄像头中的脸有几个
        if (!m_facenum.isEmpty())
        {
            //如果目前只有一个人
            if(m_current_people == 1)
            {
                qDebug() << m_executionCount;
                //裁剪出人脸区域
                Mat faceROI = cropFace(m_src_image, m_faces[0]);
                if (!faceROI.empty())
                {
                    // 调整裁剪后的脸部图像大小
                    cv::Mat resizedFace;
                    cv::resize(faceROI, resizedFace, cv::Size(92, 112));

                    // 将调整大小后的脸部图像存储在 m_src_image 中
                    m_src_image = resizedFace.clone();
                } else
                {
                    qDebug() << "裁剪后的脸部图像为空! ";
                }

                //存储的地址
                QString dir_str = "D:\\research\\CV\\Opencv\\facedata\\" + m_facenum + "\\" + QString::number(m_executionCount) + ".jpg";
                //用来判断这个地址的文件夹是否存在
                QString is_dir = "D:\\research\\CV\\Opencv\\facedata\\" + m_facenum;
                qDebug() << dir_str;
                QDir dir(is_dir);
                if (!dir.exists())
                {
                    if (!dir.mkpath("."))
                    {
                        qDebug() << "default ";
                    }
                }

                //扣的脸部的图像如果不为空
                if (!faceROI.empty())
                {
                    string filename = dir_str.toStdString();
                    // 将彩色图像转换为灰度图像
                    cv::Mat frame_gray;
                    cv::cvtColor(faceROI, frame_gray, cv::COLOR_BGR2GRAY);
                    //存储图像
                    imwrite(filename, frame_gray);
                    //在存储训练集需要的图片的地址的txt里也更新地址
                    QString csvsave = "D:/research/CV/Opencv/facedata/" + m_facenum + "/" + QString::number(m_executionCount) + ".jpg" + ";" + m_facenum ;
                    //存放要训练的模型的图片的地址的txt
                    QString csvfilename = "D:\\research\\CV\\Opencv\\at.txt";
                    //添加数据
                    appendToTextFile(csvfilename, csvsave);
                    m_executionCount++; // 每次执行计数器加一

                } else
                {
                    qDebug() << "脸部图像为空,无法写入文件! ";
                }

                //存储20张之后
                if (m_executionCount >= 20)
                {
                    m_executionCount = 0;
                    m_Very_timer->stop();
                }

            }

        }
        else
        {
            QMessageBox::about(NULL, "提示", "请输入工号!");
            m_executionCount = 0;
            m_Very_timer->stop();
            //delete m_Very_timer;
        }
    }

    //录入脸
    void Set_Verity_face(QString facenum,QString facename)
    {
        m_facenum = facenum;
        m_facename = facename;
        qDebug()<< QSqlDatabase::drivers();
        //判断数据库是否开着
        if (!m_db.open())
        {
            qDebug() << "Failed to connect to database:" ;
        } else
        {
            qDebug() << "Connected to database!";
        }

        //查找全部,看数量以便添加id
        QSqlQuery countQuery("SELECT COUNT(*) FROM staff_info");

        if (countQuery.exec() && countQuery.next())
        {
            int rowCount = countQuery.value(0).toInt(); // 获取数据条数
            int newId = rowCount + 1; // 新的 ID 就是数据条数加一

            QSqlQuery query;
            query.prepare("INSERT INTO staff_info (num, id, name) VALUES (:facenum, :faceid, :facename)");
            query.bindValue(":facenum", m_facenum);
            query.bindValue(":faceid", newId); // 使用新的 ID
            query.bindValue(":facename", m_facename);

            if (query.exec())
            {
                qDebug() << "Data inserted into database successfully!";
            }
            else
            {
                qDebug() << "Failed to insert data into database:" ;
            }
        }
        else
        {
            qDebug() << "Failed to retrieve row count from database:" ;
        }


        //关闭数据库
        m_db.close();

        qDebug() << "开始录入\n";

        //绑定时间信号及获取图像帧的图像
        connect(m_Very_timer, SIGNAL(timeout()), this, SLOT(Verity()));
        //开始定时器
        m_Very_timer->start(200);
    }

    //设置打卡部分
    void Set_Card()
    {
        Mat gray;
        cvtColor(m_src_image, gray, CV_BGR2GRAY); // 将输入图像转换为灰度图像
        vector<Rect> faces; // 存放检测到的人脸矩形的向量容器

        // 使用级联分类器检测人脸
        m_cascada.detectMultiScale(gray, faces, 1.1, 4, 0, Size(30, 30), Size(500, 500));

        // 遍历检测到的每张人脸
        for (size_t i = 0; i < faces.size(); i++)
        {
            Rect faceRect = faces[i]; // 获取当前人脸的矩形框
            // 从灰度图像中提取当前人脸区域
            Mat faceROI = gray(faceRect);

            // 检查人脸区域是否为空
            if (!faceROI.empty())
            {
                // 调用 Predict 函数对人脸进行预测
                int temp = Predict(faceROI);
                qDebug() << "预测结果:" << temp;

                // 发送打卡数据,然后让主线程在数据库中查找
                Send_Card_Data(&m_db,QString::number(temp));

            }
        }
        faces.clear();


    }


private:
    //声明opencv的视频类
    cv::VideoCapture m_cap;
    //更新显示的定时器
    QTimer *m_timer;
    //录入的定时器
    QTimer *m_Very_timer;
    //声明Mat类图像变量,存储当前摄像头前的图像
    cv::Mat m_src_image;
    //检测的分类器
    CascadeClassifier m_cascada;

    //矩形框的点
    Point m_text_lb;
    //人脸个数
    vector<Rect> m_faces;
    // 声明一个录入计数器变量
    int m_executionCount = 0;
    //工号和姓名
    QString m_facenum;
    QString m_facename;
    //识别的模型
    Ptr<LBPHFaceRecognizer> m_model;
    //当前镜头前识别出的人数
    int m_current_people = 0;
    //数据库
    QSqlDatabase m_db;
};

#endif // CAMERATHREAD_H

faceverify.cpp


#include "faceverify.h"
#include "ui_faceverify.h"

#include <QDebug>
#include <QCamera>              //管理摄像头的大类
#include <QCameraInfo>          //管理摄像头的设备表
#include <QCameraViewfinder>    //管理摄像头显示区域
#include <QCameraImageCapture>  //管理图片
#include <QDateTime>            //管理时间
#include <QString>              //管理字符串
#include "verityface.h"

#pragma execution_character_set("utf-8")

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


}

FaceVerify::~FaceVerify()
{
    delete m_cthread;
    delete ui;
}

void FaceVerify::Get_image(QImage *image)
{
    //设置图片大小和label的长宽一致
    QImage timage = image->scaled(ui->Camera->width(), ui->Camera->height(),Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    ui->Camera->setPixmap(QPixmap::fromImage(timage));
}

//打开摄像头
void FaceVerify::on_pushButton_Open_Camera_clicked()
{
    if(ui->pushButton_Open_Camera->text() ==  "打开摄像头")
    {
        m_cthread = new CameraThread();
        connect(m_cthread, &CameraThread::Set_image, this, &FaceVerify::Get_image);
        ui->pushButton_Open_Camera->setText("关闭摄像头");
    }
    else
    {

        disconnect(m_cthread, &CameraThread::Set_image, this, &FaceVerify::Get_image);
        delete m_cthread;
        m_cthread = nullptr;
        ui->Camera->clear();
        ui->pushButton_Open_Camera->setText("打开摄像头");

    }
}

//打卡
void FaceVerify::on_pushButton_Card_clicked()
{
    // 先断开之前的连接
    disconnect(this, &FaceVerify::Send_Card, m_cthread, &CameraThread::Set_Card);
    disconnect(m_cthread, &CameraThread::Send_Card_Data, this, &FaceVerify::Show_Data);

    // 连接信号和槽
    connect(this, &FaceVerify::Send_Card, m_cthread, &CameraThread::Set_Card);
    connect(m_cthread, &CameraThread::Send_Card_Data, this, &FaceVerify::Show_Data);

    // 发送信号
    emit Send_Card();

}
//打卡数据显示
void FaceVerify::Show_Data(QSqlDatabase *m_db,QString num)
{
    if (!m_db->open())
    {
        qDebug() << "Failed to connect to database:";
    }
    else
    {
        qDebug() << "Connected to database!";

        // 执行检查并插入数据
        QSqlQuery query;
        query.prepare("SELECT * FROM record_info WHERE num = :facenum AND DATE(mtime) = CURDATE()");
        query.bindValue(":facenum", num);

        if (query.exec())
        {
            if (query.next())
            {
                // 如果有记录,表示今天已经签到
                QMessageBox::information(NULL, tr("提示 "), tr("今天已签到 "));

                // 读取数据库中的数据并显示在textEdit_data中
                QString data;
                QSqlRecord record = query.record();
                int numField = record.indexOf("num"); // 获取字段索引
                int timeField = record.indexOf("mtime");

                // 遍历查询结果
                do
                {
                    QString num = query.value(numField).toString(); // 获取编号
                    QString time = query.value(timeField).toDateTime().toString("yyyy-MM-dd hh:mm:ss"); // 获取时间
                    data += "编号: " + num + ", 时间: " + time + "\n";
                } while (query.next());

                // 将数据显示在textEdit_data中
                ui->textEdit_data->setText(data);

            }
            else
            {
                QDateTime currentDateTime = QDateTime::currentDateTime();
                QString currentTimeString = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");

                qDebug() << "Current time:" << currentTimeString;
                // 如果没有记录,表示今天还未签到,执行插入操作
                query.prepare("INSERT INTO record_info (num, id, mtime) VALUES (:facenum, :faceid, :facemtime)");
                query.bindValue(":facenum", num);
                query.bindValue(":faceid", num); // 使用相同的 num 作为 id
                query.bindValue(":facemtime", currentTimeString);

                if (query.exec())
                {
                    QMessageBox::information(NULL, tr("提示 "), tr("签到成功 "));
                }
                else
                {
                    QMessageBox::critical(NULL, tr("错误 "), tr("签到失败: ") ); // 显示错误信息
                }
            }
        }
        else
        {
            QMessageBox::critical(NULL, tr("错误"), tr("查询数据失败: "));
        }

        // 关闭数据库连接
        m_db->close();
    }


}

//录入人脸
void FaceVerify::on_pushButton_face_clicked()
{
    //打开录入界面
    m_verifity = new VerityFace();
    connect(m_verifity, &VerityFace::Send_Face, this, &FaceVerify::GetFaceNum);
    m_verifity->show();
}

//训练模型
void FaceVerify::on_pushButton_Train_clicked()
{

    m_train = new train();
    connect(m_train, &train::finished, this, &FaceVerify::Train_Finish);
    m_train->run();

}
//模型训练完
void FaceVerify::Train_Finish()
{
    delete m_train;
    QMessageBox::information(NULL,"训练", "训练完成");
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity 实现原神中的元素反应

一、元素反应 原神中共有七种元素&#xff0c;分别是水、火、冰、岩、风、雷、草。这七种元素能互相作用 Demo下载&#xff1a;Download 元素反应表格图示&#xff0c;可能不够精准 /火水雷冰草岩风绽放原激化火/蒸发超载融化燃烧结晶扩散烈绽放/水蒸发/感电冻结/碎冰绽放结晶…

数据分析:甲基化分析-从DNA methylation的IDAT文件到CpG site的Beta values

介绍 DNA Methylation和疾病的发生发展存在密切相关&#xff0c;它一般通过CH3替换碱基5‘碳的H原子&#xff0c;进而调控基因的转录。常用的DNA methylation是Illumina Infinium methylation arrays&#xff0c;该芯片有450K和850K&#xff08;也即是EPIC&#xff09;。 该脚…

【canvas】前端创造的图片粒子动画效果:HTML5 Canvas 技术详解

前端创造的图片粒子动画效果&#xff1a;HTML5 Canvas 技术详解 我们将深入探讨如何通过 HTML5 的 Canvas 功能&#xff0c;将上传的图片转换成引人入胜的粒子动画效果。这种效果将图片分解成小粒子&#xff0c;并在用户与它们交互时产生动态变化。我们将分步骤详细解析代码&a…

LabVIEW专栏九、类的应用

一、类的应用 接上一章"类" 类在项目中&#xff0c;一般会在类的私有成员簇内&#xff0c;包含一个数据类型为参数类的队列。 例如网口类&#xff0c;里面实际会包含很多信息&#xff0c;有IP地址和端口等等参数。这些参数如果不放在队列引用中缓存下来&#xff0c;…

DevOps(十四)怎么实现Gitlab更新后Jenkins自动发布

目录 1、在 Jenkins 中安装 GitLab 插件 2、在 GitLab 中创建一个访问令牌(Access Token) 3、在 Jenkins 中配置 GitLab 连接 4、在 Jenkins 中创建一个新的任务(Job) 5、在 GitLab 中配置 Webhook 6、以下是一些补充说明和建议 持续集成的一个特点就是开发可以随时提交&…

微服务组件-反向代理(Nginx)

微服务组件-反向代理(Nginx) Nginx 基本概念 1、nginx是什么&#xff1f; ①、Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器同时也提供了IMAP/POP3/SMTP服务。它是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器&a…

TiDB 6.x 新特性解读 | Collation 规则

对数据库而言&#xff0c;合适的字符集和 collation 规则能够大大提升使用者运维和分析的效率。TiDB 从 v4.0 开始支持新 collation 规则&#xff0c;并于 TiDB 6.0 版本进行了更新。本文将深入解读 Collation 规则在 TiDB 6.0 中的变更和应用。 引 这里的“引”&#xff0c;…

Oracle 监控 SQL 精选 (一)

Oracle数据库的监控通常涉及性能、空间、会话、对象、备份、安全等多个层面。 有效的监控可以帮助 DBA 及时发现和解决问题&#xff0c;提高数据库的稳定性和性能&#xff0c;保障企业的数据安全和业务连续性。 常用的监控指标有&#xff1a; 性能指标&#xff1a; 查询响应时间…

产品推荐 | BittWare基于Altera Agilex“M FPGA的lA-860m加速卡

01 产品概述 BittWare的lA-860m是一款Altera Agilex“M系列FPGA卡&#xff0c;针对吞吐量和内存密集型应用进行了优化。M 系列 FPGA 具有广泛的内存层次结构&#xff0c;包括集成高带宽存储器 &#xff08;HBM2e&#xff09; 和硬内存片上网络 &#xff08;NoC&#xff09;&am…

【QT】ROS2 Humble联合使用QT教程

【QT】ROS2 Humble联合使用QT教程 文章目录 【QT】ROS2 Humble联合使用QT教程1. 安装ROSProjectManager插件2. 创建ROS项目3.一个快速体验的demoReference 环境的具体信息如下&#xff1a; ubunt 22.04ros2 humbleQt Creator 13.0.0ROS ProjectManager 13.0.0 本文建立在已经…

Vivado-IP-DDS and Testbench Learning

DDS内部结构 实现流程 首先新建一个工程&#xff0c;创建bd文件&#xff0c;添加DDS Compiler核&#xff0c;此处不多赘述 Block Design 在观测输出的信号时&#xff0c;需要将最高位符号位的信号取反&#xff0c;这样才能输出正弦波&#xff0c;否则输出的波形如下图所示 将t…

OpenStack云计算(十)——OpenStack虚拟机实例管理,增加一个计算节点并进行实例冷迁移,增加一个计算节点的步骤,实例冷迁移的操作方法

项目实训一 本实训任务对实验环境要求较高&#xff0c;而且过程比较复杂&#xff0c;涉及的步骤非常多&#xff0c;有一定难度&#xff0c;可根据需要选做。可以考虑改为直接观看相关的微课视频 【实训题目】 增加一个计算节点并进行实例冷迁移 【实训目的】 熟悉增加一个…

实验 1--SQL Server2008数据库开发环境

文章目录 实验 1--SQL Server2008数据库开发环境2.4.1 实验目的2.4.2 实验准备2.4.3 实验内容1.利用 SSMS 访问系统自带的Report Server 数据库。2.熟悉了解 SMSS对象资源管理器树形菜单相关选择项的功能。(1)右键单击数据库Report Server&#xff0c;查看并使用相关功能;(2)选…

K8s: 部署 kubernetes dashboard

部署 Dashboard K8s 官方有一个项目叫 dashboard&#xff0c;通过这个项目更方便监控集群的状态 官方地址: https://github.com/kubernetes/dashboard 通常我们通过命令行 $ kubectl get po -n kube-system 能够查看到集群所有的组件&#xff0c;但这样的方式比较不太直观 …

算法学习002-填数游戏 中小学算法思维学习 信奥算法解析 c++实现

目录 C填数游戏 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C填数游戏 一、题目要求 1、编程实现 在小学奥数中经常会看到一些填数字的游戏&#xff0c;如下图所示&#xff0c;其中每个…

【Web】第三次

【Web】第三次 1.完成学校官方网站页面制作2.使用动画完成过渡变换效果 1.完成学校官方网站页面制作 2.使用动画完成过渡变换效果 1.完成学校官方网站页面制作 html&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://…

OpenCV 实现重新映射

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 实现霍夫圆变换 下一篇 :OpenCV实现仿射变换 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 一个。使用 OpenCV 函数 cv&#xff1a;&#xff1a;remap 实现简单的重新…

Socket编程实验

文章目录 服务端&#xff1a;客户端&#xff1a;使用说明&#xff1a;封装后服务端&#xff1a;封装后客户端 听学弟学妹们反馈&#xff0c;好像老师发的socket编程实验指导里的代码跑不起来。 今天花了一大把时间写了下socket编程代码 现在附上能跑的c代码&#xff1a; 最重要…

nosql数据库 redis

一、介绍 1、redis与mysql的区别&#xff1a; Redis是一种基于键值对的内存数据库&#xff0c;数据存储在内存中&#xff0c;因此读写速度非常快。它支持多种数据结构&#xff0c;如字符串、哈希、列表等。 MySQL是一种关系型数据库&#xff0c;数据以表格的形式组织存储在磁…

12.6.1 实验5:IOS恢复

1、实验目的 通过本实验可以掌握&#xff1a; copy方式恢复IOS的步骤。TFTPDNLD方式恢复IOS的步骤。Xmodem方式恢复IOS的步骤。 2、实验拓扑 路由器IOS恢复的实验拓扑如下图所示。 3、实验步骤 如果工作中不慎误删除路由器IOS&#xff0c;或者升级了错误版本的IOS&#xff…