c++/qt连接阿里云视觉智能开发平台

官方参考文档:

        阿里云人脸活体检测api文档:调用DetectLivingFace进行人脸活体检测_视觉智能开放平台(VIAPI)-阿里云帮助中心

        阿里云视觉智能平台公共请求参数文档:人体人脸分析API接口的公共请求参数_视觉智能开放平台(VIAPI)-阿里云帮助中心

        这个公共请求参数文档里面,官方给了完整的java代码,用于请求人脸活体检测接口,但是阿里云官方对c++的支持很弱,没有c++相关的示例,这篇文章就是根据这个官方java示例,给出qt/c++的代码


先给出完整qt代码
头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QImage>
#include <QNetworkAccessManager>
#include <QNetworkReply>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_imgBtn_clicked();private:Ui::MainWindow *ui;QNetworkAccessManager *_manager = nullptr;QUrl url;void doAliDetectLivingFace();QString specialUrlEncode(const QString &value);QString sign(const QString &accessSecret, const QString &stringToSign);QString sign2(const QString &accessSecret, const QString &stringToSign);private slots:void finishedReplay();void downloadProgress(qint64 bytesSent, qint64 bytesTotal);void slotError(QNetworkReply::NetworkError net_error);
};#endif // MAINWINDOW_H

cpp 文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QBuffer>
#include <QFileInfo>
#include <QCryptographicHash>
#include <QDebug>
#include <QFileDialog>
#include <QUrlQuery>
#include <QUuid>
#include <QMessageAuthenticationCode>
#include <QTimeZone>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);_manager =new QNetworkAccessManager(this);doAliDetectLivingFace();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::finishedReplay()
{QNetworkReply *reply = dynamic_cast<QNetworkReply*>(sender());QByteArray bytes = reply->readAll();qDebug()<<"finished:\n";QString  html_text = bytes;qDebug()<<"get ready,read size:"<<html_text.size();qDebug()<< "ret_html_text:\n"<<html_text<<"\n";reply->deleteLater();
}void MainWindow::downloadProgress(qint64 bytesSent, qint64 bytesTotal)
{qDebug()<< "\ndownloadProgress done:\n";qDebug() << "bytesSent: " << bytesSent<< "  " << "bytesTocal: " << bytesTotal;
}void MainWindow::slotError(QNetworkReply::NetworkError net_error)
{qDebug()<< "slotError:"<<net_error;
}void MainWindow::doAliDetectLivingFace()
{/*最终url:http://facebody.cn-shanghai.aliyuncs.com/?Signature=olXJ3UlVH4bSG1OHrg3kQWE0lrE%3D&AccessKeyId=LTAI5tFopUsaPTXZCvSdrkpQ&Action=DetectLivingFace&Format=JSON&RegionId=cn-shanghai&SignatureMethod=HMAC-SHA1&SignatureNonce=2a90f9ef-9d6d-438e-b20f-5106653654d2&SignatureVersion=1.0&Tasks.1.ImageURL=http%3A%2F%2Fviapi-test.oss-cn-shanghai.aliyuncs.com%2Fviapi-3.0domepic%2Ffacebody%2FDetectLivingFace%2FDetectLivingFace11.jpg&Tasks.2.ImageURL=http%3A%2F%2Fviapi-test.oss-cn-shanghai.aliyuncs.com%2Fviapi-3.0domepic%2Ffacebody%2FDetectLivingFace%2FDetectLivingFace13.jpg&Timestamp=2024-10-31T09%3A03%3A08Z&Version=2019-12-30*/QDateTime currentTime = QDateTime::currentDateTime();QDateTime eightHoursAgo = currentTime.addSecs(-8 * 3600);QTimeZone gmtTimeZone("GMT");eightHoursAgo.setTimeZone(gmtTimeZone);QString currentTimeStr = eightHoursAgo.toString("yyyy-MM-dd'T'HH:mm:ss'Z'");// 这里换成自己阿里云账户的accessKeyId和accessKeySecretQString accessKeyId = "***************";QString  accessKeySecret = "***************";QMap<QString, QString> urlQueryMap;urlQueryMap.insert("Tasks.1.ImageURL", "http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/DetectLivingFace/DetectLivingFace11.jpg");urlQueryMap.insert("Tasks.2.ImageURL", "http://viapi-test.oss-cn-shanghai.aliyuncs.com/viapi-3.0domepic/facebody/DetectLivingFace/DetectLivingFace13.jpg");urlQueryMap.insert("SignatureMethod", "HMAC-SHA1");QUuid uuid = QUuid::createUuid();QString uuidString = uuid.toString();uuidString = uuidString.mid(1, uuidString.size() -2);// urlQueryMap.insert("SignatureNonce", "4449ddb6-d72a-4e56-899c-c33365a8caf2");urlQueryMap.insert("SignatureNonce", uuidString);urlQueryMap.insert("AccessKeyId", accessKeyId);urlQueryMap.insert("SignatureVersion", "1.0");// urlQueryMap.insert("Timestamp", "2024-10-28T02:02:26Z");urlQueryMap.insert("Timestamp", currentTimeStr);urlQueryMap.insert("Format", "JSON");urlQueryMap.insert("RegionId", "cn-shanghai");urlQueryMap.insert("Version", "2019-12-30");urlQueryMap.insert("Action", "DetectLivingFace");// urlQueryMap.insert("ImageURL", "https://ainemo-testdev.oss-cn-beijing.aliyuncs.com/wenkeTest/1.png");if (urlQueryMap.contains("Signature")) {urlQueryMap.remove("Signature");}QString sortQueryStringTmp;for(auto it = urlQueryMap.begin(); it != urlQueryMap.end(); ++it){sortQueryStringTmp.append("&").append(specialUrlEncode(it.key())).append("=").append(specialUrlEncode(it.value()));}QString sortedQueryString = sortQueryStringTmp.mid(1);QString stringToSign;stringToSign.append("POST").append("&");stringToSign.append(specialUrlEncode("/")).append("&");stringToSign.append(specialUrlEncode(sortedQueryString));// QString signStr = QString::fromStdString(SignUtil::sign(QString(accessKeySecret + "&").toStdString(), stringToSign.toStdString()));// signStr = signStr.left(signStr.size() - 1);QString signStr = sign(accessKeySecret + "&", stringToSign);QString signature = specialUrlEncode(signStr);QString urlStr = QString("http://facebody.cn-shanghai.aliyuncs.com/?Signature=%1&%2").arg(signature, sortedQueryString);// qDebug() << "timeStamp is " << "2024-10-28T02:02:26Z";qDebug() <<"sortedQueryString is " << sortedQueryString;qDebug() <<"stringToSign is " << stringToSign;qDebug() <<"signStr is " << signStr;qDebug() <<"signature is " << signature;qDebug() << "url str is " << urlStr;QNetworkRequest request;QString accept = "application/json";QString content_type = "application/json";request.setRawHeader(QByteArray("accept"), accept.toLocal8Bit());request.setHeader(QNetworkRequest::ContentTypeHeader,content_type);request.setUrl(QUrl(urlStr));QNetworkReply *reply = _manager->post(request, "");connect(reply, SIGNAL(finished()), this, SLOT(finishedReplay()));connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),this, SLOT(slotError(QNetworkReply::NetworkError)));connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64)));
}QString MainWindow::specialUrlEncode(const QString &value)
{QString encodedValue = QUrl::toPercentEncoding(value, "", "");encodedValue.replace("+", "%20");encodedValue.replace("*", "%2A");encodedValue.replace("%7E", "~");return encodedValue;
}QString MainWindow::sign(const QString &accessSecret, const QString &stringToSign)
{QByteArray key = accessSecret.toUtf8();QByteArray data = stringToSign.toUtf8();int blockSize = 64; // HMAC-SHA1 block sizeif (key.length() > blockSize) {key = QCryptographicHash::hash(key, QCryptographicHash::Sha1);} else if (key.length() < blockSize) {key = key.leftJustified(blockSize, '\0');}QByteArray ipad(blockSize, 0x36);QByteArray opad(blockSize, 0x5c);// XOR key with inner and outer paddingfor (int i = 0; i < blockSize; i++) {ipad[i] = ipad[i] ^ key.at(i);opad[i] = opad[i] ^ key.at(i);}QByteArray innerHash = QCryptographicHash::hash(ipad + data, QCryptographicHash::Sha1);QByteArray finalData = opad + innerHash;QByteArray signData = QCryptographicHash::hash(finalData, QCryptographicHash::Sha1);// Encode the result in Base64QByteArray base64SignData = signData.toBase64();return QString(base64SignData);
}QString MainWindow::sign2(const QString &accessSecret, const QString &stringToSign)
{QByteArray key = accessSecret.toUtf8();QByteArray data = stringToSign.toUtf8();// Calculate HMAC-SHA1QByteArray signData = QMessageAuthenticationCode::hash(data, key, QCryptographicHash::Sha1);// Encode the result in Base64QByteArray base64SignData = QByteArray(signData).toBase64();return QString(base64SignData);
}void MainWindow::on_imgBtn_clicked()
{QString imgPath = QFileDialog::getOpenFileName(this, "select image", "", tr("Images (*.png *.xpm *.jpg)"));doAliDetectLivingFace();ui->imgLineEdit->setText(imgPath);
}

        关键就是doAliDetectLivingFace函数,里面有几个细节:
1、时间的获取需要比当前时间早8个小时

2、注意stringToSign获取细节,url的query需要按字母顺序排序好,同时需要经specialUrlEncode,这一块自己仔细看代码

3、获取认证字符串的函数sign、sign2都可以使用,是一样的结果,其中sign函数呈现了更多细节

        另外,考虑到有些开发者只熟悉原生c++,不熟悉qt,而上面sign函数是关键,其它地方都好写出替代代码,所以这里给出用openssl实现的sign函数,qt的开发者可以不管这个
 

std::string SignUtil::sign(const std::string &accessSecret, const std::string &stringToSign)
{unsigned char hash[EVP_MAX_MD_SIZE];unsigned int hashLen = 0;// 初始化HMAC上下文HMAC_CTX* hmacCtx = HMAC_CTX_new();HMAC_Init_ex(hmacCtx, accessSecret.c_str(), accessSecret.length(), EVP_sha1(), NULL);// 更新HMAC上下文HMAC_Update(hmacCtx, (const unsigned char *)stringToSign.c_str(), stringToSign.length());// 完成HMAC计算HMAC_Final(hmacCtx, hash, &hashLen);// 释放HMAC上下文HMAC_CTX_free(hmacCtx);// 创建一个Base64编码器BIO* bio = BIO_new(BIO_s_mem());BIO* b64 = BIO_new(BIO_f_base64());bio = BIO_push(b64, bio);// 将哈希值写入BIOBIO_write(bio, hash, hashLen);BIO_flush(bio);// 从BIO读取Base64编码后的字符串BUF_MEM* buffer;BIO_get_mem_ptr(bio, &buffer);std::string base64Encoded(buffer->data, buffer->length);// 清理BIOBIO_free_all(bio);return base64Encoded;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tita:什么是 360 评估?

360 评估是一个专业的反馈机会&#xff0c;使一组同事和经理能够提供有关同事绩效的反馈。与仅由其经理评估员工工作绩效的典型员工绩效评估不同&#xff0c;360 评估会考虑来自同事和报告员工的反馈&#xff0c;甚至包括客户和与员工互动的其他人。 Tita&#xff1a;什么是 3…

jenkins ssh 免密报错Host key verification failed.

jenkins 发布项目&#xff0c;ssh连接远程服务器时报错&#xff1a;Host key verification failed. 解决&#xff1a; 原因是生成的sshkey不是用的jenkins用户&#xff0c;所以切换用户到&#xff1a;jenkins重新生成sshkey su jenkins ssh-keygen -t rsa ssh-copy-id -i ~/…

【Linux第七课--基础IO】内存级文件、重定向、缓冲区、文件系统、动态库静态库

目录 引入内存级文件重新使用C文件接口 -- 对比重定向写文件读文件文件流 认识文件操作的系统接口open参数 -- flagflag的内容宏的传参方式 open关闭文件写文件读文件结论 引入文件描述符fd、对文件的理解理解一切皆文件方法集文件fd的分配规则 重定向代码的重定向输入重定向输…

创意设计的起点:十大网页设计模板网站

对于网页设计领域的专业人士和爱好者而言&#xff0c;从零开始构建一个网页可能会耗费大量的时间和劳力。幸运的是&#xff0c;我们可以通过使用现成的网页模板来提升工作效率并节省宝贵的时间。一个好的模板不仅能提高设计效率&#xff0c;还能激发出卓越的创意灵感。因此&…

鸿蒙Harmony-矩形绘制组件Rect使用详解

目录 一&#xff0c;定义 二&#xff0c;绘制自定义图形 三&#xff0c;作为其他控件背景使用 一&#xff0c;定义 Rect是鸿蒙提供的矩形绘制组件&#xff0c;利用该组件可以绘制矩形背景&#xff0c;矩形图案等 官方提供的参数和属性&#xff1a; 参数&#xff1a; 参数名…

netty之bootstrap源码分析

写在前面 本文看下bootstrap类。 1&#xff1a;正文 1.1&#xff1a;干啥的&#xff1f; 在进行netty编程的时候都是先创建一个bootstrap&#xff0c;然后设置很多的东西&#xff0c;如下代码&#xff08;服务端启动代码&#xff09;&#xff1a; ServerBootstrap b new …

c# WinForm弹出窗体时不获取焦点方法

WinForm开发的软件有时候需要在屏幕右下角弹窗进行一些提示&#xff0c;通常使用new MyForm().Show()即可实现此需求。 但是当MyForm显示出来时&#xff0c;会抢走原本窗体上的光标&#xff0c;导致原本在软件上比如打字或者其他操作被中断&#xff0c;非常不人性化&#xff0…

方差和标准差哪些事儿

1.方差 在概率论与数理统计中&#xff0c;方差用来度量随机变量和其数学期望&#xff08;即均值&#xff09;之间的偏离程度。方差是各个数据与平均数之差的平方和的平均数,即: s(1/n)[(x1-x_)^2 (x2-x_)^2 …(xn-x_)^2] 其中&#xff0c;x_表示样本的平均数&#xff0c;n表示…

Hudi Upsert原理

1. 前言 如果要深入了解Apache Hudi技术的应用或是性能调优&#xff0c;那么明白源码中的原理对我们会有很大的帮助。Upsert是Apache Hudi的核心功能之一&#xff0c;主要完成增量数据在HDFS/对象存储上的修改&#xff0c;并可以支持事务。而在Hive中修改数据需要重新分区或重…

了解SQLExpress数据库

SQLExpress&#xff08;Microsoft SQL Server Express&#xff09;是由微软公司开发的一款免费且轻量级的数据库管理系统。以下是关于SQLExpress的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; SQLExpress是Microsoft SQL Server的一个缩减版或基础版&#xff0c;旨在…

空天地遥感数据识别与计算

在科技飞速发展的时代&#xff0c;遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究&#xff0c;空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而&#xff0c;对于许多专业人士而言&#xff0c;如何高效地处…

JavaEE-多线程初阶(2)

目录 1.创建线程的五种写法 1.1 继承Thread类 1.2 实现Runnable接口 1.3 使用匿名内部类 1.4 使用Runnable&#xff0c;匿名内部类 1.5 引入lambda表达式 2.Thread类及常见方法 2.1 认识Thread 2.2 Thread的常见构造方法 2.3 Thread的几个常见属性 关于后台线程 关…

【网络安全】揭示 Web 缓存污染与欺骗漏洞

未经许可,不得转载。 文章目录 前言污染与欺骗Web 缓存污染 DoS1、HTTP 头部超大 (HHO)2、HTTP 元字符 (HMC)3、HTTP 方法覆盖攻击 (HMO)4、未键入端口5、重定向 DoS6、未键入头部7、Host 头部大小写规范化8、路径规范化9、无效头部 CP-DoS10、HTTP 请求拆分Web 缓存污染与有害…

重工业数字化转型创新实践:某国家特大型钢铁企业如何快速落地基于实时数仓的数据分析平台

使用 TapData&#xff0c;化繁为简&#xff0c;摆脱手动搭建、维护数据管道的诸多烦扰&#xff0c;轻量替代 OGG, Kettle 等同步工具&#xff0c;以及基于 Kafka 的 ETL 解决方案&#xff0c;「CDC 流处理 数据集成」组合拳&#xff0c;加速仓内数据流转&#xff0c;帮助企业…

Golang | Leetcode Golang题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; func isSubseq(s, t string) bool {ptS : 0for ptT : range t {if s[ptS] t[ptT] {if ptS; ptS len(s) {return true}}}return false }func findLUSlength(strs []string) int {ans : -1 next:for i, s : range strs {for j, t : range s…

(C#面向初学者的 .NET 的生成 AI) 第 1 部分-简介

第 1 部分简介就是由Luis Quintanilla讲述本系列教程要学习哪些部分&#xff0c;基本都是介绍&#xff0c;内容不是很多。但可以先了解一下.net 生成式AI需要学习接触哪些东西。 在这个关于机器学习和AI的初学者系列中&#xff0c;Luis Quintanilla向.net开发人员介绍了基础知识…

【密码学】全同态加密基于多项式环计算的图解

全同态加密方案提供了一种惊人的能力 —— 能够在不知道数据具体内容的情况下对数据进行计算。这使得你可以在保持潜在敏感源数据私密的同时&#xff0c;得出问题的答案。 这篇文章的整体结构包括多项式环相关的数学介绍&#xff0c;基于多项式环的加密和解密是如何工作的&…

Spring Boot中解决BeanDefinitionStoreException问题的实战分享

目录 前言1. 问题背景2. 问题分析2.1 异常分析2.2 常见的错误原因2.3 排查过程 3. 解决方案3.1 清理缓存和重建项目3.1.1 清理IDEA缓存3.1.2 使用Maven清理并重建项目 3.2 升级Maven版本3.2.1 下载最新Maven版本3.2.2 IDEA配置新的Maven版本3.2.3 清理缓存并重新构建 3.3 验证问…

Java避坑案例 - 线程池未复用引发的故障复盘及源码分析

文章目录 问题现象问题定位问题代码根因分析现象剖析newCachedThreadPool 源码SynchronousQueue特点构造方法主要方法应用场景Code Demo运行结果 问题修复 问题现象 时不时有报警提示线程数过多&#xff0c;超过2000 个&#xff0c;收到报警后查看监控发现&#xff0c;瞬时线程…

AHB Matrix 四星级 验证笔记(1.8-1.9)scoreboard的实现

文章目录 前言一、scoreboard接收数据的方式和比较行为的策略选择1.接受数据的方式1. 首先是数据从哪儿来&#xff1f; 2.比较数据的方式1.方案一2.方案二3. 方案的选择 二、scoreboard的实现1.代码 三、tip1.编辑断点2. return3.有关函数的返回值&#xff1a;函数内部隐式声明…