Qt+百度AI实现人脸识别之人脸检测

2023-11-17

简单需求

本篇笔记中的示例实现了打开一张人脸图片,识别出年龄、性别、颜值等人脸属性信息。其它的人脸比对、身份验证、活体检测等等功能都可以在此基础上进行扩展,差不多都是对人脸识别接口的调用和信息处理。

Demo运行结果

这个功能可以当做是娱乐功能,同一个人不同风格的照片识别结果可能不同。
这里写图片描述


百度AI人脸识别接入

为什么使用百度AI接口

人脸识别可接入的平台挺多的,阿里云、腾讯云、Face++等等,如果是商用的话就得慎重了,毕竟要考虑的不仅是接口稳定性,还有价格、技术支持、售后等很多方面。这里只是用来学习,所以考虑的问题就比较简单了,只是关乎Money,而百度AI的接口绝大部分都免费,只是商用需要高并发或者一些付费资源的话需要付费,学习的话免费资源完全满足需求了。同样注册了阿里云的应用,直接收费,Face++给了限定的测试次数,所以选择了百度AI。技术而言,Face++可能在人脸识别这方面更专业一点,但目前各大平台的识别率基本没有什么区别。
这里写图片描述

接入步骤

  1. 注册百度账号,用来登录百度AI开发平台(http://ai.baidu.com/),有账号的可以直接登录
  2. 注册成为开发者
  3. 创建应用,应用创建成功之后也就开通了人脸检测、人脸比对等等相关业务
  4. 获取密钥,AppID、API Key和Secret key
  5. 生成签名(Access Token),这个写代码的时候要用到,每个应用的Access Token有效期为30天,到期后要重新获取,或者是在写代码时每次都获取一下
  6. 启动开发

百度AI开放平台上有详细的接入指南:http://ai.baidu.com/docs#/Begin/top

如何获取Access Token

向授权服务地址https://aip.baidubce.com/oauth/2.0/token发送请求(推荐使用POST),并在URL中带上以下参数:

  • grant_type: 必须参数,固定为client_credentials
  • client_id: 必须参数,应用的API Key
  • client_secret: 必须参数,应用的Secret Key

具体的参数值可以在下图位置中的“应用列表”里查看:
这里写图片描述
使用在线post工具按照上面的地址和参数进行请求就可以得到Access Token了,百度搜索“在线post工具"有很多可用的,这里使用http://coolaf.com/举例:
这里写图片描述


Qt软件开发

编程部分并不复杂,主要是对百度AI接口的调用及对请求数据的解析。但实现示例的功能还是用到了挺多知识点,下面会进行记录。

人脸检测Qt编程步骤

  1. 绑定请求服务器地址和密钥
  2. 按照百度人脸检测接口的格式要求添加header
  3. 将要检测的图片转换为为BASE64编码(这里需要注意一下,官方说上传的图片不能大于2M,测试了一个3M的图片依然可以请求成功,不过需要好几秒才能收到反馈,测试的3M的图片转成BASE64编码后长度超过1000万个字节,图片越小识别的速度越快)
  4. 按照百度人脸检测接口的格式要求打包body数据
  5. 使用post方式上传请求
  6. 解析反馈数据

注意:这里的请求内容必须按照百度接口指定的格式,格式如下
这里写图片描述

知识点

网络编程

这里使用了QtNetwork模块中的网络接口来实现http编程,需要在.pro文件中添加 QT += network,主要用到了下面三个类:

  • QNetworkAccessManager:该类允许应用程序发送网络请求和接收回复,类似于一个中转站或者一个容器,每当有请求创建或者接收到回复都由该类进行调度
  • QNetworkRequest:网络请求
  • QNetworkReply:网络请求的应答,在请求被完成调度是由QNetworkAccessManager创建

get、put、post请求方式的区别简述

这里只用到了post请求,并且目前大多数网络请求的方式均使用post。

  • GET请求(类似于数据库select操作),会向数据库发送数据的请求,从而来获取信息,不会改变数据内容,并且无论进行多少次操作,结果都是一样的
  • PUT请求(类似于数据库update操作),是会向服务器端发送数据的,会修改数据的内容,但是不会增加数据的种类,并且无论进行多少次操作,结果都是一样的
  • POST请求(类似于数据库insert操作),是会向服务器端发送数据的,但是该请求会改变数据的种类等资源,会创建新的内容

POST 提交数据方式

常用格式如下:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • application/json
  • text/xml

这篇文章里有这四种方式的详细介绍

如何对图片进行BASE64编码

  1. 提取图片
  2. 数据转换为BASE64编码

代码如下:

QImage image("H:/test.jpg");
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
//以png格式将图片数据写入ba
image.save(&buffer, "png");
//将图片进行BASE64编码
QString imgData = QString(ba.toBase64());
buffer.close();

JSON数据解析

这部分内容还挺多的,可以从网络学习JSON教程,下面的代码里也有用到。

核心代码

数据上传

//设置请求地址
QUrl url(requestUrl + "?access_token=" + accessToken);
QNetworkRequest request(url);

//设置数据提交格式,这个不能自己随便写,每个平台的格式可能不一样,百度AI要求的格式为application/json
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));

