QT连接OpenCV库完成人脸识别

news2024/9/20 7:56:27

1.相关的配置

1> 该项目所用环境:qt-opensource-windows-x86-mingw491_opengl-5.4.0

2> 配置opencv库路径:

1、在D盘下创建一个opencv的文件夹,用于存放所需材料

2、在opencv的文件夹下创建一个名为:opencv3.4-qt-intall 文件夹

3、将资料中的opencv_library的install文件,复制到opencv3.4-qt-intall 文件夹中

4、将路径:D:\opencv\opencv3.4-qt-intall\install\x86\mingw\bin 放入电脑的系统路径中

3> 测试是否配置好

创建一个新的qt工程,将对应配置文件和头文件放入后,不报错就说明配置成功

2.关于图像处理的相关类和函数 

1> Mat类,图像容器

2> 读取图像

Mat imread( const String& filename, int flags = IMREAD_COLOR );
//功能:读取出图像
//参数:图像路径
//返回值:读取的图像

3> 命名展示图像的窗口 

void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
功能:命名一个图像窗口
参数1:窗口名称
参数2:窗体尺寸,默认为自适应大小
返回值:无

4> 展示图像 

void imshow(const String& winname, const ogl::Texture2D& tex);
//功能:展示图像
//参数1:要展示图像的窗口名称
//参数2:要展示的二维图像
//返回值:无
#include "widget.h"
#include <QApplication>

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

    //1、定义一个图像容器
    Mat src;

    //2、将图像加载进来
    //函数原型:Mat imread( const String& filename, int flags = IMREAD_COLOR );
    //参数:图像的路径
    //返回值:图像容器
    src = imread("D:/opencv/resource/age.jpg");

    //4、命名一个展示图像的窗口
    //namedWindow("Test");

    //5、展示图像
    //函数原型:void imshow(const String& winname, const ogl::Texture2D& tex);
    //参数1:要展示图像的窗口名称
    //参数2:要展示的图像
    //返回值:无
    imshow("Test", src);

    return a.exec();
}

 3.视频流相关类和函数

1> 视频流类:VideoCapture

2> 打开视频:

 virtual bool open(const String& filename);
 //参数:要打开视频的路径
 //返回值:成功返回true失败返回false

3> 打开摄像头只需在构造时,调用构造函数参数传递0即可

4> 读取视频流中图像

virtual bool read(OutputArray image);
功能:读取视频流中的图像
参数:图像容器
返回值:成功读取返回true,失败或者视频结束返回false

 5> 图像翻转

void flip(InputArray src, OutputArray dst, int flipCode);
//将图像进行旋转
//参数1:要处理的图像
//参数2:处理后的图像容器
//参数3:处理规则:0:表示沿x翻转,1表示沿y轴翻转,-1表示沿xy轴翻转

6> 休眠阻塞函数

int waitKey(int delay = 0);
功能:阻塞等待用户输入数据,如果delay=0,则一直等待
参数:毫秒数
返回值:在等待过程中用户按下键的值
#include "widget.h"
#include <QApplication>

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

    //1、定义视频流对象
    VideoCapture v(0);             //表明使用摄像头构造一个视频流对象

    //2、读取摄像头中的图像
    Mat src;                   //用于存放读取出来的图像

    //函数原型:virtual bool read(OutputArray image);
    //功能:从视频流中读取一张图像放入参数中
    //参数:图像容器
    //返回值:成功返回真,失败或者读取视频结束返回假
    while(v.read(src))
    {
        //将图像进行翻转
        //函数原型:void flip(InputArray src, OutputArray dst, int flipCode);
        //参数1:要翻转的图像
        //参数2:翻转后的图像容器
        //参数3:翻转规则:正数表示按y轴翻转,0表示按x轴翻转,负数表示按xy轴翻转
        flip(src, src, 1);

        //展示图像
        imshow("Test1", src);

        //加延时函数
        //函数原型:int waitKey(int delay = 0);
        //参数:等待时间
        //返回值:在等待期间用户按下的键盘的ascii值    ESC键对应的值为27
        if(waitKey(20)==27)
        {
            break;
        }
    }

    return a.exec();
}

4.图像处理

1> 灰度处理

