qt学习:http+访问百度智能云api实现车牌识别

目录

登录到百度智能云,找到文字识别

 完成操作指引

开通

查看车牌识别的api文档

​编辑​编辑

查看自己应用的api key

查看回应的数据格式 

编程步骤

ui界面编辑

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

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

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

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

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

编写识别按钮的点击事件


登录到百度智能云,找到文字识别

 完成操作指引

  •  免费尝鲜---服务类型选择交通---接口选择全部----0元领取
  • 创建应用---填写应用名称---个人----应用描述

开通

查看车牌识别的api文档

查看自己应用的api key

查看回应的数据格式 

编程步骤

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"

新建两个类,一个图像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/ocr/v1/license_plate?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));
}

编写识别按钮的点击事件

    //判断有没有图片路径
    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为words_result的对象
        QJsonValue val = obj.value("words_result");

        //获取key为number的值
        QString carId = val.toObject().value("number").toString();
        //输出车牌
        qDebug()<<"carId:"<<carId;
        //显示车牌
        ui->lineEdit->setText(carId);
    }
    else
    {
        //提交失败
        ui->lineEdit->setText("unkown");
    }

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

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

相关文章

使用Docker部署WBO白板并结合内网穿透实现远程访问WBO白板

本文主要是如何使用Docker部署WBO白板并实现公网地址远程访问的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&am…

leetcode刷题(剑指offer)54.螺旋矩阵

54.螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#xff1a;ma…

编译和链接哪个才是最“猴急”的呢???

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 我会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能…

Windows Server 2003 DNS服务器搭建

系列文章目录 目录 系列文章目录 文章目录 前言 一、DNS服务器是什么&#xff1f; 二、配置服务器 1.实验环境搭建 2.服务器搭建 3)安装Web服务器和DNS服务器 4)查看安装是否成功 5)这里直接配置DNS服务器了,Web服务器如何配置我已经发布过了 文章目录 Windows Serve…

从困惑到精通:私域运营领域10大问题全解析!

一、到底什么是“私域” 在探讨私域流量的实际操作之前&#xff0c;品牌需要对“私域”有一个清晰的认识。那么&#xff0c;究竟什么是“私域”呢&#xff1f; 有观点认为&#xff0c;私域是品牌方掌握的用户群体&#xff0c;这些用户可以在品牌的运营、沉淀和变现中发挥重要…

【第二十二课】最短路:dijkstra算法 ( acwing849 / acwing850 / c++ 代码)

目录 dijkstra算法求最短距离步骤 朴素的dijkstra算法---acwing-849 代码如下 代码思路 堆优化版的dijkstra算法---acwing-850 代码如下 关于最短路问题分有好几种类型 &#xff1a; 单源就是指&#xff1a;只求从一个顶点到其他各顶点 多源是指&#xff1a;要求每个顶…

基于springboot+vue的旅游管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 研究现状…

uniapp顶部导航栏高度适配

为了实现好看又实用的顶部导航栏&#xff0c;不得不自己定义导航栏样式。而自己定义的导航栏高度会因为手机的型号不同所展示的效果也就不同&#xff0c;所以只能通过适配高度来达到预期的效果 1.需要在page.json文件中对需要自定义导航栏文件进行配置 "navigationStyle…

Leetcode第382场周赛

Leetcode第382场周赛 本人水平有限&#xff0c;只做前三道。 一、按键变更的次数 给你一个下标从 0 开始的字符串 s &#xff0c;该字符串由用户输入。按键变更的定义是&#xff1a;使用与上次使用的按键不同的键。例如 s “ab” 表示按键变更一次&#xff0c;而 s “bBBb”…

机器学习:梯度下降法(Python)

