QT 系统学习 day06 ,摄像头,语音识别(语音转文字,文字转语音,Qt 的人脸识别系统),

news2024/10/6 2:24:43

1.调用摄像头,拍照,存储照片

1.摄像头文件

/******* 摄像头相关类 *****/
#include <QCamera> /*** 摄像头类 ***/
#include <QCameraInfo> /*** 系统摄像头属性类 ***/
#include <QCameraImageCapture> /*** 用于记录摄像头数据的类 ***/

2.定义对象,(写在 头文件类里面)

    QCamera *m_Camera; /*** 摄像机类对象 ***/
    QCameraImageCapture *CameraImageCapture; /*** 用于记录摄像头数据的类 ***/

3. 获取可用的摄像头 

函数: bool QCameraInfo::isNull() const        Returns true if this QCameraInfo is null or invalid. 

bool QCameraInfo::isNull()      如果此QCameraInfo为空或无效,则返回true。

QList<QCameraInfo> cameras = QCameraInfo::availableCameras();//获取可用摄像头设备列表
        int index = cameras.size();//判断可用的摄像头有几个
        for(int i=0;i<index;i++)
        {
            if(cameras.at(i).isNull() == false)
            {
                qDebug() << "有效摄像头:" << cameras.at(i).description();//摄像头的设备名称
                ui->comboBox->addItem(cameras.at(i).description()); //将摄像头添加到UI界面摄像头列表中
            }
        }

4.打开摄像头, 的步骤代码

/**** 摄像头初始化 ****/
        QCameraInfo camreinfo = QCameraInfo::defaultCamera(); /*** 获取系统默认摄像头 ***/
        if(camreinfo.isNull() == true)
        {
            QMessageBox::warning(this,"警告","系统没有可用摄像头");
            return ;
        }
        /**** 申请摄像头类空间 ****/
        m_Camera = new QCamera(camreinfo); // 直接使用系统默认的
        m_Camera->setCaptureMode(QCamera::CaptureStillImage);				//设置捕捉模式为静态帧(图片形式)
        m_Camera->setCaptureMode(QCamera::CaptureMode::CaptureViewfinder);	//将采集到取景器中
        m_Camera->setViewfinder((ui->VideoWidget)); //将摄像头数据输出到 UI 界面显示
        m_Camera->start(); //摄像头打开

重点: (不然你的视频不能播放)
 m_Camera->setViewfinder((ui->VideoWidget)); //将摄像头数据输出到 UI 界面显示

QCamera::setViewfinder(QVideoWidget *viewfinder)

可以看到我们 的成员是  QVideoWidget  ,所以我们需要把, QWidget 提升为   QVideoWidget .


 5.打开 摄像头记录类   准备拍照  (捕捉照片,保存图片)

/***** 将摄像头放入摄像头记录类中,方便拍照 ******/
        CameraImageCapture = new QCameraImageCapture(m_Camera);
        CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);
        /*********** 捕获信号函数 imageCaptured(int,QImage) 拍了一张照,发出该信号 ********/
        connect(CameraImageCapture,SIGNAL(imageCaptured(int,QImage)),this,SLOT(slot_CameraImageCapture(int,QImage)));//这个信号是捕获 图片

信号:

void QCameraImageCapture::imageCaptured(int id,const QImage&preview)

捕获请求id为的帧时发出的信号,但尚未处理和保存。可以向用户显示帧预览。

槽函数:

void Widget::slot_CameraImageCapture(int id, QImage image)
{
    ui->label->setPixmap(QPixmap::fromImage(image));//把捕获的照片存入 标签里面
}


void Widget::slot_pushButton_capture()
{
    CameraImageCapture->capture("D:\\QT\\hqyj_coding\\day06_camera\\gw.jpg");
}
//函数 capture 是保存图片, 参数是路径 + 名称

ui->设计界面,


头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
/******* 摄像头相关类 *****/
#include <QCamera> /*** 摄像头类 ***/
#include <QCameraInfo> /*** 系统摄像头属性类 ***/
#include <QCameraImageCapture> /*** 用于记录摄像头数据的类 ***/
#include <QMessageBox>
#include <QDebug> /*** debug 调试类 ****/

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

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

private:
    Ui::Widget *ui;
    QCamera *m_Camera; /*** 摄像机类对象 ***/
    QCameraImageCapture *CameraImageCapture; /*** 用于记录摄像头数据的类 ***/
public slots:
    void slot_pushButton_camrae_open();
    void slot_CameraImageCapture(int id,QImage image);
    void slot_pushButton_capture();
};

#endif // WIDGET_H

 .cpp 文件

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

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras();//获取可用摄像头设备列表
        int index = cameras.size();
        for(int i=0;i<index;i++)
        {
            if(cameras.at(i).isNull() == false)
            {
                qDebug() << "有效摄像头:" << cameras.at(i).description();//摄像头的设备名称
                ui->comboBox->addItem(cameras.at(i).description()); //将摄像头添加到UI界面摄像头列表中
            }
        }

        connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_camrae_open()));
        connect(ui->pushButton_2,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_capture()));
}

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


void Widget::slot_pushButton_camrae_open()
{
    if(ui->pushButton->text() == "打开摄像头")
    {
        /**** 摄像头初始化 ****/
        QCameraInfo camreinfo = QCameraInfo::defaultCamera(); /*** 获取系统默认摄像头 ***/
        if(camreinfo.isNull() == true)
        {
            QMessageBox::warning(this,"警告","系统没有可用摄像头");
            return ;
        }
        /**** 申请摄像头类空间 ****/
        m_Camera = new QCamera(camreinfo); // 直接使用系统默认的   /// 或者调用上面的可用设备, 上面不是有码?? 就是存入 comBox里面的数据 
        m_Camera->setCaptureMode(QCamera::CaptureStillImage);				//设置捕捉模式为静态帧(图片形式)
        m_Camera->setCaptureMode(QCamera::CaptureMode::CaptureViewfinder);	//将采集到取景器中
        m_Camera->setViewfinder((ui->VideoWidget)); //将摄像头数据输出到 UI 界面显示
        m_Camera->start(); //摄像头打开

        ui->pushButton->setText("关闭摄像头");
        ui->pushButton_2->setEnabled(true);

        /***** 将摄像头放入摄像头记录类中,方便拍照 ******/
        CameraImageCapture = new QCameraImageCapture(m_Camera);
        CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);
        /*********** 捕获信号函数 imageCaptured(int,QImage) 拍了一张照,发出该信号 ********/
        connect(CameraImageCapture,SIGNAL(imageCaptured(int,QImage)),this,SLOT(slot_CameraImageCapture(int,QImage)));
    }
    else
    {
        delete m_Camera; //释放他的空间
        delete CameraImageCapture; //释放他的空间

        ui->pushButton->setText("打开摄像头");
        ui->pushButton_2->setEnabled(false);
    }
}