void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
功能:转换图像色彩空间
//参数1:要转换的图像
//参数2:转变后图像容器
//参数3:转换规则:BGR to gray
返回值:无

2> 均衡化处理

void equalizeHist( InputArray src, OutputArray dst ); 
参数1:输入的灰度图像,必须是8-bit的单通道图像  
参数2:输出的图像 
图像直方图:对整个图像在灰度范围内的像素值(0-255)统计出现的频率,据此生成直方图,直 方图反应了图像的灰度分布情况。
#include "widget.h"
#include <QApplication>

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

    //1、定义视频流对象
    VideoCapture v(0);             //表明使用摄像头构造一个视频流对象

    //2、读取摄像头中的图像
    Mat src;                   //用于存放读取出来的图像
    Mat gray;                   //用于存储灰度图的图像容器
    Mat dst;                     //用于存储均衡化处理后的图像容器

    //函数原型:virtual bool read(OutputArray image);
    //功能:从视频流中读取一张图像放入参数中
    //参数:图像容器
    //返回值:成功返回真,失败或者读取视频结束返回假
    while(v.read(src))
    {
        //将图像进行翻转
        //函数原型:void flip(InputArray src, OutputArray dst, int flipCode);
        //参数1:要翻转的图像
        //参数2:翻转后的图像容器
        //参数3:翻转规则:正数表示按y轴翻转,0表示按x轴翻转,负数表示按xy轴翻转
        flip(src, src, 1);

        //3、将图像灰度处理
        //函数原型:void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
        //参数1:要转换的图像
        //参数2:转换后的图像容器
        //参数3:转换规则  CV_BGR2GRAY表示将bgr彩色图转换为gray灰度图
        //返回值:无
        cvtColor(src, gray, CV_BGR2GRAY);

        //4、对图像进行均衡化处理
        //函数原型:void equalizeHist( InputArray src, OutputArray dst );
        //参数1:要进行均衡化处理的图像,必须是单通道灰度图
        //参数2:均衡化处理后的图像容器
        //返回值:无
        equalizeHist(gray, dst);

        //展示彩色图像
        imshow("Test1", src);

        //展示灰度图像
        imshow("Test2", gray);

        //展示均衡化处理后的图像
        imshow("Test3", dst);

        //加延时函数
        //函数原型:int waitKey(int delay = 0);
        //参数:等待时间
        //返回值:在等待期间用户按下的键盘的ascii值    ESC键对应的值为27
        if(waitKey(20)==27)
        {
            break;
        }
    }

    return a.exec();
}

5.级联分类器 

1> opencv级联分类器工具类 : CascadeClassifier //struct Student

2> 加载级联分类器配置文件 : bool load( const String& filename )

参数1:分类器数据文件的名字

返回值:成功true,失败false

3> 找到人脸所在位置的矩形区域

void detectMultiScale(
const Mat& image, 
CV_OUT vector& objects,    //int arr[4]; 
double scaleFactor = 1.1,
int minNeighbors = 3, 
int flags = 0, 
Size ize = Size(24,24))
参数1:待检测灰度图像(数据少处理起来简单) 
参数2:被检测物体的矩形框向量( 人脸Rect矩形区域,其中objects.size()是人脸个数 ) 
参数3:前后两次相继的扫描中搜索窗口的比例系数,默认为1.1 即每次搜索窗口扩大10% 
参数4:构成检测目标的相邻矩形的最小个数 如果组成检测目标的小矩形的个数和小于 minneighbors - 1 都会被除 
参数5:若设置为CV_HAAR_DO_CANNY_PRUNING 函数将会使用Canny边缘检测来排除边缘过多 或过少的区域,,一般采用默认值0 
参数6:用来限制得到的目标区域的范围,一般检测人脸使用Size(24, 24)

4> 人脸部分的矩形区域显示出来

void rectangle(CV_IN_OUT Mat& img, Rect rec,
                          const Scalar& color, int thickness = 1,
                          int lineType = LINE_8, int shift = 0);