LinearRegression_GD.py import numpy as np import matplotlib.pyplot as pltclass LinearRegression_GradDesc:"""线性回归&#xff0c;梯度下降法求解模型系数1、数据的预处理&#xff1a;是否训练偏置项fit_intercept&#xff08;默认True&#xff09;&…

【数据分享】1929-2023年全球站点的逐月最高气温数据(Shp\Excel\无需转发)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01; 之前我们分享过1929-2023年全球气象站…

C# Onnx yolov8 仪表指针检测

目录 效果 模型信息 项目 代码 训练数据 下载 C# Onnx yolov8 仪表指针检测 效果 模型信息 Model Properties ------------------------- date&#xff1a;2024-01-31T11:19:38.828556 author&#xff1a;Ultralytics task&#xff1a;detect license&#xff1a;AGPL-…

wordpress怎么做产品展示站?推荐使用MOK主题和ent主题

大多数WordPress站点都是个人博客网站&#xff0c;主要以文章性质的图文为主。不过部分站长想要用WordPress搭建一个产品展示站&#xff0c;应该怎么做呢&#xff1f; 其实&#xff0c;WordPress可以用来建立各种各样的博客网站&#xff0c;包括个人博客、企业网站、商城、影视…

小白级教程,10秒开服《幻兽帕鲁》

在帕鲁的世界&#xff0c;你可以选择与神奇的生物「帕鲁」一同享受悠闲的生活&#xff0c;也可以投身于与偷猎者进行生死搏斗的冒险。帕鲁可以进行战斗、繁殖、协助你做农活&#xff0c;也可以为你在工厂工作。你也可以将它们进行售卖&#xff0c;或肢解后食用。 前言 马上过年…

带大家详细了解msvcr120.dll丢失的原因,msvcr120.dll丢失怎样修复的方法

在使用电脑和运行应用程序时&#xff0c;我们经常会遇到与动态链接库&#xff08;Dynamic Link Library, DLL&#xff09;文件相关的错误。其中之一是 "msvcr120.dll 丢失" 的错误提示。今天我们就来详细的了解一下msvcr120.dll这个文件和分享msvcr120.dll丢失怎样修…

从宏观上对人工智能(AI)的一些理解

1.人工智能概述 68年前&#xff0c;约翰麦卡锡在“达特茅斯会议”正式提出人工智能概念。直到2023年&#xff0c;ChatGPT掀起全球AI大模型浪潮&#xff0c;英伟达市值一年飙涨2.4倍&#xff0c;真正意义上的“人工智能元年”到来了。 提到人工智能&#x…

事件驱动架构:使用Flask实现MinIO事件通知Webhooks

MinIO的事件通知可能一开始看起来并不激动人心&#xff0c;但一旦掌握了它们的力量&#xff0c;它们就能照亮您存储桶内的动态。事件通知是一个全面、高效的对象存储系统中的关键组件。Webhooks是我个人最喜欢的工具&#xff0c;用于与MinIO集成。它们在事件的世界中就像一把瑞…

八种Flink任务监控告警方式

目录 一、Flink应用分析 1.1 Flink任务生命周期 1.2 Flink应用告警视角分析 二、监控告警方案说明 2.1 监控消息队中间件消费者偏移量 2.2 通过调度系统监控Flink任务运行状态 2.3 引入开源服的SDK工具实现 2.4 调用FlinkRestApi实现任务监控告警 2.5 定时去查询目标库…

在深度学习中,epoch和learning rate的通常取值范围?

在深度学习中&#xff0c;epoch和学习率的取值确实会根据不同的任务、数据集和模型架构有所不同。然而&#xff0c;您提到的范围是一些常见的经验性取值&#xff0c;这些取值在很多情况下都能工作得相当好。 1. 对于epoch的取值范围&#xff1a; 在很多研究论文和实际应用中&…

机器学习 | 掌握逻辑回归在实践中的应用

目录 初识逻辑回归 逻辑回归实操 分类评估方法 初识逻辑回归 逻辑回归&#xff08;LogisticRegression&#xff09;是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回归&#xff0c;但是它与回归之间有一定的联系。由于算法的简单…