阿里云提供了人脸识别的api,其示例除了c/c++,其他主流语言都有相应的实例。
本人由于项目债务和集成需要,需要用c/c++实现,若只是支持win/Linux平台,采用
acl_master源码库也可行,有需要的可参考《阿里云短信服务接口的c++实现》,
阿里云的短信服务接口与人脸识别在数据签名、加密等方面是一致的。
我当前项目由于跨平台支持android编译,所以采用了qt实现阿里云的人脸识别接口。
备注:若需要静态编译实现阿里云的人脸识别,可能 qt环境需要重新静态编译network模块,追加openssl静态编译支持,
更细节的实现可以参考《qt5.8_for_vs2015 and openssl静态编译 》。
阿里云的人脸识别主要有两个难点,其一是,若你直接传输图片内容,需要对图片内容进行编码,其二是需要实现签名认证。
下面就如何实现阿里云的人脸属性识别的过程(人脸检测定位、人脸比对类似):
1)首先需要开通 阿里云 的人脸识别服务,下面是本人在阿里云的云产品通用代金券链接:
https://promotion.aliyun.com/ntms/yunparter/invite.html?userCode=pfb80n4a
开通服务后,进入 人脸识别的控制台,在其左侧栏目有个API调试,点击进去,这里标注的
请求地址是我们需要用到的,例如:https://dtplus-cn-shanghai.data.aliyuncs.com/face/attribute
另外 Access Key ID和Access Key Secret在API调用也需要,在你的头像下的AccessKeys项点击进去获取即可。
2)阿里API说明手册指出,若图片内容指定url,需要你只身配备网络存储路径,采用阿里的OSS也是不错的选择,若直接传输图片内容,需要采用base64编码,刚好qt5.8就能直接实现,下面就直接传输本地图片内容进行阿里云人脸识别API调用,记得qt工程文件需要添加,
QT += network
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="<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)), // this, SLOT(slotSslErrors(QList))); 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="<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)), // this, SLOT(slotSslErrors(QList))); 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 把字符串hashed转换为Hex,内存中的ASCII码arrayFromHexString QByteArray arrayFromHexString = QByteArray::fromHex(hashed.toHex()); qDebug()<<"hmacSha1内存中的ASCII码 arrayFromHexString \n"<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:"<