img:图像。 
rec:表征矩形的位置和长宽。 
color:线条颜色 (RGB) 。 
thickness:组成矩形的线条的粗细程度。 
line_type:线条的类型。 
shift:坐标点的小数点位数,0表示没有小数点。
#include "widget.h"
#include <QApplication>

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

    //1、定义视频流对象
    VideoCapture v(0);             //表明使用摄像头构造一个视频流对象

    //2、读取摄像头中的图像
    Mat src;                   //用于存放读取出来的图像
    Mat gray;                   //用于存储灰度图的图像容器
    Mat dst;                     //用于存储均衡化处理后的图像容器

    //5、实例化一个级联分类器的对象,用于找到图像中的人脸矩形区域
    CascadeClassifier c;
    //给类对象装载人脸识别模型
    //函数原型:bool load( const String& filename );
    //功能:给级联分类器对象,下载一个识别模型
    //参数:人脸识别模型的文件路径
    //返回值:成功下载返回真,失败返回假
    if(!c.load("D:/opencv/resource/haarcascade_frontalface_alt2.xml"))
    {
        QMessageBox::information(NULL,"失败", "人脸识别模型装载失败");
        return -1;
    }

    //定义容器存放人脸分类后的矩形框
    vector<Rect> faces;

    //函数原型:virtual bool read(OutputArray image);
    //功能:从视频流中读取一张图像放入参数中
    //参数:图像容器
    //返回值:成功返回真,失败或者读取视频结束返回假
    while(v.read(src))
    {
        //将图像进行翻转
        //函数原型:void flip(InputArray src, OutputArray dst, int flipCode);
        //参数1:要翻转的图像
        //参数2:翻转后的图像容器
        //参数3:翻转规则:正数表示按y轴翻转,0表示按x轴翻转,负数表示按xy轴翻转
        flip(src, src, 1);

        //3、将图像灰度处理
        //函数原型:void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
        //参数1:要转换的图像
        //参数2:转换后的图像容器
        //参数3:转换规则  CV_BGR2GRAY表示将bgr彩色图转换为gray灰度图
        //返回值:无
        cvtColor(src, gray, CV_BGR2GRAY);

        //4、对图像进行均衡化处理
        //函数原型:void equalizeHist( InputArray src, OutputArray dst );
        //参数1:要进行均衡化处理的图像,必须是单通道灰度图
        //参数2:均衡化处理后的图像容器
        //返回值:无
        equalizeHist(gray, dst);

        //6、使用级联分类器对象,获取人脸矩形区域
        //函数原型:void detectMultiScale( InputArray image,CV_OUT std::vector<Rect>& objects)
        //参数1:要进行识别的图像
        //参数2:对该图像识别后,的矩形框存放的数组容器
        c.detectMultiScale(dst, faces);

        //7、将上述得到的矩形框,全部都绘制到图像上
        for(int i=0; i<faces.size(); i++)
        {
            //将任意一个矩形框,全部都绘制到图像上
            //函数原型:void rectangle(CV_IN_OUT Mat& img, Rect rec,const Scalar& color, int thickness = 1)
            //参数1:要被绘制的图像
            //参数2:要绘制的矩形框
            //参数3:矩形框的颜色
            //参数4:矩形框的粗细
            //返回值:无
            rectangle(src, faces[i], Scalar(0,0,255), 2);
        }

        //8、像素反差
        for(int i=0; i<src.rows; i++)        //外层循环控制行数
        {
            for(int j=0; j<src.cols; j++)        //内层循环控制列数
            {
                //找到任意一个像素:src.at<Vec3b>(i,j)
                //找到任意一个像素中的通道中的值src.at<Vec3b>(i,j)[k]
                for(int k=0; k<3; k++)
                {
                    src.at<Vec3b>(i,j)[k] = 255 - src.at<Vec3b>(i,j)[k];  //对像素进行反差
                }

            }
        }

        //展示彩色图像
        imshow("Test1", src);

        //展示灰度图像
        imshow("Test2", gray);

        //展示均衡化处理后的图像
        imshow("Test3", dst);

        //加延时函数
        //函数原型:int waitKey(int delay = 0);
        //参数:等待时间
        //返回值:在等待期间用户按下的键盘的ascii值    ESC键对应的值为27
        if(waitKey(20)==27)
        {
            break;
        }
    }

    return a.exec();
}

6. 介绍 

机器学习的作用:根据提供的图片模型通过算法生成数据模型,从而在其它图片中查找相关的目 标。