void Widget::slot_CameraImageCapture(int id, QImage image)
{
    ui->label->setPixmap(QPixmap::fromImage(image));
}

void Widget::slot_pushButton_capture()
{
    CameraImageCapture->capture("D:\\QT\\hqyj_coding\\day06_camera\\gw.jpg");
}



2.关于 阿里云 的人脸识别运用 (加载图片(注册),对比 )

1. 和上面差不多,只是加了 , HTTP  的网络请求 模式, 

2.建立信号, 

 connect(m_http,SIGNAL(finished(QNetworkReply*)),this,SLOT(slot_http_finished(QNetworkReply*)));

//有信号可以读取的时候,调用槽函数

3. 第一步获取    发送请求     得到访问_打开的命令 和 状态码,

void Camera::slot_http_finished(QNetworkReply *Reply)
{
    // 响应的状态码为 200 , 表示请求成功
    int stat = Reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    QByteArray Reply_data = Reply->readAll();//读取网站的访问命令
    qDebug() << "Reply_data = " << Reply_data << endl;
    if(stat == 200) /*** 成功数据 ***/
    {
        //获取响应信息
        QByteArray byteArray = QString(Reply_data).toUtf8();//把数据转型
        QJsonDocument JsonDocument = QJsonDocument::fromJson(byteArray); //转为JSON格式字符串
        if(JsonDocument.isObject() == true)
        {
            QJsonObject JsonObject = JsonDocument.object();
            if(JsonObject.find("access_token") != JsonObject.end())
            {
                access_token = JsonObject["access_token"].toString();
                qDebug() << "access_token:" << access_token << endl;
            }
        }
    }
}

4.之后包括,注册和 搜索功能, 首先,我们的 讲 搜索功能 

百度云技术文档 

搜索


void Camera::slot_pushButton_find()
{
    /**** 获取用户输入的信息 *****/
    QString group = ui->comboBox_group->currentText();
    QString ID = ui->lineEdit_ID->text();
    QString name = ui->lineEdit_user_info->text();

    /***** 组装http访问百度 *****/
    QString baidu = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=%1";
    QString url = baidu.arg(access_token);
    /**** 图片转码为BASE64编码 ****/
    QImage Image = ui->label_pixmap->pixmap()->toImage(); //获取 QLabel 标签的图片

    QByteArray data; /*** 用于存储图片的二进制数据 ***/

    QBuffer buffer(&data); /*** 将 data 作为缓冲区对象 ****/
    Image.save(&buffer,"png"); /***将图片保存到 buf -> data 缓存区 为 png 格式 ***/

    QString buf = data.toBase64(); /** BASE64转码 **/
    /*** 组装JSON数据 ****/
    QJsonObject json;

    json["image"] = buf;
    json["image_type"] = "BASE64";
    json["group_id_list"] = "Student,Teather"; //多组使用逗号隔开

    /** 注意:人脸注册完毕后,生效时间一般为5s以内,之后便可以进行人脸搜索或认证操作 **/

    /**** HTTP 请求POST 百度 ****/
    QNetworkRequest Request(url);
    Request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");   //请求头 类型 JSON 格式

    QByteArray byte = QJsonDocument(json).toJson(QJsonDocument::Compact); //将JSON类内容转为字符串方便发送
    /**** 执行post请求 ****/
    m_http->post(Request,byte);
}

5.注册功能:

百度云技术文档


void Camera::slot_pushButton_regiset()
{
    /**** 获取用户输入的信息 *****/
    QString group = ui->comboBox_group->currentText();
    QString ID = ui->lineEdit_ID->text();
    QString name = ui->lineEdit_user_info->text();

    /***** 组装http访问百度 *****/
    QString baidu = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=%1";
    QString url = baidu.arg(access_token);
    /**** 图片转码为BASE64编码 ****/
    QImage Image = ui->label_pixmap->pixmap()->toImage(); //获取 QLabel 标签的图片

    QByteArray data; /*** 用于存储图片的二进制数据 ***/

    QBuffer buffer(&data); /*** 将 data 作为缓冲区对象 ****/
    Image.save(&buffer,"png"); /***将图片保存到 buf -> data 缓存区 为 png 格式 ***/

    QString buf = data.toBase64(); /** BASE64转码 **/
    /*** 组装JSON数据 ****/
    QJsonObject json;

    json["image"] = buf;
    json["image_type"] = "BASE64";
    json["group_id"] = group;
    json["user_id"] = ID;
    json["user_info"] = name;

    /** 注意:人脸注册完毕后,生效时间一般为5s以内,之后便可以进行人脸搜索或认证操作 **/

    /**** HTTP 请求POST 百度 ****/
    QNetworkRequest Request(url);
    Request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");   //请求头 类型 JSON 格式

    QByteArray byte = QJsonDocument(json).toJson(QJsonDocument::Compact); //将JSON类内容转为字符串方便发送
    /**** 执行post请求 ****/
    m_http->post(Request,byte);
}


所有的代码 (自己去加  百度云的  密钥, 私钥 )(用别人的有危险, 百度云有免费的,只要自己注册)

ui 界面设计

头文件 

#ifndef CAMERA_H
#define CAMERA_H

#include <QMainWindow>
/******* 摄像头相关类 *****/
#include <QCamera> /*** 摄像头类 ***/
#include <QCameraInfo> /*** 系统摄像头属性类 ***/
#include <QCameraImageCapture> /*** 用于记录摄像头数据的类 ***/

#include <QDebug> /*** debug 调试类 ****/
/******* 网络相关类 ****/
#include <QNetworkAccessManager> /** 网络访问类 ***/
#include <QNetworkReply> /** 网络数据结果类 ***/

/******* QJSON 相关类 *****/
#include <QJsonDocument>
#include <QJsonObject>


QT_BEGIN_NAMESPACE
namespace Ui { class Camera; }
QT_END_NAMESPACE

