通过face++平台可进行人脸识别、人脸检测、人脸比对、人脸搜查等等。下面是使用调用face++API进行的人脸的各种操作。
- 调用face++接口可以通过网络API也可以通过离线SDK,这里先介绍Qt通过发起Http请求调用face++接口。调用face++接口首先需要在官网注册账号,获得api_key api_secret。这时调用接口必须用到的两个参数。
- 人脸识别的几个关键概念
(1)人脸
人脸(Face)在人脸识别技术中特指图像中发现的人脸,当对一张图片进行人脸检测时,会将检测到的人脸记录下来,包括人脸在图片中的位置,用一个系统标识face_token来表示。注意:对同一张图片进行多次人脸检测,对同一个人脸会得到不同的face_token。
(2)人脸集合
人脸集合(FaceSet)是用来存储检测到人脸的存储对象。一个FaceSet内face_token是不重复的。
(3)人脸比对/人脸搜索
计算机检测到图片中一个人脸之后,通过人脸判断人身份的过程被称为人脸比对/人脸搜索。
人脸比对指采集新的人脸,与一个已知身份用户的人脸进行比对,判断新的人脸是否属于该已知身份用户。人脸比对需要调用Compare API。
人脸搜索是指采集用户新的人脸,在多个已知身份用户的人脸集合中进行搜索,找出新的人脸属于哪一个已知身份用户。人脸搜索需要调用Search API。 - 下面通过调用人脸识别的接口展示如何调用face++接口
以上几个参数是api调用必须的参数,具体可以参考官方文档:https://console.faceplusplus.com.cn/documents/4888373
Qt可以通过QNetworkAccessManager、QNetworkrequest、Qurl、QHttpPart、QHttpMultiPart 等发起网络请求调用face++接口。
代码如下:
//获得类型为String类型的参数
QHttpPart Face::setHttpPart(QByteArray body, QVariant value)
{
QHttpPart part ;
part.setHeader(QNetworkRequest::ContentDispositionHeader,value);
part.setBody(body);
return part;
}
//获得类型为图像的参数 ,这里返回的是图片的二进制形式
QHttpPart Face::imageHttpPart(const QString &filename, QVariant value)
{
QHttpPart imagePart ;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader,value);
QImage image(filename);
QByteArray ba;
QByteArray hex;
QBuffer buf(&ba);
if(buf.open(QIODevice::WriteOnly)){
image.save(&buf,"jpeg",20);
hex = ba.toBase64();
buf.close();
}else{
qDebug()<<"buf.error"<<buf.errorString();
}
imagePart.setBody(hex);
return imagePart;
}
//人脸检测,filename是传递的图片的路径
void Face::detectFace(const QString &filename)
{
QTimer timer;//检查确认联网情况
timer.setInterval(10000);//设置单次请求时间
timer.setSingleShot(true);
QNetworkAccessManager *manager = new QNetworkAccessManager;
if(filename!=""){
QUrl url("https://api-cn.faceplusplus.com/facepp/v3/detect");
//必须使用QHttpMultiPart的方式传递参数
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart apikey = setHttpPart(this->apiKey.toLatin1(),QVariant("form-data; name=\"api_key\""));
QHttpPart apisecret = setHttpPart(this->apiSecret.toLatin1(),QVariant("form-data; name=\"api_secret\""));
multiPart->append(apikey);
multiPart->append(apisecret);
//如果传递的图片是url,那下面name后面的就是\"image_url\"";
//如果传递的图片是二进制文件,那么name后面的就是"\image_base64\"";
//如果传递的图片是文件,那么name后面的就是"\image_file\"";
QString dataform = "form-data; name=\"image_base64\"";
QHttpPart imagePart = imageHttpPart(filename.toLatin1(),dataform);
multiPart->append(imagePart);
//发起请求
QNetworkRequest request(url);
//必须以post的方式请求
QNetworkReply *reply = manager->post(request, multiPart);
// 用 reply 删除 multiPart
multiPart->setParent(reply);
//时间循环机制
QEventLoop loop;
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
timer.start();
loop.exec(); //loop循环
if (timer.isActive()){
//此时 QNetworkReply::finished,响应完成,还尚未超时
timer.stop();
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (reply->error() != QNetworkReply::NoError) {
this->isError=true;
qDebug() << "In detectImage the error is "<<reply->error()<<reply->errorString();
return ;
}else {
finishedDetect(reply);
this->isError = false;
}
}else { //超过8秒
disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
reply->abort();
reply->deleteLater();
qDebug() << "联网超时";
}
}
}
这是通过使用Qt发起网络请求调用face++接口。