//将要检测的图片进行BASE64编码
QImage image(imgPath);
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
//以png格式将图片数据写入ba
image.save(&buffer, "png");
//将图片进行BASE64编码
QString imgData = QString(ba.toBase64());
buffer.close();

//打包请求参数
QJsonObject post_data;;
QJsonDocument document;
post_data.insert("image", imgData);
post_data.insert("image_type", "BASE64");
post_data.insert("face_field", "age,beauty,gender,expression");
document.setObject(post_data);
QByteArray post_param = document.toJson(QJsonDocument::Compact);

//发送请求
manager->post(request, post_param);

请求反馈数据解析

replyData = reply->readAll();
qDebug()<<"reply data is:"<<QString(replyData);

QJsonParseError json_error;
QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
if(json_error.error == QJsonParseError::NoError)
{
    //判断是否是对象,然后开始解析数据
    if(document.isObject())
    {
        QJsonObject obj = document.object();
        //解析反馈的人脸属性结果
        if(obj.contains("result"))
        {
            QJsonObject resultObj = obj.take("result").toObject();
            //解析人脸个数
            if(resultObj.contains("face_num"))
            {
                int faceNum = obj.take("face_num").toInt();
                qDebug()<<"查询到了图片中的人脸个数为:"<<faceNum;
            }
            //解析人脸属性
            if(resultObj.contains("face_list"))
            {
                QJsonArray faceArray = resultObj.take("face_list").toArray();

                for(int i = 0; i < faceArray.size(); i++)
                {
                    QJsonObject faceObj = faceArray.at(i).toObject();
                    if(faceObj.contains("gender"))
                    {
                        QJsonObject genderObj = faceObj.take("gender").toObject();
                        if(genderObj.contains("type"))
                        {
                            QString type = genderObj.take("type").toString();;
                            if(type == "male")
                            {
                                ui->lblSex->setText("男");
                            }
                            else
                            {
                                ui->lblSex->setText("女");
                            }
                        }
                    }
                    if(faceObj.contains("age"))
                    {
                        int age = faceObj.take("age").toDouble();
                        qDebug()<<"查询到了年龄:"<<age;
                        ui->lblAge->setText(QString::number(age));
                    }
                    if(faceObj.contains("beauty"))
                    {
                        int beauty = faceObj.take("beauty").toDouble();;
                        qDebug()<<"查询到了颜值:"<<beauty;
                        ui->lblBeauty->setText(QString::number(beauty));
                    }
                    if(faceObj.contains("expression"))
                    {
                        QJsonObject expressionObj = faceObj.take("expression").toObject();
                        if(expressionObj.contains("type"))
                        {
                            QString type = expressionObj.take("type").toString();;
                            if(type == "smile")
                            {
                                ui->lblFeature->setText("微笑");
                            }
                            else if(type == "laugh")
                            {
                                ui->lblFeature->setText("大笑");
                            }
                            else
                            {
                                ui->lblFeature->setText("不笑");
                            }
                        }
                    }
                }
            }
        }
    }
}
reply->deleteLater();