class Camera : public QMainWindow
{
    Q_OBJECT

public:
    Camera(QWidget *parent = nullptr);
    ~Camera();

private:
    Ui::Camera *ui;
    QCamera *m_Camera; /*** 摄像机类对象 ***/
    QCameraImageCapture *CameraImageCapture; /*** 用于记录摄像头数据的类 ***/
    QNetworkAccessManager *m_http; /**网络访问对象 **/
    /***** 百度人脸库秘钥 ****/
    QString AppID = "";
    QString API_Key = "";
    QString Secret_Key = "";
    QString access_token = "";
public slots:
    void slot_pushButton_camrae_open();
    void slot_CameraImageCapture(int id,QImage image);
    void slot_pushButton_capture();
    void slot_http_finished(QNetworkReply* Reply);
    void slot_pushButton_regiset();
    void slot_pushButton_find();
};
#endif // CAMERA_H

.cpp

#include "camera.h"
#include "ui_camera.h"
#include <QMessageBox>
#include <QBuffer>
Camera::Camera(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::Camera)
{
    ui->setupUi(this);
    /****  获取系统可用摄像头列表 ****/
    QList<QCameraInfo> cameras = QCameraInfo::availableCameras();//获取可用摄像头设备列表
    int index = cameras.size();
    for(int i=0;i<index;i++)
    {
        if(cameras.at(i).isNull() == false)
        {
            qDebug() << "有效摄像头:" << cameras.at(i).description();//摄像头的设备名称
            ui->comboBox->addItem(cameras.at(i).description()); //将摄像头添加到UI界面摄像头列表中
        }
    }


    connect(ui->pushButton_camrae_open,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_camrae_open()));
    connect(ui->pushButton_capture,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_capture()));

    /****** HTTP网络访问类初始化 *****/
    m_http = new QNetworkAccessManager(this);

    connect(m_http,SIGNAL(finished(QNetworkReply*)),this,SLOT(slot_http_finished(QNetworkReply*)));
    QString url("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2&");
    url = url.arg(API_Key,Secret_Key);

    m_http->get(QNetworkRequest(QUrl(url)));
    /****** 按钮发送 http 的 post 请求 ******/
    connect(ui->pushButton_regiset,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_regiset()));
    connect(ui->pushButton_find,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_find()));
}

void Camera::slot_pushButton_find()
{
    /**** 获取用户输入的信息 *****/
    QString group = ui->comboBox_group->currentText();
    QString ID = ui->lineEdit_ID->text();
    QString name = ui->lineEdit_user_info->text();

    /***** 组装http访问百度 *****/
    QString baidu = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=%1";
    QString url = baidu.arg(access_token);
    /**** 图片转码为BASE64编码 ****/
    QImage Image = ui->label_pixmap->pixmap()->toImage(); //获取 QLabel 标签的图片

    QByteArray data; /*** 用于存储图片的二进制数据 ***/

    QBuffer buffer(&data); /*** 将 data 作为缓冲区对象 ****/
    Image.save(&buffer,"png"); /***将图片保存到 buf -> data 缓存区 为 png 格式 ***/

    QString buf = data.toBase64(); /** BASE64转码 **/
    /*** 组装JSON数据 ****/
    QJsonObject json;

    json["image"] = buf;
    json["image_type"] = "BASE64";
    json["group_id_list"] = "Student,Teather"; //多组使用逗号隔开

    /** 注意:人脸注册完毕后,生效时间一般为5s以内,之后便可以进行人脸搜索或认证操作 **/

    /**** HTTP 请求POST 百度 ****/
    QNetworkRequest Request(url);
    Request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");   //请求头 类型 JSON 格式

    QByteArray byte = QJsonDocument(json).toJson(QJsonDocument::Compact); //将JSON类内容转为字符串方便发送
    /**** 执行post请求 ****/
    m_http->post(Request,byte);
}


void Camera::slot_pushButton_regiset()
{
    /**** 获取用户输入的信息 *****/
    QString group = ui->comboBox_group->currentText();
    QString ID = ui->lineEdit_ID->text();
    QString name = ui->lineEdit_user_info->text();

    /***** 组装http访问百度 *****/
    QString baidu = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=%1";
    QString url = baidu.arg(access_token);
    /**** 图片转码为BASE64编码 ****/
    QImage Image = ui->label_pixmap->pixmap()->toImage(); //获取 QLabel 标签的图片

    QByteArray data; /*** 用于存储图片的二进制数据 ***/

    QBuffer buffer(&data); /*** 将 data 作为缓冲区对象 ****/
    Image.save(&buffer,"png"); /***将图片保存到 buf -> data 缓存区 为 png 格式 ***/

    QString buf = data.toBase64(); /** BASE64转码 **/
    /*** 组装JSON数据 ****/
    QJsonObject json;

    json["image"] = buf;
    json["image_type"] = "BASE64";
    json["group_id"] = group;
    json["user_id"] = ID;
    json["user_info"] = name;

    /** 注意:人脸注册完毕后,生效时间一般为5s以内,之后便可以进行人脸搜索或认证操作 **/

    /**** HTTP 请求POST 百度 ****/
    QNetworkRequest Request(url);
    Request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");   //请求头 类型 JSON 格式

    QByteArray byte = QJsonDocument(json).toJson(QJsonDocument::Compact); //将JSON类内容转为字符串方便发送
    /**** 执行post请求 ****/
    m_http->post(Request,byte);
}





void Camera::slot_http_finished(QNetworkReply *Reply)
{
    qDebug()<<"这里输出";
    // 响应的状态码为 200 , 表示请求成功
    int stat = Reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    QByteArray Reply_data = Reply->readAll();
    qDebug() << "Reply_data = " << Reply_data << endl;
    ui->textEdit_JSON->setText(QJsonDocument::fromJson(Reply_data).toJson()); //将其转为JSON字符串
    if(stat == 200) /*** 成功数据 ***/
    {
        //获取响应信息
        QByteArray byteArray = QString(Reply_data).toUtf8();
        QJsonDocument JsonDocument = QJsonDocument::fromJson(byteArray); //转为JSON格式字符串
        if(JsonDocument.isObject() == true)
        {
            QJsonObject JsonObject = JsonDocument.object();
            if(JsonObject.find("access_token") != JsonObject.end())
            {
                access_token = JsonObject["access_token"].toString();
                qDebug() << "access_token:" << access_token << endl;
            }
        }
    }
}



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

