qt学习:http+访问百度智能云api实现动物图片识别

目录

获取id key

编程步骤

配置ui界面

添加模块,头文件和定义变量

新建两个类,一个图像Image类,一个Http类,http类继承QObject类,并添加头文件并定义成员和函数

实现图像Image类,Http类的函数

在ui界面的cpp中添加全局变量,根据自己的应用来写,开头有获取方法

编写打开图片按钮的点击事件

编写开始识别按钮的点击事件​编辑​编辑

效果


获取id key

登录百度智能云平台,实名认证,进入右上角的控制台

选择图像识别 ,按照步骤做,完成前两个

创建应用----填写应用名称,自己定义,选择个人,应用描述随便写,点击创建,返回应用列表,记住上面的id key ,

打开左边的技术文档,选择api文档,就可以查看要识别什么图像要用什么接口

编程步骤

配置ui界面

添加模块,头文件和定义变量

在pro中添加模块
QT       += core gui network

在ui界面类的.h里添加
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QThread>
#include <QFileDialog>

#include "image.h"
#include "http.h"

private:
    QString fileName;
    QString accessToken;

新建两个类,一个图像Image类,一个Http类,http类继承QObject类,并添加头文件并定义成员和函数

Image类

#include <QString>
#include <QImage>
#include <QBuffer>
#include <QTextCodec>

public:
    static QByteArray imageToBase64(QString fileName);

Http类

#include <QString>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QEventLoop>

public:
     static bool  post_syns(QString url,QMap<QString,QString>header,QByteArray& requestData,QByteArray&replyData);

实现图像Image类,Http类的函数

Image类

//将图片转换为base64位
QByteArray Image::imageToBase64(QString fileName)
{
    //创建一个QImage对象img,并使用传入的文件名fileName来初始化它
    QImage img(fileName);
    //创建一个空的QByteArray对象ba,用于存储图片的二进制数据
    QByteArray ba;
    //用QByteArray构造QBuffer
    //创建一个QBuffer对象buf,并将之前创建的QByteArray对象ba的地址传递给它。
    //这样,我们可以将数据写入这个缓冲区
    QBuffer buf(&ba);
    //打开缓冲区buf以进行写操作。这是为了准备将图片数据写入缓冲区
    buf.open(QIODevice::WriteOnly);
    //将图片对象img保存到缓冲区buf中,使用JPG格式。
    //这样,图片的二进制数据将被写入到之前创建的QByteArray对象中
    img.save(&buf,"JPG");//把img 写入QBuffer
    //将之前存储的图片二进制数据转换为Base64编码的字符串,并存储在新的QByteArray对象中
    QByteArray base64 = ba.toBase64();//不包含编码头
    //创建一个指向UTF-8编码的文本编解码器的指针。
    QTextCodec *codec = QTextCodec::codecForName("utf-8");
    //对Base64编码的字符串进行URL编码
    //对图片urlencode
    QByteArray imaData = codec->fromUnicode(base64).toPercentEncoding();

    return imaData;
}

Http类

//提交http并将回应数据接收并判断是否提交成功
bool Http::post_syns(QString url, QMap<QString,QString>header, QByteArray &requestData, QByteArray &replyData)
{
    //创建管理者对象,负责发送和管理网络请求
    QNetworkAccessManager manager;//发送请求的动作
    //创建http请求包对象,用于存储关于HTTP请求的信息
    QNetworkRequest request;//请求的内容(包含url和头)
    //设置请求的URL为传入的url参数
    request.setUrl(url);
    //创建一个迭代器来遍历传入的请求头
    QMapIterator<QString,QString> it(header);
    //循环遍历所有的请求头
    while(it.hasNext())
    {
        //移动迭代器到下一个头
        it.next();
        //为请求设置一个原始头
        //.toLatin1()方法将字符串转换为Latin-1编码的字节数组,
        //因为Qt的网络模块要求头字段使用Latin-1编码
        request.setRawHeader(it.key().toLatin1(),it.value().toLatin1());
    }
    //使用之前设置的请求信息和请求数据发送一个POST请求,并将返回的响应对象存储在reply指针中
    QNetworkReply *reply =  manager.post(request,requestData);
    //创建一个事件循环对象
    QEventLoop l;
    //当网络请求完成时,连接的信号(finished)将触发事件循环的退出槽(quit)
    //当网络请求完成时,事件循环会结束
    connect(reply,&QNetworkReply::finished,&l,&QEventLoop::quit);
    //开始事件循环,等待网络请求完成事件发生
    l.exec();
    //检查是否有一个有效的响应对象,并且该响应没有错误
    if(reply != nullptr && reply->error() == QNetworkReply::NoError)
    {
        //从响应对象中读取所有的数据,并存储在replyData中
        replyData  = reply->readAll();
        //返回成功
        return true;
    }
    else
        //返回失败
        return false;
}