级联分类器:是用来人脸识别。 在判断之前,我们要先进行学习,生成人脸的模型以便后续识别使用。

人脸识别器:判断是谁的面部。 FaceRecognizer类是opencv提供的人脸识别器基类,LBPHFaceRecognizer是根据LBPH算法实 现的识别器类,其中LBPHFaceRecognizer识别器支持在原有模型基础上继续学习(模型数据可以累 计)。

7.创建LBPHFaceRecognizer识别器对象

 所需的头文件:#include 、using namespace cv::face;
 创建空的人脸识别器对象:Ptr<FaceRecognizer> recognizer =
 LBPHFaceRecognizer::create();
 ​
 根据已有的模型创建人脸识别器对象,在创建人脸识别器的时候,需要一个已经学习好的模型文件:
 Ptr<FaceRecognizer> recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("模型文
 件.xml");

8.机器学习并更新模型

 容器:容器中装了n张人脸Mat对象,先采集脸,装到容器中,存储标签,人的身份证,每一张脸
 给一个编号:1 张三脸 2 李四脸 3 王五脸。
 功能函数1:void update(InputArrayOfArray src,InputArray labels)//机器学习并更新模型
 功能函数2:void train(InputArrayOfArrays src,InputArray labels);//只是学习,不更新
 //参数1src:图片模型数组 vector<Mat>
 //参数2labels:标签数组,每个模型识别后的标签vector<int>

9.保存模型

功能函数:void save(const String& filename);//参数1:模型文件的名字
例如:
recognizer->update(study_faces,study_label);//学习
recognizer->save("face.xml");//将学习的成果,保存到face.xml模型文件中,生成模型:
study_faces.clear();、study_labels.clear();

10.预测目标

判断这个人脸到底是谁。
功能函数:
void predict(InputArray src,  int &label,  double &confidence)
//参数1:预测图形 Mat src
//参数2::预测后的标签,学习时对应的标签
//参数3:预测出结果的可信度,数值越小可信度越高
例如:
int label = -1;//预测后的标签,学习时对应的标签
double confidence = 0;//可信度
Mat face = frame(faces[0]);//人脸区域
cvtColor(face,face,CV_BGR2GRAY);//更改色彩空间
cv::resize(face,face,Size(90,90));//设置人脸的大小
recognizer->predict(face,label,confidence); //预测,相当于识别人脸,预测出人脸是谁的
面部,label的值就那张脸对应的标签,如果预测不到,label的值是-1。

11.设置可信度

功能函数:void setThreshold(double val);
//参数1:预测可信度极值,预测可信度超出极值则预测失败。

12.完整项目代码 

.pro文件:

#-------------------------------------------------
#
# Project created by QtCreator 2023-09-04T19:10:16
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = 01_demo
TEMPLATE = app


SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

INCLUDEPATH += C:/opencv/opencv3.4-qt-install/install/include
INCLUDEPATH += C:/opencv/opencv3.4-qt-install/install/include/opencv
INCLUDEPATH += C:/opencv/opencv3.4-qt-install/install/include/opencv2
LIBS += C:/opencv/opencv3.4-qt-install/install/x86/mingw/lib/libopencv_*.a

头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#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_openCameraBtn_clicked();

    void on_closeCameraBtn_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("C:/opencv/resource/haarcascade_frontalface_alt.xml"))
    {
        QMessageBox::information(this,"失败","人脸识别模型装载失败");
        return;
    }

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

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

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

Widget::~Widget()
{
    delete ui;
}

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

//关闭摄像头按钮对应的槽函数
void Widget::on_closeCameraBtn_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);

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

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

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

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

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

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

        //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;               //以便于下一次录入

            //更新人脸模型
            //函数原型:CV_WRAP virtual void update(InputArrayOfArrays src, InputArray labels);
            //参数1:要进行更新的人脸数组
            //参数2:要更新的人脸标签数组
            //返回值:无
            recognizer->update(study_face,study_lab);

            //将数据模型保存到本地磁盘中
            recognizer->save("C:/opencv/resource/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("C:/opencv/resource/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);
                }
            }
        }
    }

}