void Camera::slot_pushButton_camrae_open()
{
    if(ui->pushButton_camrae_open->text() == "打开摄像头")
    {
        /**** 摄像头初始化 ****/
        QCameraInfo camreinfo = QCameraInfo::defaultCamera(); /*** 获取系统默认摄像头 ***/
        if(camreinfo.isNull() == true)
        {
            QMessageBox::warning(this,"警告","系统没有可用摄像头");
            return ;
        }
        /**** 申请摄像头类空间 ****/
        m_Camera = new QCamera(camreinfo); // 直接使用系统默认的
        m_Camera->setCaptureMode(QCamera::CaptureStillImage);				//设置捕捉模式为静态帧(图片形式)
        m_Camera->setCaptureMode(QCamera::CaptureMode::CaptureViewfinder);	//将采集到取景器中
        m_Camera->setViewfinder(ui->VideoWidget); //将摄像头数据输出到 UI 界面显示
        m_Camera->start(); //摄像头打开

        ui->pushButton_camrae_open->setText("关闭摄像头");
        ui->pushButton_capture->setEnabled(true);

        /***** 将摄像头放入摄像头记录类中,方便拍照 ******/
        CameraImageCapture = new QCameraImageCapture(m_Camera);
        CameraImageCapture->setCaptureDestination(QCameraImageCapture::CaptureToFile);
        /*********** 捕获信号函数 imageCaptured(int,QImage) 拍了一张照,发出该信号 ********/
        connect(CameraImageCapture,SIGNAL(imageCaptured(int,QImage)),this,SLOT(slot_CameraImageCapture(int,QImage)));
    }
    else
    {
        delete m_Camera; //释放他的空间
        delete CameraImageCapture; //释放他的空间

        ui->pushButton_camrae_open->setText("打开摄像头");
        ui->pushButton_capture->setEnabled(false);
    }
}



void Camera::slot_CameraImageCapture(int id, QImage image)
{
    ui->label_pixmap->setPixmap(QPixmap::fromImage(image));
}

void Camera::slot_pushButton_capture()
{
    CameraImageCapture->capture("王老师.jpg");
}






3. 文字转语音  录音,播放录音

1.首先在。pro 文件里面添加这个   (文字转语音的模块)

2.头文件

/******** 音频相关类 *********/
#include <QAudioDeviceInfo> //音频属性类
#include <QAudioFormat> //音频参数
#include <QAudioInput>  //音频输入
#include <QAudioOutput> //音频输出
/******** 文件相关类 **********/
#include <QFile>
/******** 文字转语音类 ********/
#include <QTextToSpeech>

3.建立对象

 QAudioInput *m_AudioInput;//音频输入
    QAudioOutput *m_AudioOutput;//音频输出
    QFile *m_file;//文件对象
    QTextToSpeech *m_speech;//文字转语音对象

4.获取电脑上的音频输入,输出设备


    /******* 获取系统可用的音频设备 ********/
    QList<QAudioDeviceInfo> AudioDevice_Outputs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
    for(int i = 0; i < AudioDevice_Outputs.size() ; i++)
    {
        QString name = AudioDevice_Outputs[i].deviceName();//获取名字
        ui->comboBox_audio_ouput->addItem(name);//写入 ui 设计界面的设计框中
    }

    QList<QAudioDeviceInfo> AudioDevice_Inputs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    for(int i = 0; i < AudioDevice_Inputs.size() ; i++)
    {
        QString name = AudioDevice_Inputs[i].deviceName();//获取名字
        ui->comboBox_audio_input->addItem(name);//写入 ui 设计界面的设计框中
    }

5.配置音频参数  (好被识别,)

QAudioFormat format;
    format.setSampleRate(16000);	//设置采样率:16000MHz
    format.setChannelCount(1);		//设置采集通道数:1通道
    format.setSampleSize(16);		//设置样本大小:16比特
    format.setCodec("audio/pcm");	//设置录音格式为:pcm格式

6.检测输入设备是否可以使用, 我们默认使用系统默认的输入设备

QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); /** 使用默认输入 ***/
    if(info.isFormatSupported(format) == false)	//检测配置是否支持该音频设备
    {
        format = info.nearestFormat(format);	//只用最接近配置的音频配置
    }

7.实列化对象,打开空间音频 准备 存入数据

/****** 申请音频空间 *****/
    m_AudioInput = new QAudioInput(format,this);
    m_AudioOutput = new QAudioOutput(format,this);

8.准备文字转 音频的函数

 /***** 打印电脑的TTS语音引擎 *****/
    QStringList TextToSpeechs = QTextToSpeech::availableEngines();
    for(QString text : TextToSpeechs)
    {
        qDebug() << "语音引擎:" << text << endl;
    }

    m_speech = new QTextToSpeech(this); //文字转语音对象实列化

9.录制音频


void Audio::slot_pushButton_input() /*** 录制音频 ***/
{
    if(ui->pushButton_input->text() == "开始录制")
    {
        m_file = new QFile("./录音.wav");//音乐文件实列化 ,开辟空间
        m_file->open(QIODevice::ReadWrite | QIODevice::Truncate);//打开文件,没有创造, 可读可写
        if(m_file->isOpen() == false){ //打开失败
            delete m_file;
            return ;
        }
        m_AudioInput->start(m_file);//开始录制

        ui->pushButton_input->setText("停止录制");
    }
    else if(ui->pushButton_input->text() == "停止录制")
    {
        m_AudioInput->stop();//关闭录制
        m_file->close(); //关闭文件
        ui->pushButton_input->setText("开始录制");
    }
}

10.播放音频

void Audio::slot_pushButton_output()
{
    m_file = new QFile("./录音.wav");
    m_file->open(QIODevice::ReadWrite);
    if(m_file->isOpen() == false){ //打开失败
        delete m_file;
        return ;
    }

    m_AudioOutput->start(m_file);//播放音频
}

11.当文件播放完成 ,删除文件, (包含信号   连接函数)

void Audio::slot_AudioOutput(QAudio::State state)
{
    if(state == QAudio::IdleState)//状态播放完成
    {
        m_AudioOutput->stop();
        delete m_file;
    }
}

12.文字转语音,(需要系统自带的tts   的语音翻译工具)(文本转语音)

void Audio::slot_pushButton_transition()//转化函数
{
    QString text = ui->lineEdit_Text->text();//获取文字
    m_speech->setVolume(1);//播放音量 最大 1  最小 0
    m_speech->say(text);//播放获取的文字
}

13.假如你的  tts不行 不能 文字转语音采用下面这种方法,百度云直接申请文字转语音,