在ui界面的cpp中添加全局变量,根据自己的应用来写,开头有获取方法

const QString baiduTokenUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%1&client_secret=%2&";

const char *client_id = ""; //APP Key
const char *secret_id = "";//Secret Key
const QString baiduImageUrl = "https://aip.baidubce.com/rest/2.0/image-classify/v1/animal?access_token=%1";

编写打开图片按钮的点击事件

//打开图片
void Widget::on_btnOpen_clicked()
{
    //打开文件对话框,获取文件的路径名,返回字符串
    fileName = QFileDialog::getOpenFileName(
                this,//当前界面
                "打开图片",//标题
                ".",//默认路径
                "Image(*.png *.bmp *.jpg);"//过滤器
    );

    //判断文件是否打开成功
    if(fileName.isEmpty())
        return ;

    //创建文件对象
    QImage img(fileName);

    //将图片自适应显示到label上
    img = img.scaled(ui->label->size());
    ui->label->setPixmap(QPixmap::fromImage(img));
}

编写开始识别按钮的点击事件

//开始识别
void Widget::on_btnStart_clicked()
{
    //判断有没有图片路径
    if(fileName.isEmpty())
        return ;
    
    //调用自己定义的静态函数将图片转换为base64位
    QByteArray img = Image::imageToBase64(fileName);
    
    //组合成包体的一部分
    //将"image="字符串和转换后的Base64图片数据拼接在一起,形成完整的图片数据,用于后续的网络请求
    QByteArray imgData = "image=" + img; //body

    //获取access_token,文档中提到要先获取access_token
    //保存回复信息的对象
    QByteArray replyData; 
    //组合url
    QString url = QString(baiduTokenUrl).arg(client_id).arg(secret_id);
    //封装头部信息
    //创建一个QMap对象来存储HTTP头部信息。
    QMap<QString,QString> header;
    //这里只插入了一个头部信息,即"Content-Type",其值为"application/x-www-form-urlencoded"
    header.insert(QString("Content-Type"),QString("application/x-www-form-urlencoded"));

    //调用自己定义的静态函数提交http
    //url为接口地址
    //header是Content-Type:application/x-www-form-urlencoded,接口文档里有规定
    //imgData是图片的base64数据
    //replyData是回应的数据
    bool result = Http::post_syns(url,header,imgData,replyData);
    //判断是否提交成功,有数据返回
    if(result)
    {
        //从字符串中解析为一个json对象
        QJsonObject obj = QJsonDocument::fromJson(replyData).object();
        //获取对象里key为access_token的值,该值就是access_token
        accessToken = obj.value("access_token").toString();
    }

    //清除回应的数据
    replyData.clear();
    //将url和access_token组合
    QString imgurl = baiduImageUrl.arg(accessToken);
    //调用自己定义的静态函数提交http,和第一次只是url不一样
    //url为接口地址
    //header是Content-Type:application/x-www-form-urlencoded,接口文档里有规定
    //imgData是图片的base64数据
    //replyData是回应的数据
    result = Http::post_syns(imgurl,header,imgData,replyData);
    //判断是否提交成功
    if(result)
    {
        //打印回应的结果
        qDebug()<<"replyData:"<<replyData;
        //解析结果成一个json对象
        QJsonObject obj = QJsonDocument::fromJson(replyData).object();
        //获取key为result的值
        QJsonValue val = obj.value("result");
        //判断该值是不是数组
        if(val.isArray())
        {   
            //是数组就获取第一位
            QJsonValue first = val.toArray().at(0);
            //判断第一位是不是对象
            if(first.isObject())
            {
                //获取key为name的值显示出来
                QString animalName =  first.toObject().value("name").toString();
                ui->lineEdit->setText(animalName);
                return ;
            }
        }
    }
    //没有提交成功
    ui->lineEdit->setText("unkown");
}

效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值