完整示例代码

https://download.csdn.net/download/zbw1185/10613073

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt+百度AI实现人脸识别之人脸检测 的相关文章

  • 通过CMake实现Qt项目

    我正在尝试通过 Cmake 构建并运行非常简单且基本的 Qt 示例 删除 pro 文件 以下是Qt项目的代码 自动生成的Qt项目的目录结构为 Cmake my project name headers mainwindow h source
  • 如何在 QT 安装程序框架中区分每用户安装与系统范围安装?

    我正在使用一些名为 pgModeler 的应用程序 它的当前版本提供了一个基于 QT 安装程序框架的安装程序 Windows 上该安装程序的问题是它安装每个用户的开始菜单条目 https github com pgmodeler pgmod
  • 如何在qt中进行异步文件io?

    我想知道如何在qt中实现异步文件io 这在普通的 qt 中是否可以实现 或者有人需要使用另一个库 例如 libuv 来实现这样的事情 我正在查看 QDataStream 但即使它是一个 流 它也不是非阻塞的 我想一种解决方案是制作一个在内部
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 在 Qt 5 中嵌入 Python

    我想将 Python 解释器嵌入到 Qt 5 应用程序中 我在 Qt 5 中有一个工作应用程序 但是当我把 include
  • SWI-Prolog 与 C++ 接口的问题

    我试图让 SWI Prolog 与 C 很好地配合 现在束手无策 现在 在我开始准确解释我的问题是什么之前 我想首先说明我的项目是关于什么的以及我选择了哪些工具来开发解决方案 我的教授分配给我的任务是开发一个 GUI 程序 作为 SWI p
  • 我应该使用 QCoreApplication::processEvents() 还是 QApplication::processEvents()?

    我有一个从两者调用的方法QThreads和主线程 这个方法有时可能需要很长时间才能在循环中进行计算 所以我把QCoreApplication processEvents 这可以防止 GUI 冻结 在某个时刻我已经改变了QCoreApplic
  • 使用 QTextCursor 选择一段文本

    使用 Qt 框架选择文本片段时遇到问题 例如 如果我有这个文件 没有时间休息 我想选择 ime for r 并从文档中删除这段文本 我应该如何使用 QTextCursor 来做到这一点 这是我的代码 QTextCursor cursor n
  • 如何在 QT 中绘制点?

    我正在用 QT 用 C 编写一个应用程序 其中有 n 个点并计算它的凸包 然而 一旦计算出来 我不知道如何绘制点并绘制船体的边界 制作菜单按钮等很简单 但我不确定我是否知道执行此操作的工具 你怎么做到这一点 图形视图 addEllipse
  • 在没有加载器的情况下实例化内联组件

    有没有办法实例化内联Component 即在同一文件中定义 而不使用Loader 我不太关心使用的性能影响Loader因为我要用很多东西污染我的文件Loader包装纸 我发现从 JavaScript 创建动态 QML 对象 http doc
  • 使用 CMake 编译时更改头文件位置会导致缺少 vtable 错误

    对于一个大型 C 项目 我需要从 qmake 过渡到 CMake 但是在处理一个玩具示例时 我遇到了一些我不理解的行为 示例代码具有单个头文件 当该头文件移动到子目录中时 我收到 MainWindow 类缺少 vtable 的错误 CMak
  • Retina 显示屏中具有 QOpenGLWIdget 的 Qt MainWindow 显示错误大小

    我有一个 Qt 应用程序MainWindow 我嵌入一个QOpenGLWidget在里面 一切正常 直到我开始使用 Apple Retina 显示屏并在高 DPI 模式下运行我的应用程序 我的QOpenGLWidget只是它应该具有的大小的
  • QMainWindow 上的 Qt 布局

    我设计了一个QMainWindow with QtCreator s设计师 它由默认的中央小部件 aQWidget 其中包含一个QVBoxLayout以及其中的所有其他小部件 现在我想要的一切就是QVBoxLayout自动占据整个中央小部件
  • Qt:不完整类型和前向声明的使用无效

    我有一些误解 A h ifndef A H define A H include B h class A public B Q OBJECT public A endif A cpp include A h A A B ui gt blan
  • 覆盖 QWebView 中的页面回复

    我试图在 Qt 的 QWebView 中拦截页面 表单请求 并在某些情况下使用替代内容进行响应 QNetworkReply ngcBrowser createRequest Operation operation const QNetwor
  • Qt 5.1.1 与 Visual Studio 2012 - 这些 QT 版本无法访问

    打开 Visual Studio 时出现此错误 我安装自http qt project org downloads http qt project org downloads 适用于 Windows 64 位的 Qt 5 1 1 VS 20
  • 使用 QGraphicsScene 实现流畅的动画

    我希望我的问题并不总是同样的问题 我有一个 QGraphicsScene 它的项目是一些 QGraphicsPixmap 我用一个计时器来移动它们 每秒 SetX 10 我设置 10是因为窗口大100 使用这个解决方案我的动画不流畅 我想我
  • 即使我在单独的线程中运行,QT GUI 也会冻结

    我有一个小型聊天应用程序 其中使用 SQLite 数据库来存储所有对话 我注意到该应用程序随机冻结 然后我必须最小化和最大化它才能使其再次工作 我认为问题可能是 SQLite 选择 插入导致 gui 冻结 我决定尝试将所有 SQLite 方
  • QFileSystemModel setRootPath

    我正在尝试创建一个 Qt 应用程序来显示文件夹 Mac OS 中的 Users 文件夹 的内容 这是代码 QFileSystemModel dirModel new QFileSystemModel dirModel gt setRootP
  • Qt 支持 Windows 蓝牙 API 吗?

    谁能告诉我 Qt 是否支持 Windows 蓝牙 API 如果是这样 您能否分享一些有关如何使用它的信息 自上次答复以来 这个问题的答案发生了一些变化 Qt 5 2 版为 Linux BlueZ 和 BlackBerry 设备实现了蓝牙 A