http://tsn.baidu.com/text2audio?lan=zh&ctp=1&cuid=abcdxxx&tok=1.a6b7dbd428f731035f771b8d****.86400.1292922000-2346678-124328&tex=%e7%99%be%e5%ba%a6%e4%bd%a0%e5%a5%bd&vol=9&per=0&spd=5&pit=5&aue=3
// 这是一个正常MP3的下载url
// tex在实际开发过程中请urlencode2次

代码:

 QString text=ui->lineEdit_Text->text();
  QByteArray url="http://tsn.baidu.com/text2audio?";
      url.append(QString("&lan=zh&cuid= MAC  物理地址,自己的  &ctp=1&tok="));
      url.append(QUrl::toPercentEncoding(access_token));//这个后面还可以加别的参数 声音, 列表里面的东西   
      url.append("&tex=");
      url.append(QUrl::toPercentEncoding(text));
      qDebug()<<url;
      media_player->setMedia(QUrl::fromLocalFile(url));
      media_player->play();


ui 设计界面

头文件

#ifndef AUDIO_H
#define AUDIO_H

#include <QWidget>
/******** 音频相关类 *********/
#include <QAudioDeviceInfo> //音频属性类
#include <QAudioFormat> //音频参数
#include <QAudioInput>  //音频输入
#include <QAudioOutput> //音频输出
/******** 文件相关类 **********/
#include <QFile>
/******** 文字转语音类 ********/
#include <QTextToSpeech>

#include <QMediaPlayer>
QT_BEGIN_NAMESPACE
namespace Ui { class Audio; }
QT_END_NAMESPACE

class Audio : public QWidget
{
    Q_OBJECT

public:
    Audio(QWidget *parent = nullptr);
    ~Audio();

private:
    Ui::Audio *ui;
    QAudioInput *m_AudioInput;//音频输入
    QAudioOutput *m_AudioOutput;//音频输出
    QFile *m_file;//文件对象
    QTextToSpeech *m_speech;//文字转语音对象
  QMediaPlayer* media_player;//没有 tts  的播放对象
public slots:
    void slot_pushButton_input();
    void slot_pushButton_output();
    void slot_AudioOutput(QAudio::State state);
    void slot_pushButton_transition();
};
#endif // AUDIO_H

#include "audio.h"
#include "ui_audio.h"
#include <QDebug>
Audio::Audio(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Audio)
{
    ui->setupUi(this);
    media_player = new QMediaPlayer(this);//mp3播放
    /******* 获取系统可用的音频设备 ********/
    QList<QAudioDeviceInfo> AudioDevice_Outputs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
    for(int i = 0; i < AudioDevice_Outputs.size() ; i++)
    {
        QString name = AudioDevice_Outputs[i].deviceName();
        ui->comboBox_audio_ouput->addItem(name);
    }

    QList<QAudioDeviceInfo> AudioDevice_Inputs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    for(int i = 0; i < AudioDevice_Inputs.size() ; i++)
    {
        QString name = AudioDevice_Inputs[i].deviceName();
        ui->comboBox_audio_input->addItem(name);
    }


    /****** 配置音频参数 ******/
    QAudioFormat format;
    format.setSampleRate(16000);	//设置采样率:16000MHz
    format.setChannelCount(1);		//设置采集通道数:1通道
    format.setSampleSize(16);		//设置样本大小:16比特
    format.setCodec("audio/pcm");	//设置录音格式为:pcm格式

    QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); /** 使用默认输入 ***/
    if(info.isFormatSupported(format) == false)	//检测配置是否支持该音频设备
    {
        format = info.nearestFormat(format);	//只用最接近配置的音频配置
    }

    /****** 申请音频空间 *****/
    m_AudioInput = new QAudioInput(format,this);
    m_AudioOutput = new QAudioOutput(format,this);


    /****** 录音 ******/
    connect(ui->pushButton_input,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_input()));
    connect(ui->pushButton_output,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_output()));
    connect(m_AudioOutput,SIGNAL(stateChanged(QAudio::State)),this,SLOT(slot_AudioOutput(QAudio::State)));


    /***** 打印电脑的TTS语音引擎 *****/
    QStringList TextToSpeechs = QTextToSpeech::availableEngines();
    for(QString text : TextToSpeechs)
    {
        qDebug() << "语音引擎:" << text << endl;
    }

    m_speech = new QTextToSpeech(this); //文字转语音对象实列化
    connect(ui->pushButton_transition,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_transition()));
}

void Audio::slot_pushButton_transition()//转化函数
{
    QString text = ui->lineEdit_Text->text();//获取文字
    m_speech->setVolume(1);//播放音量 最大 1  最小 0
    m_speech->say(text);//播放的内容
}

Audio::~Audio()
{S
    delete ui;
}

void Audio::slot_pushButton_input() /*** 录制音频 ***/
{
    if(ui->pushButton_input->text() == "开始录制")
    {
        m_file = new QFile("./录音.wav");
        m_file->open(QIODevice::ReadWrite | QIODevice::Truncate);
        if(m_file->isOpen() == false){ //打开失败
            delete m_file;
            return ;
        }
        m_AudioInput->start(m_file);

        ui->pushButton_input->setText("停止录制");
    }
    else if(ui->pushButton_input->text() == "停止录制")
    {
        m_AudioInput->stop();//关闭录制
        m_file->close(); //关闭文件
        ui->pushButton_input->setText("开始录制");
    }
}

void Audio::slot_pushButton_output()
{
    m_file = new QFile("./录音.wav");
    m_file->open(QIODevice::ReadWrite);
    if(m_file->isOpen() == false){ //打开失败
        delete m_file;
        return ;
    }

    m_AudioOutput->start(m_file);
}

void Audio::slot_AudioOutput(QAudio::State state)
{
    if(state == QAudio::IdleState)
    {
        m_AudioOutput->stop();
        delete m_file;
    }
}






4.百度云的语音识别功能

1.基础配置和上面的出不多,只是多了语音识别为 文字的功能。。

2.百度云的开始 的步骤:(开辟一个列表就行了)

主要是 连接百度云的 语音翻译模式


