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实现人脸识别之人脸检测 的相关文章

  • 来自无符号字符缓冲区的 QImage(jpg 格式)

    我有类型的缓冲区unsigned char 我用JPG图像填充 我想使用此缓冲区将图像绘制到 QLabel 中的应用程序屏幕上 我已经这样做了 但图像不正确 谁能告诉我最好的方法是什么 QPixmap pix QPixmap fromIma
  • QMainWindow::showMaximized() 不更新大小

    我正在尝试创建一个QMainWindow封装一个QGraphicsView我把它放进去 我希望它一开始就最大化 所以我这样做 QMainWindow mainWindow new QMainWindow mainWindow gt setW
  • Qt Designer 与手动编码

    每次我使用图形工具包开始一个项目时 第一个冲突就会发生在如何处理视觉设计和小部件布局的决定上 图形工具还是手动编码 这是一个非常棘手 主观的问题 因为大多数人会根据个人喜好来决定 它还很大程度上取决于图形工具的质量 在这种情况下 我想只关注
  • 如何在点击 Qtablewidget 单元格时获取放置在该单元格中的小部件的行号?

    我正在尝试的是当用户选择项目时获取 QcomboBox 的行号 虽然使用它很容易获得单元格的列和行 cellClicked int int 信号 但仅当单元格上没有小部件时才有效 那么如果单元格中放置了小部件 如何获取行号 Note 所有组
  • 在 Qt C++ 中使用多个键

    我正在构建 坦克 游戏 我使用关键事件在地图上运行我的坦克 实际上我当时只能使用一把钥匙 但我需要有能力去完成任务 同时向上和离开 这是我的单键事件代码 switch event gt key case Qt Key Up if ui gt
  • 如何设置 Xcode 来代替 Qt Creator 工作?

    我不使用 Qt Creator 的 UI 设计功能 对于一个新项目 我想体验一下使用 Xcode 的工作 这将是一个常规的 Qt 项目 使用 C 和 Qt 库开发 就像在 Qt Creator 中一样 我没有使用 OS X 尤其是 Xcod
  • 异步设计中如何知道哪个QNetworkReply属于QNetworkRequest?

    我可以轻松地用 C 进行异步设计 HttpResponseMessage response await httpClient GetAsync InputAddress Text run when request finished And
  • 检查目录是否为空

    我正在尝试检查目录是否为空 MainWindow MainWindow QWidget parent QMainWindow parent ui new Ui MainWindow ui gt setupUi this QDir Dir h
  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • cx_freeze:QODBC 驱动程序未加载

    我的 python 应用程序如下所示 test py from PyQt4 import QtCore from PyQt4 import QtGui from PyQt4 import QtSql import sys import at
  • 仅将非模态 QDialog 窗口放置在我的应用程序顶部,而不是所有应用程序顶部

    我有一个 QDialog 窗口 它应该始终位于我的应用程序顶部 它不是模态的 用户可以随时与对话框和主应用程序进行交互 使用窗口保持在顶部提示在某种程度上实现了这一点 但是 该对话框仍然位于所有其他正在运行的应用程序 例如记事本 chrom
  • QGraphicsView 和 eventFilter

    这个问题已经困扰我两天多了 所以我想我应该问一下 我在Win7上使用Qt 4 5 3 用VC2008编译 我有 MyGraphicsView 继承 QGraphicsView 和 MyFilter 继承 QObject 类 当我将 MyFi
  • 如何在 Qt-Embedded 中(正确)输出多语言文本?

    我的目标系统是 linux 3 3 7 Qt Embedded 开源版 4 8 Droid 字体 取自 fonts droid 20111207 git 1 all deb Debian 软件包并复制到 usr lib fonts目录 主要
  • QSpinBox 输入 NaN 作为有效值

    我正在尝试扩展 QSpinBox 以能够输入 NaN 或 nan 作为有效值 根据文档 我应该使用 textFromValue valueFromText 和 validate 函数来完成此操作 但我无法让它工作 因为它仍然不允许我输入除数
  • Qt Creator:如何区分 win32 和 win64

    我必须在 pro 文件中执行类似的操作 win32 LIBS L 3rdparty libusb win32 lib msvc llibusb else win64 LIBS L 3rdparty libusb win32 lib msvc
  • QT/QML Android App,点击通知栏时打开应用程序

    我为 Android 应用程序制作了一个 QT 当我单击平板电脑中上面看到的按钮通知栏时 但是 如果单击通知 我的应用程序将打开 聚焦 不知道 并显示黑色窗口 简单来说怎么做呢 我的代码是 package org ays operation
  • (如何)我可以抑制未找到包配置文件的警告吗?

    我正在尝试创建一个CMakeLists txt尝试查找的文件Qt5 如果失败 则尝试回退到Qt4安装 该脚本到目前为止有效 但如果出现以下情况我总会收到警告Qt5未安装 注意FindQt5 cmake是由提供Qt5并且仅当以下情况时才可用Q
  • Qt - 如何粘合两个窗口并将它们移动在一起?

    就像qmmp Qt 音乐播放器ui设计一样 这两个或三个窗口实际上在同一个窗口中 因为只有一个dock图标 并且这些窗口可以一起移动并相互附着 我看了源码 好像有用QDockWidget 但我真的不知道如何获得它的细节 当您手动移动辅助窗口
  • PyQt:如何设置组合框项目可检查?

    为了将 GUI 小部件数量保持在最低限度 我需要找到一种方法来为用户提供下拉菜单项的选择 这些菜单项可用于过滤掉 listWidget 项中显示的内容 假设 listWidget 列出了 5 个不同类别的项目 Cat A Cat B Cat
  • 错误 LNK2001:无法解析的外部符号 __CxxFrameHandler3

    我正在将 Qt 从 VS 2013 迁移到 Qt 5 10 1 到 VS 2015 出现以下多个链接错误 error LNK2001 unresolved external symbol CxxFrameHandler3 error LNK

随机推荐

  • 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 提交