随机推荐

  • mysql数据库各种应用_MySQL数据库常见管理应用(1)

    MySQL数据库常见管理应用 1 创建数据库 创建一个数据库solin mysql gt create database solin 建立一个名为solin gbk的GBK字符集 mysql gt create database solin
  • Java通过反射获取注解以及注解中的信息

    首先自定义两个注解 1 用于描述表名 只能用在类 接口 枚举上 Target ElementType TYPE Retention RetentionPolicy RUNTIME public interface TableName Str
  • 《现代控制系统》第五章——反馈控制系统性能分析 5.3 二阶系统的性能

    现在我们看一个单环二阶系统的单位阶跃响应 一个闭环反馈控制系统如下图所示 已知该闭环系统的转换方程为 把受控系统的转换方程代入进去得到 如果给一个阶跃输入 那么 查拉普拉斯逆变换表我们得到时域输出为 其中 同时也是特征方程在s域的根与原点的
  • 实际项目二次封装axios------request.js和使用

    前言 axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端 本质上也是对原生XHR的封装 只不过它是Promise的实现版本 符合最新的ES规范 在项目的实际开发中用到也比较多 这里我介绍一下实际开发中的基
  • 什么是高内聚、低耦合?

    起因 模块独立性指每个模块只完成系统要求的独立子功能 并且与其他模块的联系最少且接口简单 两个定性的度量标准 耦合性和内聚性 耦合性也称块间联系 指软件系统结构中各模块间相互联系紧密程度的一种度量 模块之间联系越紧密 其耦合性就越强 模块的
  • align-items属性

    弹性子元素在 侧轴 交叉轴上的对齐方式 align items stretch 默认值 如果弹性子元素没有高度或高度为auto 将占满整个容器的高度 align items flex start 子元素在侧轴顶端对齐 align items
  • CSS餐厅小游戏练习1~32关(附答案和链接)

    前言 CSS3众多基础常见的选择器都可以小游戏中学习 每天刷一遍 辅助记忆 做好熟练运用CSS3的第一步 小游戏链接 CSS3餐厅练习 玩法 利用各种选择器和选择器之间的关系选中抖动的物体即可通关 文章目录 第一关 Type Selecto
  • postgresql从入门到菜鸟(三)基本命令和窗口函数

    上一篇我们已经在rhel上创建了数据库 并且建立的一张成绩表 之后通过通过客户端连接上服务器端 这一篇将会写一些关于数据库的操作 首先是一些基本的操作的操作如选择数据库 查看表等等 连接至服务器端后可以通过以下命令查看数据库的基本信息 l
  • 记录element-plus + vue3.2 + tsx 开发时的问题

    开发时 select组件无法通过 model value v model value 设置值 查看了一下源码 image png https p1 juejin byteimg com tos cn i k3u1fbpfcp e1e92e6
  • 搞懂了Vue对象与实例的区别!

    很多人把Vue对象和Vue实例混为一谈 但它们还是有区别的 Vue构造函数就像一台智能手机的设计图纸 定义了这款手机的总体结构和组件 而每部依照设计图组装出来的真实手机 就是Vue实例 设计图上注明了屏幕尺寸 CPU型号等静态信息 对应Vu
  • vscode 自动导入包(组件)插件Auto Import安装好后,依旧没有自导导入提示的原因

    在TodoList js中 第一次用AntDesign的
  • Linux系统下搭建(更新)cuda环境

    本人之前ubuntu系统装的是cuda8 因为模型需要升级cuda 因此重新装cuda10 安装和更新cuda和cudnn以及安装和更新显卡驱动 下面操作都适合 一 安装 升级 显卡驱动 升级cuda之前 先要升级显卡驱动 登陆网页http
  • v-show切换显示隐藏失败

    最近在使用element ui时发现使用v show显示某一元素不生效 问题 当切换到日期维度时坐席中心并不会跟着改变 解决方法 将v show替换成v if 总结 v show是不支持template语法的 v if vs v show
  • MySQL分页查询慢怎么办

    今天看到一个问题 MySQL分页查询慢怎么办 第一反应是用limit限制返回的条数 比如 select from table order by idlimit 10 100 实际上我们限制的只是返回的条数是100 并不是查询时就从第10条开
  • java网络编程

    java网络编程 1 1 概述 1 2 网络通信的要素 如何实现网络通信 通信双方地址 地址ip 端口号 127 0 0 1 8080 OSI七层模型 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img w2Vt3r
  • 测试人遇到难以重现的bug,要怎么办?

    长时间做测试的人 自然也惹上了一堆毛病 譬如 这生了病不叫病 叫做bug 好了 发现bug了第一件事情 重现或者说确认开始了 摸了摸自己的胸口 恩 有点痛 但是又似乎是飘渺的 看来这还是一个难以重现的bug 作为一个资深的测试人员 我们是不
  • 2021斯坦福CS224N课程笔记~4

    4 依存解析 Dependency Parsing 参考文档 https zhuanlan zhihu com p 420736640 https www showmeai tech article detail 237 https zhu
  • 地鼠君黑盒测试--小白功能测试避雷经验分享

    测试计划 接到任务的第一时间 需要快速建档 准备测试计划 测试计划主要有几个侧重点 第一 该项目的截止时间和团队是否确定的阶段时间交付 第二 模块分析图 这一块由于公司小 缺少原型图 常常导致滞后产生 并且这一块花费的时间 笔者发现常常超时
  • centos7.5重启网络服务,网卡ip先显示后消失

    ip地址丢失不见 网卡报错 当重启网卡时 Job for network service failed because the control process exited with error code See systemctl sta
  • Qt+百度AI实现人脸识别之人脸检测

    文章目录 简单需求 Demo运行结果 百度AI人脸识别接入 为什么使用百度AI接口 接入步骤 如何获取Access Token Qt软件开发 人脸检测Qt编程步骤 知识点 网络编程 get put post请求方式的区别简述 POST 提交