void Audio::slot_pushButton_discern()
{
    /***** 读取音频文件 *****/
    m_file = new QFile("./录音.wav");
    m_file->open(QIODevice::ReadWrite);
    if(m_file->isOpen() == false){ //打开失败
        delete m_file;
        return ;
    }

    QByteArray requestData = m_file->readAll(); //读取文件所有内容
    m_file->close();;;;;
    QString buf = requestData.toBase64(); //转码 BASE 64
    /****** 组装网址 **************/
    QUrl url("http://vop.baidu.com/server_api");
    /****** 组装JSON *************/
    QJsonObject json;
    json["format"] = "pcm";
    json["rate"] = 16000;
    json["dev_pid"] = 1537;
    json["channel"] = 1;
    json["token"] = access_token;
    json["cuid"] = "q12993";
    json["len"] = requestData.size(); //语音文字真是的byte长度
    json["speech"] = buf;

    /****** 设置头部 **********/
    QNetworkRequest Request(url);
    Request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");

    QByteArray send_json = QJsonDocument(json).toJson();
    m_http->post(Request,send_json);
}

3.获取语音翻译:


void Audio::slot_http_finished(QNetworkReply *Reply)
{
    // 响应的状态码为 200 , 表示请求成功
    int stat = Reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    QByteArray Reply_data = Reply->readAll();
    qDebug() << "Reply_data = " << Reply_data << endl;
    ui->textEdit_JSON->setText(QJsonDocument::fromJson(Reply_data).toJson()); //将其转为JSON字符串
    if(stat == 200) /*** 成功数据 ***/
    {
        //获取响应信息
        QByteArray byteArray = QString(Reply_data).toUtf8();
        QJsonDocument JsonDocument = QJsonDocument::fromJson(byteArray); //转为JSON格式字符串
        if(JsonDocument.isObject() == true)
        {
            QJsonObject JsonObject = JsonDocument.object();
            if(JsonObject.find("access_token") != JsonObject.end())
            {
                access_token = JsonObject["access_token"].toString();
                qDebug() << "access_token:" << access_token << endl;
            }

            if(JsonObject.find("err_msg") != JsonObject.end() && JsonObject.find("result") != JsonObject.end())
            {
                QJsonArray JsonArray = JsonObject["result"].toArray();
                QString result = JsonArray[0].toString();//最后 JSON  形式的数据转为 QSTring类型的数据
                ui->lineEdit_Json->setText(result);
                /***** 判断结果 *****/
                if(result.contains("打开") == true)
                {
                    if(result.contains("卧室灯") == true)
                    {
                        m_speech->say("卧室灯已打开");
                    }
                    else if(result.contains("厨房灯") == true)
                    {
                        m_speech->say("厨房灯已打开");
                    }
                }
                else if(result.contains("关闭") == true)
                {
                    if(result.contains("卧室灯") == true)
                    {
                        m_speech->say("卧室灯已关闭");
                    }
                    else if(result.contains("厨房灯") == true)
                    {
                        m_speech->say("厨房灯已关闭");
                    }
                }
            }
        }
    }
}

ui 界面

头文件  (密钥自己  搞, 创建一个百度云就行了, 1元可以玩一个月,)

#ifndef AUDIO_H
#define AUDIO_H

#include <QWidget>
/******** 音频相关类 *********/
#include <QAudioDeviceInfo> //音频属性类
#include <QAudioFormat> //音频参数
#include <QAudioInput>  //音频输入
#include <QAudioOutput> //音频输出
/******** 文件相关类 **********/
#include <QFile>
/******** 文字转语音类 ********/
#include <QTextToSpeech>
/******* 网络相关类 ****/
#include <QNetworkAccessManager> /** 网络访问类 ***/
#include <QNetworkReply> /** 网络数据结果类 ***/

/******* QJSON 相关类 *****/
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
QT_BEGIN_NAMESPACE
namespace Ui { class Audio; }
QT_END_NAMESPACE

class Audio : public QWidget
{
    Q_OBJECT

public:
    Audio(QWidget *parent = nullptr);
    ~Audio();

private:
    Ui::Audio *ui;
    QAudioInput *m_AudioInput;
    QAudioOutput *m_AudioOutput;
    QFile *m_file;
    QTextToSpeech *m_speech;//文字转语音对象

    QNetworkAccessManager *m_http; /**网络访问对象 **/
    /***** 百度人脸库秘钥 ****/
    QString AppID = "";
    QString API_Key = "";
    QString Secret_Key = "";
    QString access_token = "";
public slots:
    void slot_pushButton_input();
    void slot_pushButton_output();
    void slot_AudioOutput(QAudio::State state);
    void slot_pushButton_transition();
    void slot_http_finished(QNetworkReply* Reply);
    void slot_pushButton_discern();
};
#endif // AUDIO_H

.cpp 文件

#include "audio.h"
#include "ui_audio.h"
#include <QDebug>
Audio::Audio(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Audio)
{
    ui->setupUi(this);

    /******* 获取系统可用的音频设备 ********/
    QList<QAudioDeviceInfo> AudioDevice_Outputs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
    for(int i = 0; i < AudioDevice_Outputs.size() ; i++)
    {
        QString name = AudioDevice_Outputs[i].deviceName();
        ui->comboBox_audio_ouput->addItem(name);
    }

    QList<QAudioDeviceInfo> AudioDevice_Inputs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    for(int i = 0; i < AudioDevice_Inputs.size() ; i++)
    {
        QString name = AudioDevice_Inputs[i].deviceName();
        ui->comboBox_audio_input->addItem(name);
    }


    /****** 配置音频参数 ******/
    QAudioFormat format;
    format.setSampleRate(16000);	//设置采样率:16000MHz
    format.setChannelCount(1);		//设置采集通道数:1通道
    format.setSampleSize(16);		//设置样本大小:16比特
    format.setCodec("audio/pcm");	//设置录音格式为:pcm格式

    QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); /** 使用默认输入 ***/
    if(info.isFormatSupported(format) == false)	//检测配置是否支持该音频设备
    {
        format = info.nearestFormat(format);	//只用最接近配置的音频配置
    }

    /****** 申请音频空间 *****/
    m_AudioInput = new QAudioInput(format,this);
    m_AudioOutput = new QAudioOutput(format,this);


    /****** 录音 ******/
    connect(ui->pushButton_input,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_input()));
    connect(ui->pushButton_output,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_output()));
    connect(m_AudioOutput,SIGNAL(stateChanged(QAudio::State)),this,SLOT(slot_AudioOutput(QAudio::State)));


    /***** 打印电脑的TTS语音引擎 *****/
    QStringList TextToSpeechs = QTextToSpeech::availableEngines();
    for(QString text : TextToSpeechs)
    {
        qDebug() << "语音引擎:" << text << endl;
    }
    qDebug()<<"没有";
    m_speech = new QTextToSpeech(this);
    qDebug()<<"1111";
    connect(ui->pushButton_transition,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_transition()));

    /****** HTTP网络访问类初始化 *****/
    m_http = new QNetworkAccessManager(this);

    connect(m_http,SIGNAL(finished(QNetworkReply*)),this,SLOT(slot_http_finished(QNetworkReply*)));
    QString url("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2&");
    url = url.arg(API_Key,Secret_Key);

    m_http->get(QNetworkRequest(QUrl(url))); //获取 access_token
    connect(ui->pushButton_discern,SIGNAL(clicked(bool)),this,SLOT(slot_pushButton_discern()));
}