//录入人脸按钮对应的槽函数
void Widget::on_inputFaceBtn_clicked()
{
    //启动人脸录入的定时器
    qDebug() << "开始进行人脸录入...";

    studyId = this->startTimer(60);

    //将按钮设置成不可用状态
    ui->inputFaceBtn->setEnabled(false);
    //将flag设置成1,表示正在录入人脸,不要进行人脸检测了
    flag = 1;

    count = 0;       //清空计数器

}

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

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

相关文章

Android Glide in RecyclerView,only load visible item when page return,Kotlin

Android Glide in RecyclerView&#xff0c;only load visible item when page return&#xff0c;Kotlin base on this article&#xff1a; Android Glide preload RecyclerView切入后台不可见再切换可见只加载当前视野可见区域item图片&#xff0c;Kotlin_zhangphil的博客…

L1和L2正则

L1和L2正则 L1正则常被用来进行特征选择&#xff0c;主要原因在于L1正则化会使得较多的参数为0&#xff0c;从而产生稀疏解&#xff0c;我们可以将0对应的特征遗弃&#xff0c;进而用来选择特征。一定程度上L1正则也可以防止模型过拟合。 L2正则&#xff1a; L1损失函数相比于…

口袋参谋:淘宝卖家如何对订单实现批量标旗?

​插旗在淘宝店铺里是经常能使用到的&#xff0c;如果淘宝卖家订单量太大&#xff0c;一个一个的标旗太过于繁琐&#xff0c;而且容易出错。 那么使用批量插旗工具&#xff0c;则可以大大节省卖家时间&#xff0c;提高工作效率&#xff01; 【批量插旗】功能&#xff1a; 一键…

基于blockqueue的生产和消费模型

线程篇下讲的是基于阻塞队列的生产者消费者模型。在学习这个之前我们先了解一些其他概念&#xff1a; 同步&#xff1a;在保证数据安全的条件下&#xff0c;让线程按某种特定的顺序依次访问临界资源。 通过上一节的代码我们实现了一个多线程抢票的程序&#xff0c;但结果显示…

Pytorch学习:卷积神经网络—nn.Conv2d、nn.MaxPool2d、nn.ReLU、nn.Linear和nn.Dropout

文章目录 1. torch.nn.Conv2d2. torch.nn.MaxPool2d3. torch.nn.ReLU4. torch.nn.Linear5. torch.nn.Dropout 卷积神经网络详解&#xff1a;csdn链接 其中包括对卷积操作中卷积核的计算、填充、步幅以及最大值池化的操作。 1. torch.nn.Conv2d 对由多个输入平面组成的输入信号…

ChatGPT AIGC 完成超炫酷的大屏可视化

大屏可视化一直各大企业进行数据决策的重要可视化方式,接下来我们先来看一下ChatGPT,AIGC人工智能帮我们实现的综合案例大屏可视化效果: 像这样的大屏可视化使用HTML,JS,Echarts就可以来完成,给ChatGPT,AIGC发送指令的同时可以将数据一起发送给ChatGPT。 第一段指令加数…

Direct3D绘制旋转立方体例程

初始化文件见Direct3D的初始化_direct3dcreate9_寂寂寂寂寂蝶丶的博客-CSDN博客 D3DPractice.cpp #include <windows.h> #include "d3dUtility.h" #include <d3dx9math.h>IDirect3DDevice9* Device NULL; IDirect3DVertexBuffer9* VB NULL; IDirect3…

【C语言】入门——结构体

目录 结构体 为什么有结构体&#xff1f; 1.结构体的声明 1.2结构体变量的访问和初始化 2.结构体成员的访问 结构体 struct 结构体类型 {//相关属性; }结构体变量; 结构体和数组不同&#xff0c;同一类型的数据的集合是数组&#xff1b; 结构体是多种类型的数据的集合&…

NSV60600MZ4T1G 双极型晶体管(BJT)学习总结

双极型晶体管的起源: 双极型晶体管是在1947年发明的&#xff0c;第一个晶体管是将两条具有尖锐端点的金属线与锗衬底(germanium substrate)形成点接触(point contact)&#xff0c;以今天的水准来看&#xff0c;此第一个晶体管虽非常简陋但它却改变了整个电子工业及人类的生活方…

CANdelaStudio CDD编写方法

