当前位置: 首页 > news >正文

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.mrgr.cn/news/63103.html

相关文章:

  • 萤石私有化设备视频平台EasyCVR视频融合平台如何构建农业综合监控监管系统?
  • 【neo4j】 neo4j cypher单一语句 optional 可选操作的技巧
  • aab上架谷歌市场流程(apk)
  • opencv-windows-cmake-Mingw-w64,编译opencv源码
  • c# 实现文件更新通知
  • 【大数据学习 | kafka】kafka的shell操作
  • 【图书介绍】案例可借鉴的Spring应用开发书
  • RabbitMQ的发布订阅模式
  • CSS 动画:网页设计的动态之美
  • 流水线(Pipeline)技术
  • ARKit读取LiDAR点云
  • C语言数据结构之二叉树(BINARY TREE)链式存贮的简单实现
  • 猫头虎分享:Claude AI、ChatGPT 和 知乎直答的 AI 搜索大战
  • 深入探索C语言:fread函数的高效文件读取艺术
  • 2023-2024年教育教学改革、教学成果奖等项目申请书合集-最新出炉 附下载链接
  • 【如何获取股票数据31】Python、Java等多种主流语言实例演示获取股票行情api接口之沪深A股融资融券标的股数据获取实例演示及接口API说明文档
  • 2024年10月31日Day1
  • 基于Python的自然语言处理系列(50):Soft Prompt 实现
  • IEC104规约的秘密之十九----6号文中的一些问题
  • IDEA修改生成jar包名字的两种方法实现
  • 前端八股文第八篇
  • Vue v-on 简写 @, v-bind 简写 :
  • Vue v-html v-once v-if
  • 定制化视频生成新模范!零样本主体驱动,精确运动控制!复旦阿里等发布DreamVideo-2
  • 消息队列面试——打破沙锅问到底
  • 2024最新IntelliJ IDEA常用的小技巧汇总,JAVA 新手上路必备