void Audio::slot_pushButton_discern()
{
    /***** 读取音频文件 *****/
    m_file = new QFile("./录音.wav");
    m_file->open(QIODevice::ReadWrite);
    if(m_file->isOpen() == false){ //打开失败
        delete m_file;
        return ;
    }

    QByteArray requestData = m_file->readAll(); //读取文件所有内容
    m_file->close();;;;;
    QString buf = requestData.toBase64(); //转码 BASE 64
    /****** 组装网址 **************/
    QUrl url("http://vop.baidu.com/server_api");
    /****** 组装JSON *************/
    QJsonObject json;
    json["format"] = "pcm";
    json["rate"] = 16000;
    json["dev_pid"] = 1537;
    json["channel"] = 1;
    json["token"] = access_token;
    json["cuid"] = "q12993";
    json["len"] = requestData.size(); //语音文字真是的byte长度
    json["speech"] = buf;

    /****** 设置头部 **********/
    QNetworkRequest Request(url);
    Request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");

    QByteArray send_json = QJsonDocument(json).toJson();
    m_http->post(Request,send_json);
}

void Audio::slot_pushButton_transition()
{
    QString text = ui->lineEdit_Text->text();
    m_speech->setVolume(1);
    m_speech->say(text);
}

void Audio::slot_http_finished(QNetworkReply *Reply)
{
    // 响应的状态码为 200 , 表示请求成功
    int stat = Reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    QByteArray Reply_data = Reply->readAll();
    qDebug() << "Reply_data = " << Reply_data << endl;
    ui->textEdit_JSON->setText(QJsonDocument::fromJson(Reply_data).toJson()); //将其转为JSON字符串
    if(stat == 200) /*** 成功数据 ***/
    {
        //获取响应信息
        QByteArray byteArray = QString(Reply_data).toUtf8();
        QJsonDocument JsonDocument = QJsonDocument::fromJson(byteArray); //转为JSON格式字符串
        if(JsonDocument.isObject() == true)
        {
            QJsonObject JsonObject = JsonDocument.object();
            if(JsonObject.find("access_token") != JsonObject.end())
            {
                access_token = JsonObject["access_token"].toString();
                qDebug() << "access_token:" << access_token << endl;
            }

            if(JsonObject.find("err_msg") != JsonObject.end() && JsonObject.find("result") != JsonObject.end())
            {
                QJsonArray JsonArray = JsonObject["result"].toArray();
                QString result = JsonArray[0].toString();
                ui->lineEdit_Json->setText(result);
                /***** 判断结果 *****/
                if(result.contains("打开") == true)
                {
                    if(result.contains("卧室灯") == true)
                    {
                        m_speech->say("卧室灯已打开");
                    }
                    else if(result.contains("厨房灯") == true)
                    {
                        m_speech->say("厨房灯已打开");
                    }
                }
                else if(result.contains("关闭") == true)
                {
                    if(result.contains("卧室灯") == true)
                    {
                        m_speech->say("卧室灯已关闭");
                    }
                    else if(result.contains("厨房灯") == true)
                    {
                        m_speech->say("厨房灯已关闭");
                    }
                }
            }
        }
    }
}


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

void Audio::slot_pushButton_input() /*** 录制音频 ***/
{
    if(ui->pushButton_input->text() == "开始录制")
    {
        m_file = new QFile("./录音.wav");
        m_file->open(QIODevice::ReadWrite | QIODevice::Truncate);
        if(m_file->isOpen() == false){ //打开失败
            delete m_file;
            return ;
        }
        m_AudioInput->start(m_file);

        ui->pushButton_input->setText("停止录制");
    }
    else if(ui->pushButton_input->text() == "停止录制")
    {
        m_AudioInput->stop();//关闭录制
        m_file->close(); //关闭文件
        ui->pushButton_input->setText("开始录制");
    }
}

void Audio::slot_pushButton_output()
{
    m_file = new QFile("./录音.wav");
    m_file->open(QIODevice::ReadWrite);
    if(m_file->isOpen() == false){ //打开失败
        delete m_file;
        return ;
    }

    m_AudioOutput->start(m_file);
}

void Audio::slot_AudioOutput(QAudio::State state)
{
    if(state == QAudio::IdleState)
    {
        m_AudioOutput->stop();
        delete m_file;
    }
}



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

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

相关文章

C语言入门(一)——程序的基本概念

程序的基本概念 程序和编程语言 自然语言和形式语言 程序的调试 第一个程序 程序的基本概念 程序和编程语言 1.程序 程序&#xff08;Program&#xff09;告诉计算机应如何完成一个计算任务&#xff0c;这里的计算可以是数学运算&#xff0c;比如解方 程&#xff0c;也可…

Centos7下安装PostgreSQL14及其基本命令使用

MySQL关系型数据库目前算是互联网公司使用最多的。前两天看到一个推文&#xff0c;相对比国内使用MySQL&#xff0c;PostgreSQL在国内的普及貌似不高&#xff1f;国外像网络电话公司Skype公司等在大量使用PostgreSQL 作为互联网从业者&#xff0c;保持学习是必须的。开始学习Po…

小甲鱼C语言【课后笔记第一章——打印(printf)

目录 1、“打印”就是“输出”的意思 2、使用 GCC 编译程序&#xff1a;gcc 源代码 -o 可执行文件。 3、printf 是格式化输出函数 a、函数概要 b、函数原型 c、参数分析 d、返回值 e、演示 4. 转义字符 5. 反斜杠的奥义 6、课后习题&#xff08;编程题&#xff09; 1、…

性能工具之JMeter模拟多IP地址访问

文章目录一、前言二、前置条件三、操作步骤一、前言 今天一同事在压测时提到怎么用 JMeter 里虚拟多个 IP 来发送请求&#xff0c;我想了一下以前用LR时用过虚拟ip地址&#xff0c;JMeter 还没有使用过。想着原理应该是相通的&#xff0c;既然 LR 都能支持的话&#xff0c;那 …