本文是基于CANdelaStudio12.0讲解 一.把DTC从Excel导入cdd的方法 问题一&#xff1a;当导入DTC的xxx.cdi文件报如下红色错误 可能原因&#xff1a;在设置具有下拉框的属性的内容时&#xff0c;输入的内容不在下拉框列表中 解决办法:在.cddt文件中更新“”Error Code Table“”…

通达信趋向指标DMI公式详解

DMI指标(Directional Movement Index)也称趋向指标或动向指标&#xff0c;是用于衡量市场的趋势方向以及趋势强度的一种技术指标&#xff0c;由著名的技术派大师威尔斯威尔德(Welles Wilder)于1978年发表在《技术交易系统新概念》这本书中。威尔斯威尔德(Welles Wilder)这位大佬…

企微SCRM营销平台MarketGo-ChatGPT助力私域运营

一、前言 ChatGPT是由OpenAI&#xff08;开放人工智能&#xff09;研发的自然语言处理模型&#xff0c;其全称为"Conversational Generative Pre-trained Transformer"&#xff0c;即对话式预训练转换器。它是GPT系列模型的最新版本&#xff0c;GPT全称为"Gene…

springboot项目中application.properties无法变成小树叶问题解决

1.检查我们的resources目录的状态&#xff0c;看看是不是处在普通文件夹的状态&#xff0c;如果是的话&#xff0c;我们需要重新mark一下 右键点击文件夹&#xff0c;选择mark directory as → resources root 此时我们发现配置文件变成了小树叶 2.如果执行了上述方法还是不行…

[uniapp]踩坑日记 unexpected character > 1或‘=’>1 报错

在红色报错文档里下滑&#xff0c;找到Show more 根据提示看是缺少标签&#xff0c;如果不是缺少标签&#xff0c;看看view标签内容是否含有<、>、>、<号,把以上符合都进行以<号为例做{{“<”}}处理

超详细-Vivado配置Sublime+Sublime实现VHDL语法实时检查

目录 一、前言 二、准备工作 三、Vivado配置Sublime 3.1 Vivado配置Sublime 3.2 环境变量添加 3.3 环境变量验证 3.4 Vivado设置 3.5 配置验证 3.6 解决Vivado配置失败问题 四、Sublime配置 4.1 Sublime安装Package Control 4.2 Sublime安装VHDL插件 4.3 语法检查…

排序相关问题

本篇博客在B站做了内部分享,标题为「排序相关问题」 MySQL的ORDER BY有两种排序实现方式&#xff1a; 利用有序索引获取有序数据 (不得不进行)文件排序 在explain中分析时&#xff0c;利用有序索引获取有序数据显示Using index&#xff0c;文件排序显示Using filesort。 1. 能够…

macm1环境下jdk版本切换

macm1环境下jdk版本切换 本文目录 macm1环境下jdk版本切换下载jdk安装动态切换jdk终端生效全局生效 参考 下载jdk oracle官方源下载地址 https://www.oracle.com/java/technologies/downloads/#jdk17-mac Azul下载地址 https://www.azul.com/downloads/?packagejdk#download…

Autosar-Runnables(可运行实体)

文章目录 Runnable entities (简称Runnables)一、Runnables的定义二、Runnables的作用三、DaVinci配置总结Runnable entities (简称Runnables) 包含实际实现的函数(具体的逻辑算法或者操作) Runables由RTE周期性、或事件触发调用(如,当接收到数据、被操作调用) 一、Runna…

时序预测 | MATLAB实现ELM极限学习机时间序列预测未来

时序预测 | MATLAB实现ELM极限学习机时间序列预测未来 目录 时序预测 | MATLAB实现ELM极限学习机时间序列预测未来预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.MATLAB实现ELM极限学习机时间序列预测未来&#xff1b; 2.运行环境Matlab2018及以上&#xff0c;data为数…

MYSQL MHA实现故障转移和自动切换

目录 1、MHA理论&#xff1a; 1.1、MHA概述 1.2、MHA的组成&#xff1a; 1.3、特点&#xff1a; 1.4、传统的MySQL主从架构存在一些常见的问题&#xff1a; 1.5、MHA工作原理总结如下 1.6、 故障切换备选主库的算法&#xff1a; 2、 故障转移实验 2.1、搭建 MySQL MHA…