目录
一、阿里云人脸识别的api
二、qt实现阿里云人脸识别API调用
三、完整源码
一、阿里云人脸识别的api
阿里云提供了人脸识别的api,其示例除了c/c++,其他主流语言都有相应的实例。
本人由于项目债务和集成需要,需要用c/c++实现,若只是支持win/Linux平台,采用acl_master源码库也可行,有需要的可参考《阿里云短信服务接口的c++实现》,阿里云的短信服务接口与人脸识别在数据签名、加密等方面是一致的。
我当前项目由于跨平台支持android编译,所以采用了qt实现阿里云的人脸识别接口。
备注:若需要静态编译实现阿里云的人脸识别,可能 qt环境需要重新静态编译network模块,追加openssl静态编译支持,
更细节的实现可以参考《qt5.8_for_vs2015 and openssl静态编译 》。
阿里云的人脸识别主要有两个难点:
其一是,若你直接传输图片内容,需要对图片内容进行编码;
其二是需要实现签名认证。
下面就如何实现阿里云的人脸属性识别的过程(人脸检测定位、人脸比对类似):
1)首先需要开通 阿里云 的人脸识别服务,下面是本人在阿里云的云产品通用代金券链接:
阿里云限量红包
开通服务后,进入 人脸识别的控制台,在其左侧栏目有个API调试,点击进去,这里标注的
请求地址是我们需要用到的,例如:https://dtplus-cn-shanghai.data.aliyuncs.com/face/attribute
另外 Access Key ID和Access Key Secret在API调用也需要,在你的头像下的AccessKeys项点击进去获取即可。
2)阿里API说明手册指出,若图片内容指定url,需要你只身配备网络存储路径,采用阿里的OSS也是不错的选择,若直接传输图片内容,需要采用base64编码。
二、qt实现阿里云人脸识别API调用
刚好qt5.8就能直接实现base64编码,下面就直接传输本地图片内容进行阿里云人脸识别API调用,记得qt工程文件需要添加,
1QT += network
示例代码:
1
2
3
4
5
6
7
8
9
10QByteArray FaceDetectObject::Image_To_Base64(QString image_path) { QImage image(image_path); QByteArray ba; QBuffer buf(&ba); image.save(&buf,"jpg"); QByteArray hexed = ba.toBase64(); buf.close(); return hexed; }
3)关于人脸识别的通信接口的签名的细节要求查看官方说明文档《API校验规范》章节,其内容要求UTF-8和Base64编码,签名算法遵循RFC 2104HMAC-SHA1规范。
MD5转换示例代码:
1
2
3
4
5
6
7
8QByteArray FaceDetectObject::getMD5(QByteArray bytes_) { QCryptographicHash ch(QCryptographicHash::Md5); QByteArray ret; ch.addData(bytes_); ret = ch.result(); return ret; }
1
2HMACSha1算法示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25QByteArray FaceDetectObject::HMACSha1(QByteArray key, QByteArray baseString) { int blockSize = 64; // HMAC-SHA-1 block size, defined in SHA-1 standard if (key.length() > blockSize) { // if key is longer than block size (64), reduce key length with SHA-1 compression key = QCryptographicHash::hash(key, QCryptographicHash::Sha1); } QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char "6" QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char "/" // ascii characters 0x36 ("6") and 0x5c ("/") are selected because they have large // Hamming distance (http://en.wikipedia.org/wiki/Hamming_distance) for (int i = 0; i < key.length(); i++) { innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length } // result = hash ( outerPadding CONCAT hash ( innerPadding CONCAT baseString ) ).toBase64 QByteArray total = outerPadding; QByteArray part = innerPadding; part.append(baseString); total.append(QCryptographicHash::hash(part, QCryptographicHash::Sha1)); QByteArray hashed = QCryptographicHash::hash(total, QCryptographicHash::Sha1); /// 注意——>把字符串hashed转换为Hex,内存中的ASCII码arrayFromHexString QByteArray arrayFromHexString = QByteArray::fromHex(hashed.toHex()); qDebug()<<"hmacSha1内存中的ASCII码 arrayFromHexString n"<<arrayFromHexString.toHex(); return arrayFromHexString; }
4)阿里云一般对于http协议的时间格式要求是GMT的
也就是QT里面的UTC格式, 实现 样例:
1
2QLocale lo = QLocale::English;//设置QLocale为英文 QString date = lo.toString(QDateTime::currentDateTimeUtc(),"ddd, dd MMM yyyy hh:mm:ss")+QString(" GMT");
其通信协议需要openssl支持才能实现https请求,实现 样例:
1
2
3
4
5QNetworkRequest request; QSslConfiguration config; config.setPeerVerifyMode(QSslSocket::VerifyNone); config.setProtocol(QSsl::TlsV1_0); request.setSslConfiguration(config);
5)实现阿里云的人脸属性识别请求,记得把key和密钥换成自己的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62void FaceDetectObject::do_post_al(QByteArray bytearray) { qDebug()<<"img_bytearray_size="<<bytearray.size()<<"n"; // qDebug()<<"img_bytearray="<<bytearray.data()<<"n"; url = QUrl("https://dtplus-cn-shanghai.data.aliyuncs.com/face/attribute",QUrl::TolerantMode); // url.toEncoded(); qDebug() <<"url="<<url.url()<<"n"; QString ak_id = "**************"; //you key QString ak_secret = "**************************";//you secret /* * http header 参数 */ QString method = "POST"; QString accept = "application/json"; QString content_type = "application/json"; QLocale lo = QLocale::English;//设置QLocale为英文 QString date = lo.toString(QDateTime::currentDateTimeUtc(),"ddd, dd MMM yyyy hh:mm:ss")+QString(" GMT"); qDebug() <<"date = " << date <<"n"; //1.对body做MD5+BASE64加密 QByteArray body = QString("{"type":"1","content":"%1"}").arg(bytearray.data()).toLocal8Bit(); qDebug() <<"body = " << body <<"n"; QByteArray bodyMd5 = getMD5(body); qDebug() <<"bodyMd5 = " << bodyMd5 <<"n"; QString bodyBase64 = bodyMd5.toBase64(); qDebug() <<"bodyBase64 = " << bodyBase64 <<"n"; QString stringToSign = method + "n" + accept + "n" + bodyBase64 + "n" + content_type + "n" + date + "n"+ url.path(); qDebug() << "stringToSign="<<stringToSign<<"n"; // 2.计算 HMAC-SHA1 QString signature = HMACSha1(ak_secret.toLocal8Bit(),stringToSign.toLocal8Bit()).toBase64(); qDebug() << "signature="<<signature<<"n"; // 3.得到 authorization header QString authHeader = "Dataplus " + ak_id + ":" + signature; qDebug() << "authHeader="<<authHeader<<"n"; QNetworkRequest request; // request.sslConfiguration().setPeerVerifyMode(QSslSocket::VerifyNone); // request.sslConfiguration().setProtocol(QSsl::TlsV1_0); QSslConfiguration config; config.setPeerVerifyMode(QSslSocket::VerifyNone); config.setProtocol(QSsl::TlsV1_0); request.setSslConfiguration(config); request.setUrl(url); request.setRawHeader(QByteArray("accept"), accept.toLocal8Bit()); request.setHeader(QNetworkRequest::ContentTypeHeader,content_type); request.setRawHeader(QByteArray("date"), date.toLocal8Bit()); request.setRawHeader(QByteArray("Authorization"), authHeader.toLocal8Bit()); // request.setRawHeader(QByteArray("Connection"), QByteArray("keep-alive")); if(reply != Q_NULLPTR) {//更改reply指向位置钱一定要保证之前的定义了自动delete reply->deleteLater(); } reply = manager->post(request,body); // connect(reply, &QNetworkReply::finished, this, &FaceDetectThread::finishedReplay); connect(reply, SIGNAL(finished()), this, SLOT(finishedReplay())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); // connect(reply, SIGNAL(sslErrors(QList<QSslError>)), // this, SLOT(slotSslErrors(QList<QSslError>))); connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(downloadProgress(qint64,qint64))); qDebug() << "start post_al"; }
备注:bytearray是base64的图片内容
6)请求返回的数据为JSON格式 描述,字段描述细节参考官方的人脸属性识别API 调用说明,内容有点多,我就不截图。
返回数据获取示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28void FaceDetectObject::finishedReplay() { QByteArray bytes = reply->readAll(); const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); reply->deleteLater(); reply = Q_NULLPTR; if (!redirectionTarget.isNull()) {//如果网址跳转重新请求 const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl()); qDebug()<<"redirectedUrl:"<<redirectedUrl.url()<<"n"; url = redirectedUrl; qDebug()<<"new_url="<<url.toString().toLocal8Bit()<<"n"; //写出新url,测试使用 QFile f("url_.txt");//写出文件 f.open(QFile::WriteOnly); f.write(url.toString().toLocal8Bit()); f.close(); return; } qDebug()<<"finished:n"; QString html_text = bytes; qDebug()<<"get ready,read size:"<<html_text.size(); qDebug()<< "ret_html_text:n"<<html_text<<"n"; //保存结果,测试使用 QFile f("result.html");//写出文件 f.open(QFile::WriteOnly); f.write(bytes); f.close(); }
返回结果示例:
1{"face_num":1,"face_rect":[391,365,94,127],"face_prob":[1.0],"pose":[5.843783378601074,-3.454075336456299,2.8692541122436523],"landmark_num":105,"landmark":[..展示需要删除..],"iris":[417.10675048828125,415.4582214355469,4.029685020446777,460.1661071777344,418.9272155761719,4.029685020446777],"gender":[0],"age":[28],"expression":[0],"glass":[0],"dense_fea_len":1024,"dense_fea":"[..展示需要删除..]","errno":0,"request_id":"3bad9b68-b337-4c07-8661-403178948a31"}
取得返回结果后就是 业务应用的范畴了,人脸检测定位、人脸比对实现类似。基于我的业务逻辑只需要脸数、性别、年龄、笑容,示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93//输入参数来自:QByteArray bytes = reply->readAll(); void FaceDetectObject::JsonDecode(QByteArray bytes) { QJsonParseError json_error; QJsonDocument retVals = QJsonDocument::fromJson(bytes,&json_error); if(json_error.error == QJsonParseError::NoError) { if(retVals.isObject()) { int face_num_val=0 ; QVector<bool> genders; QVector<int> ages; QVector<bool> expressions; QJsonObject obj = retVals.object(); if(obj.contains("face_num")) { QJsonValue face_num_Json = obj.value("face_num"); qDebug() <<"face_num_Json="<< face_num_Json.toInt()<<"n"; if(face_num_Json.isDouble()) { face_num_val = face_num_Json.toInt(); } } if(obj.contains("gender")) { QJsonValue gender_Json = obj.value("gender"); if(gender_Json.isArray()) { QJsonArray gender_vals = gender_Json.toArray(); qDebug() <<"gender_vals="<< gender_vals<<"n"; foreach (QJsonValue gval, gender_vals) { if(gval.isDouble()) genders.push_back(gval.toInt()>0?true:false); } if(genders.size()!=face_num_val) { qDebug() << QString("gender vector num(%1) is not map face_num(%2)!") .arg(genders.size()).arg(face_num_val); } }else{ qDebug() << "gender_Json value type is not map Array!"; } } if(obj.contains("age")) { QJsonValue age_Json = obj.value("age"); if(age_Json.isArray()) { QJsonArray age_vals = age_Json.toArray(); qDebug() <<"age_vals="<< age_vals<<"n"; foreach (QJsonValue age_val, age_vals) { if(age_val.isDouble()) ages.push_back(age_val.toInt()); } if(ages.size()!=face_num_val) { qDebug() << QString("ages vector num(%1) is not map face_num(%2)!") .arg(ages.size()).arg(face_num_val); } }else{ qDebug() << "age_Json value type is not map Array!"; } } if(obj.contains("expression")) { QJsonValue expression_Json = obj.value("expression"); if(expression_Json.isArray()) { QJsonArray expression_vals = expression_Json.toArray(); qDebug() <<"expression_vals="<< expression_vals<<"n"; foreach (QJsonValue expression_val, expression_vals) { if(expression_val.isDouble()) expressions.push_back(expression_val.toInt()>0?true:false); } if(expressions.size()!=face_num_val) { qDebug() << QString("expressions vector num(%1) is not map face_num(%2)!") .arg(expressions.size()).arg(face_num_val); } }else{ qDebug() << "expression_Json value type is not map Array!"; } } qDebug() << "face_num_val="<<face_num_val<<"n" << "genders="<<genders<<"n" << "ages="<<ages<<"n" << "expressions="<<expressions<<"n"; } }else{ qDebug() << "QJsonDocument::fromJson fail:"<<json_error.errorString()<<"n"; }
三、完整源码
下面给出本实例的完整通信接口供有需要的朋友,记得换成自己的key和密钥,由于是示例代码,很多地方未做优化和产品化考虑,请大家斟酌参考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#ifndef FACEDETECTOBJECT_H #define FACEDETECTOBJECT_H #include <QObject> #include <QString> #include <QByteArray> #include <QImage> #include <QNetworkAccessManager> #include <QUrl> #include <QNetworkRequest> #include <QNetworkReply> class FaceDetectObject : public QObject { Q_OBJECT public: FaceDetectObject(QObject * parent = 0); ~FaceDetectObject(); private: QByteArray getMD5(QByteArray bytes_); QByteArray HMACSha1(QByteArray key, QByteArray baseString); QByteArray Image_To_Base64(QString image_path); QImage Base64_To_Image(QByteArray bytearray,QString save_Path); QByteArray Image_To_ByteArray(QString image_path); QImage ByteArray_To_Image(QByteArray bytearray,QString save_Path); public slots: void do_get(); void do_post_img(QString imgFile); void do_post(QByteArray bytearray); void do_post_al(QByteArray bytearray); private slots: void finishedReplay(); void slotError(QNetworkReply::NetworkError net_error); void downloadProgress(qint64 bytesSent, qint64 bytesTotal); private: QNetworkAccessManager *manager; QUrl url; QNetworkReply *reply; }; #endif // FACEDETECTOBJECT_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262#include "facedetectobject.h" #include <QBuffer> #include <QCryptographicHash> #include <QDateTime> #include <QFile> #include <QSslConfiguration> #include <QSslSocket> #include <QDebug> FaceDetectObject::FaceDetectObject(QObject * parent) : QObject(parent) { // //test // QByteArray src = Image_To_ByteArray("fdtimg.jpg"); // QImage dest = ByteArray_To_Image(src,"fdtimg_c.jpg"); manager =new QNetworkAccessManager(this); url = QUrl("http://www.baidu.com/"); reply = Q_NULLPTR; } FaceDetectObject::~FaceDetectObject() { } void FaceDetectObject::do_get() { QNetworkRequest request; request.setUrl(url); if(reply != Q_NULLPTR) {//更改reply指向位置钱一定要保证之前的定义了自动delete reply->deleteLater(); } reply = manager->get(request); // connect(reply, &QNetworkReply::finished, this, &FaceDetectThread::finishedReplay); 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))); qDebug() << "start get"; } void FaceDetectObject::do_post_img(QString imgFile) { qDebug()<<"do_post_img and imgfile="<<imgFile<<"n"; QByteArray imgByteArray = Image_To_Base64(imgFile); do_post_al(imgByteArray); } void FaceDetectObject::do_post(QByteArray bytearray) { QNetworkRequest request; request.setUrl(url); request.setRawHeader("Content-Type","application/x-www-form-urlencoded"); if(reply != Q_NULLPTR) {//更改reply指向位置钱一定要保证之前的定义了自动delete reply->deleteLater(); } reply = manager->post(request,bytearray); // connect(reply, &QNetworkReply::finished, this, &FaceDetectThread::finishedReplay); connect(reply, SIGNAL(finished()), this, SLOT(finishedReplay())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); // connect(reply, SIGNAL(sslErrors(QList<QSslError>)), // this, SLOT(slotSslErrors(QList<QSslError>))); connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(downloadProgress(qint64,qint64))); qDebug() << "start post"; } void FaceDetectObject::do_post_al(QByteArray bytearray) { qDebug()<<"img_bytearray_size="<<bytearray.size()<<"n"; // qDebug()<<"img_bytearray="<<bytearray.data()<<"n"; url = QUrl("https://dtplus-cn-shanghai.data.aliyuncs.com/face/attribute",QUrl::TolerantMode); // url.toEncoded(); qDebug() <<"url="<<url.url()<<"n"; QString ak_id = "************"; //key QString ak_secret = "*************************"; //secret /* * http header 参数 */ QString method = "POST"; QString accept = "application/json"; QString content_type = "application/json"; QLocale lo = QLocale::English;//设置QLocale为英文 QString date = lo.toString(QDateTime::currentDateTimeUtc(),"ddd, dd MMM yyyy hh:mm:ss")+QString(" GMT"); qDebug() <<"date = " << date <<"n"; //1.对body做MD5+BASE64加密 QByteArray body = QString("{"type":"1","content":"%1"}").arg(bytearray.data()).toLocal8Bit(); qDebug() <<"body = " << body <<"n"; QByteArray bodyMd5 = getMD5(body); qDebug() <<"bodyMd5 = " << bodyMd5 <<"n"; QString bodyBase64 = bodyMd5.toBase64(); qDebug() <<"bodyBase64 = " << bodyBase64 <<"n"; QString stringToSign = method + "n" + accept + "n" + bodyBase64 + "n" + content_type + "n" + date + "n"+ url.path(); qDebug() << "stringToSign="<<stringToSign<<"n"; // 2.计算 HMAC-SHA1 QString signature = HMACSha1(ak_secret.toLocal8Bit(),stringToSign.toLocal8Bit()).toBase64(); qDebug() << "signature="<<signature<<"n"; // 3.得到 authorization header QString authHeader = "Dataplus " + ak_id + ":" + signature; qDebug() << "authHeader="<<authHeader<<"n"; QNetworkRequest request; // request.sslConfiguration().setPeerVerifyMode(QSslSocket::VerifyNone); // request.sslConfiguration().setProtocol(QSsl::TlsV1_0); QSslConfiguration config; config.setPeerVerifyMode(QSslSocket::VerifyNone); config.setProtocol(QSsl::TlsV1_0); request.setSslConfiguration(config); request.setUrl(url); request.setRawHeader(QByteArray("accept"), accept.toLocal8Bit()); request.setHeader(QNetworkRequest::ContentTypeHeader,content_type); request.setRawHeader(QByteArray("date"), date.toLocal8Bit()); request.setRawHeader(QByteArray("Authorization"), authHeader.toLocal8Bit()); // request.setRawHeader(QByteArray("Connection"), QByteArray("keep-alive")); if(reply != Q_NULLPTR) {//更改reply指向位置钱一定要保证之前的定义了自动delete reply->deleteLater(); } reply = manager->post(request,body); // connect(reply, &QNetworkReply::finished, this, &FaceDetectThread::finishedReplay); connect(reply, SIGNAL(finished()), this, SLOT(finishedReplay())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(slotError(QNetworkReply::NetworkError))); // connect(reply, SIGNAL(sslErrors(QList<QSslError>)), // this, SLOT(slotSslErrors(QList<QSslError>))); connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(downloadProgress(qint64,qint64))); qDebug() << "start post_al"; } QByteArray FaceDetectObject::getMD5(QByteArray bytes_) { QCryptographicHash ch(QCryptographicHash::Md5); QByteArray ret; ch.addData(bytes_); ret = ch.result(); return ret; } QByteArray FaceDetectObject::HMACSha1(QByteArray key, QByteArray baseString) { int blockSize = 64; // HMAC-SHA-1 block size, defined in SHA-1 standard if (key.length() > blockSize) { // if key is longer than block size (64), reduce key length with SHA-1 compression key = QCryptographicHash::hash(key, QCryptographicHash::Sha1); } QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char "6" QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char "/" // ascii characters 0x36 ("6") and 0x5c ("/") are selected because they have large // Hamming distance (http://en.wikipedia.org/wiki/Hamming_distance) for (int i = 0; i < key.length(); i++) { innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length } // result = hash ( outerPadding CONCAT hash ( innerPadding CONCAT baseString ) ).toBase64 QByteArray total = outerPadding; QByteArray part = innerPadding; part.append(baseString); total.append(QCryptographicHash::hash(part, QCryptographicHash::Sha1)); QByteArray hashed = QCryptographicHash::hash(total, QCryptographicHash::Sha1); /// 注意——>把字符串hashed转换为Hex,内存中的ASCII码arrayFromHexString QByteArray arrayFromHexString = QByteArray::fromHex(hashed.toHex()); qDebug()<<"hmacSha1内存中的ASCII码 arrayFromHexString n"<<arrayFromHexString.toHex(); return arrayFromHexString; } QByteArray FaceDetectObject::Image_To_Base64(QString image_path) { QImage image(image_path); QByteArray ba; QBuffer buf(&ba); image.save(&buf,"jpg"); QByteArray hexed = ba.toBase64(); buf.close(); return hexed; } QImage FaceDetectObject::Base64_To_Image(QByteArray bytearray,QString save_Path) { QByteArray Ret_bytearray; Ret_bytearray = QByteArray::fromBase64(bytearray); QBuffer buffer(&Ret_bytearray); buffer.open(QIODevice::WriteOnly); QImage imageresult; imageresult.loadFromData(Ret_bytearray); if(save_Path != "") { qDebug() <<"save" ; imageresult.save(save_Path); } return imageresult; } QByteArray FaceDetectObject::Image_To_ByteArray(QString image_path) { qDebug()<<"image_path="<<image_path<<"n"; QImage image(image_path); QByteArray ba; QBuffer buf(&ba); image.save(&buf,"jpg"); qDebug()<<"ba_size="<<ba.size()<<"n"; // qDebug()<<"ba="<<ba.data()<<"n"; buf.close(); return ba; } QImage FaceDetectObject::ByteArray_To_Image(QByteArray bytearray,QString save_Path) { QBuffer buffer(&bytearray); buffer.open(QIODevice::WriteOnly); QImage imageresult; imageresult.loadFromData(bytearray); if(save_Path != "") { qDebug() <<"save" ; imageresult.save(save_Path); } return imageresult; } void FaceDetectObject::finishedReplay() { QByteArray bytes = reply->readAll(); const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); reply->deleteLater(); reply = Q_NULLPTR; if (!redirectionTarget.isNull()) {//如果网址跳转重新请求 const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl()); qDebug()<<"redirectedUrl:"<<redirectedUrl.url()<<"n"; url = redirectedUrl; qDebug()<<"new_url="<<url.toString().toLocal8Bit()<<"n"; //写出新url,测试使用 QFile f("url_.txt");//写出文件 f.open(QFile::WriteOnly); f.write(url.toString().toLocal8Bit()); f.close(); return; } qDebug()<<"finished:n"; QString html_text = bytes; qDebug()<<"get ready,read size:"<<html_text.size(); qDebug()<< "ret_html_text:n"<<html_text<<"n"; //保存结果,测试使用 QFile f("result.html");//写出文件 f.open(QFile::WriteOnly); f.write(bytes); f.close(); } void FaceDetectObject::slotError(QNetworkReply::NetworkError net_error) { qDebug()<< "slotError:"<<net_error; } void FaceDetectObject::downloadProgress(qint64 bytesSent, qint64 bytesTotal) { qDebug()<< "ndownloadProgress done:n"; qDebug() << "bytesSent: " << bytesSent<< " " << "bytesTocal: " << bytesTotal; }
最后
以上就是狂野柚子最近收集整理的关于qt5.8(c++)实现阿里云人脸识别云接口的全部内容,更多相关qt5内容请搜索靠谱客的其他文章。
发表评论 取消回复