多线程学习笔记(四)-- 常见类及使用

1. thread的方法 Thread.sleep()&#xff1a;占用cpu资源 Thread.yeild()&#xff1a;当前线程让渡cpu资源&#xff0c;大家竞争&#xff0c;也有再抢到cpu的机会 t1.join()&#xff1a;在t2线程中&#xff0c;调用t1.join()&#xff0c;是等待t1执行完成 2. 线程状态 3. sy…

力扣(LeetCode)142. 环形链表 II(C++)

哈希表 最直观的思想&#xff0c;哈希表记录遍历的结点&#xff0c;如果结点重复出现&#xff0c;则有环。如果遍历到空结点&#xff0c;无环。 class Solution { public:ListNode *detectCycle(ListNode *head) {unordered_set<ListNode *> ad;auto tail head;while(…

java计算机毕业设计ssm医患交流平台93xzr(附源码、数据库)

java计算机毕业设计ssm医患交流平台93xzr&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。…

用Excel自带图表插入带分类变量的箱形图(单坐标轴并列箱)

箱型图主要用来观察一个或多个类别下&#xff0c;数值型变量的分位数及离群值的特征和分布&#xff0c;以及在一定程度上观察到偏度和峰度的状态。网上有一些自己计算分位数来绘制箱型图的方法&#xff0c;但一方面是没有直接使用excel自带的箱型图好看和功能全面&#xff0c;二…

qq群聊机器人接入ChatGPT-简介和源码

qq群聊机器人接入ChatGPT 最近 ChatGPT 很火&#xff0c;也注册了账号玩了玩&#xff0c;确实灰常强大。但是也有的小伙伴可能没办法注册账号&#xff0c;我就想着把qq群机器人接入ChatGPT。 过程还是比较简单顺利的。下面简单介绍一下 直接跳过介绍&#xff0c;查项目代码 1…

绘制金字塔-第10届蓝桥杯Scratch选拔赛真题精选

[导读]&#xff1a;超平老师计划推出Scratch蓝桥杯真题解析100讲&#xff0c;这是超平老师解读Scratch蓝桥真题系列的第100讲。 蓝桥杯选拔赛每一届都要举行4~5次&#xff0c;和省赛、国赛相比&#xff0c;题目要简单不少&#xff0c;再加上篇幅有限&#xff0c;因此我精挑细选…

基于java(springboot)校园新闻管理系统源码(java毕业设计)

基于java(springboot)校园新闻管理系统 校园新闻管理系统是基于java编程语言&#xff0c;MySQL数据库&#xff0c;和springboot框架&#xff0c;用idea开发工具开发的设计&#xff0c;本设计分为学生用户&#xff0c;管理员两个角色&#xff0c; 学生的主要功能是可以注册登陆…

Cpolar实现虚拟机内网穿透,搭建私人云服务器

Cpolar实现虚拟机内网穿透,搭建私人云服务器 一、Cpolar功能介绍 Cpolar官网 Cpolar是一个安全的内网穿透的服务&#xff0c;可以将内网下的本地服务器通过安全隧道暴漏给公网。允许公网用户可以正常访问内网服务&#xff0c;是一款免费的内网穿透软件。只需要一行命令&#…

Python小炼(1):初识Python

"也许对我来说&#xff0c;太多拘束可能" 本篇的主要内容,针对的是一些常见的语法&#xff0c;在python中是怎样表示的&#xff0c;例如,python变量如何定义、选择、循环、判断结构是如何表示的&#xff1f;python函 数定义是怎么定义的…… ----前言 一、认识pyt…

无需代理及注册在VsCode中使用ChatGPT

无需代理及注册在VsCode中使用ChatGPT 安装 要安装扩展&#xff0c;请按照下列步骤操作&#xff1a; 1.打开 Visual Studio Code 2.单击左侧栏中的扩展程序图标 3.搜索"ChatGPT中文版" 4.点击安装按钮安装扩展 5.重启VSCode 用法 开始使用 在编辑器中右键触发…

【LeetCode每日一题:1691. 堆叠长方体的最大高度~~~排序+贪心】

题目描述 给你 n 个长方体 cuboids &#xff0c;其中第 i 个长方体的长宽高表示为 cuboids[i] [widthi, lengthi, heighti]&#xff08;下标从 0 开始&#xff09;。请你从 cuboids 选出一个 子集 &#xff0c;并将它们堆叠起来。 如果 widthi < widthj 且 lengthi < …

Java学习笔记6.3.3 文件操作 - 对象序列化与反序列化

文章目录零、本讲学习目标一、对象序列化与反序列化&#xff08;一&#xff09;对象序列化与反序列化概念&#xff08;二&#xff09;对象序列化与反序列化示意图&#xff08;三&#xff09;实际开发中序列化和反序列化的场景&#xff08;四&#xff09;实现对象序列化的两种方…

26岁,干了三年测试,月薪才12k,能跳槽找到一个更高薪资的工作吗?

在我们的身边&#xff0c;存在一个普遍现象&#xff1a;很多人从事软件测试岗&#xff0c;不计其数&#xff0c;经历的心酸难与外人道也。可是技术确难以提升、止步不前&#xff0c;薪资也只能看着别人水涨船高&#xff0c;自己却没有什么起色。 虽然在公司里属于不可缺少的一…

计算机网络:数据链路层

数据链路层 数据链路层主要处理单个链路上如何传输数据&#xff0c;并且向网络层向上提供服务 1. 数据链路层概述 1.1 术语介绍 主机拥有全部的计算机网络结构&#xff0c;路由器只有一部分 各个路由器之间由物理层连接 红线为发送的信息 1.2 数据链路层的三个重要问题 封装…

职业危机:从无到有,从弱到强;反思再反思和应对措施

一、写在开头 每天每周不写点东西&#xff0c;不把脑中的疑惑写明白&#xff0c;就感觉不到每天的进步。 每天没进步&#xff0c;这北漂生活&#xff0c;何时是个头啊。 可以北漂10年&#xff0c;也可以20年&#xff0c;但不可能是一辈子。 因为我不是北京人呐。 二、持续转…

Redis的字符串是怎么实现的

本篇会讲以下内容&#xff1a; Redis字符串的实现 Redis字符串的性能优势 Redis字符串的实现 Redis虽然是用C语言写的&#xff0c;但却没有直接用C语言的字符串&#xff0c;而是自己实现了一套字符串。目的就是为了提升速度&#xff0c;提升性能&#xff0c;可以看出Redis为…