face++人脸识别、对比、检测全过程(使用qt调用face++接口

首先需要明白人脸、人脸集合(faceset)、人脸比对、人脸搜索的概念,以及如何调用face++接口。本文使用的是qt平台、语言C++。可以参考文章:人脸识别——Qt通过发起Http请求调用face++接口

下面是具体过程

具体代码如下:
头文件:

#ifndef FACE_H
#define FACE_H
#include <cstdio>
#include <QString>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include<opencv2/cxcore.h>
#include <QFile>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QHttpPart>
#include <QEventLoop>
#include <QTimer>
#include <QObject>
#include <stdio.h>
#include <QString>
#include "dbpostgis.h"
#include <QHttpMultiPart>
#include <QHttpPart>
#include <QPushButton>
#include <QLabel>
#include <string>
#include <vector>
#include <QFile>
#include <opencv/cv.h>
using namespace cv;
using namespace std;
class Face : public QObject
{
    Q_OBJECT
public:
    Face();
	void test()
    void detectAndDisplay(QString filePath,Mat frame);
    int connetNetWork(); //连接网络 使用face++ 否则使用openCV
    QHttpPart setHttpPart(QByteArray body,QVariant value);//used in face++ to set params
    QHttpPart imageHttpPart(const QString &filename,QVariant value);//used in face++ to set params
    QHttpMultiPart* setKeyAndSecret();
 
    void createFaceSet(QString displayName,QString outerId);
    QList<QString> getfaceToken(QByteArray responseData);
    void detectFace(const QString &filename);
    void addFaceTokens(QList<QString>faceTokens);
    //将两个人脸进行比对,来判断是否为同一个人,返回比对结果置信度和不同误识率下的阈值。
    void compareFace(const QString &faceTk1,const QString &faceTk2);
    //在已有的 FaceSet 中找出与目标人脸最相似的一张或多张人脸,返回置信度和不同误识率下的阈值。
    void searchFace(const QString &image);
public slots:
     void finishedQ(QNetworkReply *reply);
     void finishedDetect(QNetworkReply *reply);
     void finishedSearch(QNetworkReply *reply);
public:
    bool getIsError() const;
    void setIsError(bool value);
private:
    QNetworkAccessManager *manager;
    QString filename1;
    QString filename2;
    QString apiKey,apiSecret;
    QString faceset_token,outer_id;
    bool isError= false;
    double confidence;// searchApi 中得出的confidence
    QString face_token;//在faceSet中找出的和目标人脸最相思的人脸的face_token
};

#endif // FACE_H
Face::Face()
{
     //改成自己的图片路径
    filename1 = "E:\\photo\\photoManagement2\\test.jpg";
    filename2 = "E:\\photo\\photoManagement2\\test3.jpg";
    //followings are some keys used in face++ which cann't be modified
    this->apiKey = "api_key";//  改成自己的apikey和apisecret
    this->apiSecret = "api_secret";
    this->faceset_token ="xxx";//当创建好faceset集合后改为自己的faceset_token
    this->outer_id ="facesInPhotoManagement";
    confidence = 0.0;
    face_token = "";

}
//this function used as entry point for image recognition

void Face::test()
{
    QList<QString>filenames;
    filenames.push_back(filename1);
    filenames.push_back(filename2);
    detectFace(filenames);
    qDebug()<<("Hello Open CV!");
    //改为自己的图片路径
    QString filepath="E:/photo/photoManagement/hezhao1.jpg";
    connetNetWork();
}
int Face::connetNetWork(){
    QNetworkAccessManager netAccMana;
    QString urlString = "https://www.faceplusplus.com.cn/";
    QUrl url(urlString + "user/get");
    qDebug() <<url<<'\n';
    QNetworkRequest request(url); // use url to build a request object
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json;charset=utf-8")); // set request header
    QTimer timer;
    timer.setInterval(8000); // 设置超时时间 8 秒
    timer.setSingleShot(true); // 单次触发
    QNetworkReply *pReply = netAccMana.get(request);
    QEventLoop loop;
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    connect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    timer.start();
    loop.exec();  //loop循环
    if (timer.isActive()){
        timer.stop();//此时 QNetworkReply::finished,响应完成,还尚未超时
        if (pReply->error() != QNetworkReply::NoError) {
            qDebug() << "the error is"<<pReply->error()<<" ,使用openCV : ";
            return 0;
        }else {
            qDebug() << "联网测试成功,使用face++ : ";

        }
    }else { //超过5秒
        disconnect(pReply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        pReply->abort();
        pReply->deleteLater();
        qDebug() << "使用openCV : ";

    }
    return 1;

}

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;

}
void Face::createFaceSet(QString displayName, QString outerId)
{   QTimer timer;
    timer.setInterval(8000);
    timer.setSingleShot(true);
    QNetworkAccessManager *manager = new QNetworkAccessManager;
    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);
    if(displayName!=""){
        QHttpPart textPart1;
        textPart1 = setHttpPart(displayName.toLatin1(),QVariant("form-data;name=\"display_name\""));
        multiPart->append(textPart1);
    }
    if(outerId!=""){
        QHttpPart textPart2;
        textPart2 = setHttpPart(outerId.toLatin1(),QVariant("form-data;name=\"outer_id\""));
        multiPart->append(textPart2);
    }
    QUrl url("https://api-cn.faceplusplus.com/facepp/v3/faceset/create");
    QNetworkRequest request(url);
    QNetworkReply *reply = manager->post(request, multiPart);
    QEventLoop loop;
    connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
    connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
    timer.start();
    loop.exec();
    if (timer.isActive()){
        timer.stop();
        if (reply->error() != QNetworkReply::NoError) {
            this->isError = true;
            qDebug() << "In  faceSetCreate the error is "<<reply->errorString();
            return ;
        }else {
            this->isError = false;
            qDebug()<<reply->readAll();
        }
    }else { //超过8秒
        disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        reply->abort();
        reply->deleteLater();
        qDebug() << "联网超时";

    }
}

QList<QString> Face::getfaceToken(QByteArray responseData)
{
    QMap<QString,QVariant>map;
    QJsonDocument documment ;
    map = documment.fromJson(responseData).toVariant().toMap();
    if(isError){
        QString errorMsg = map.value("error_message").toString();
        QList<QString>errors;
        errors.push_back(errorMsg);
        return errors;
    }else{
        QJsonArray faces = map.value("faces").toJsonArray();
        QList<QString> faceTokens;
        for(int i = 0;i<faces.size();i++){
            QJsonObject faceObj =faces.at(i).toObject();
            QString faceToken = faceObj.value("face_token").toString();
            faceTokens.push_back(faceToken);
        }

        return faceTokens;

    }


}

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 *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);
        QString dataform = "form-data; name=\"image_base64\"";
        QHttpPart imagePart = imageHttpPart(filename.toLatin1(),dataform);
        multiPart->append(imagePart);
        QNetworkRequest request(url);
        QNetworkReply *reply = manager->post(request, multiPart);
        multiPart->setParent(reply); // 用 reply 删除 multiPart
        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() << "联网超时";

           }
    }
}
void Face::addFaceTokens(QList<QString> faceTokens)
{

    QTimer timer;
    timer.setInterval(8000);
    timer.setSingleShot(true);
    QNetworkAccessManager *manager = new QNetworkAccessManager;
    QHttpMultiPart *multiPart = new  QHttpMultiPart(QHttpMultiPart::FormDataType);
    QHttpPart apikey,apisecret,faceset_token,face_tokens;
    apikey = setHttpPart(this->apiKey.toLatin1(),QVariant("form-data; name=\"api_key\""));
    apisecret = setHttpPart(this->apiSecret.toLatin1(),QVariant("form-data; name=\"api_secret\""));
    faceset_token = setHttpPart(this->faceset_token.toLatin1(),QVariant("form-data; name=\"faceset_token\""));
    QString facetokenStr="";
    if(faceTokens.size()<1){
        return ;
    }
    for(int i = 0;i<faceTokens.size()-1;i++){
        facetokenStr=facetokenStr+faceTokens[i]+",";
    }
    facetokenStr = facetokenStr+faceTokens[faceTokens.size()-1];
    qDebug()<<"查看facetokemmstr"<<facetokenStr;
    face_tokens = setHttpPart(facetokenStr.toLatin1(),QVariant("form-data; name=\"face_tokens\""));
    multiPart->append(apikey);
    multiPart->append(apisecret);
    multiPart->append(faceset_token);
    multiPart->append(face_tokens);
    QUrl url("https://api-cn.faceplusplus.com/facepp/v3/faceset/addface");
    QNetworkRequest request(url);
    QNetworkReply *reply = manager->post(request,multiPart);
    multiPart->setParent(reply); // 用 reply 删除 multiPart
    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();
        qDebug()<<"httpCodes"<<statusCode;
        if (reply->error() != QNetworkReply::NoError) {
            this->isError=true;
            qDebug() << "In addFaceToken the error is "<<reply->error()<<reply->errorString();
            return ;
        }else {
            qDebug()<<reply->readAll();
        }
    }else { //超过8秒
        disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        reply->abort();
        reply->deleteLater();
        qDebug() << "联网超时";

    }
    if(reply->error()==QNetworkReply::NoError){
        qDebug()<<"测试加入facetoken"<<reply->readAll();
    }else{
        qDebug()<<"error in AddFaceToken "<<reply->errorString();
    }


}

void Face::compareFace(const QString &faceTk1, const QString &faceTk2)
{
    QTimer timer;
    timer.setInterval(8000);
    timer.setSingleShot(true);
    QNetworkAccessManager *manager = new QNetworkAccessManager;
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    QHttpPart apikey,apisecret,face1,face2;
    apikey = setHttpPart(this->apiKey.toLatin1(),QVariant("form-data; name=\"api_key\""));
    apisecret = setHttpPart(this->apiSecret.toLatin1(),QVariant("form-data; name=\"api_secret\""));
    face1 = imageHttpPart(faceTk1.toLatin1(),QVariant("form-data; name=\"image_base64_1\""));
    face2 = imageHttpPart(faceTk2.toLatin1(),QVariant("form-data; name=\"image_base64_2\""));
    multiPart->append(apikey);
    multiPart->append(apisecret);
    multiPart->append(face1);
    multiPart->append(face2);
    QUrl url("https://api-cn.faceplusplus.com/facepp/v3/compare");
    QNetworkRequest request(url);
    QNetworkReply *reply = manager->post(request,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();
        qDebug()<<"httpCodes"<<statusCode;
        if (reply->error() != QNetworkReply::NoError) {
            this->isError=true;
            qDebug() << "In compareFace the error is "<<reply->error()<<reply->errorString();
            return ;
        }else {
            isError= false;
            finishedSearch(reply);
        }
    }else { //超过8秒
        disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        reply->abort();
        reply->deleteLater();
        qDebug() << "联网超时";

    }

}

void Face::searchFace(const QString &image)
{
    QTimer timer;
    timer.setInterval(8000);
    timer.setSingleShot(true);
    QNetworkAccessManager *manager = new QNetworkAccessManager;
    connect(manager,&QNetworkAccessManager::finished,this,&Face::finishedSearch);
    QHttpMultiPart * multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    QHttpPart apikey,apisecret,targetImg,faceset;
    apikey = setHttpPart(this->apiKey.toLatin1(),QVariant("form-data; name=\"api_key\""));
    apisecret = setHttpPart(this->apiSecret.toLatin1(),QVariant("form-data'; name=\"api_secret\""));
    targetImg = setHttpPart(image.toLatin1(),QVariant("form-data; name=\"face_token\""));
    faceset = setHttpPart(this->faceset_token.toLatin1(),QVariant("form-data; name=\"faceset_token\""));
    multiPart->append(apikey);
    multiPart->append(apisecret);
    multiPart->append(targetImg);
    multiPart->append(faceset);
    QUrl url("https://api-cn.faceplusplus.com/facepp/v3/search");
    QNetworkRequest request(url);
    QNetworkReply *reply = manager->post(request,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();
        if (reply->error() != QNetworkReply::NoError) {
            this->isError=true;
            qDebug() << "In searchFace the error is "<<reply->error()<<reply->errorString();
            return ;
        }else {
            this->isError= false;
//            finishedSearch(reply);
        }
    }else { //超过8秒
        disconnect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
        reply->abort();
        reply->deleteLater();
        qDebug() << "联网超时";

    }

    
}
````void Face::finishedQ(QNetworkReply *reply)
{
    int error = reply->error();
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"httpCodes"<<statusCode;
    if(error==QNetworkReply::NoError && statusCode==200){
        QByteArray responseData = reply->readAll();
        QList<QString>faceTokens;
        faceTokens = getfaceToken(responseData);
        qDebug()<<"dajdadjadada"<<responseData<<"  "<<faceTokens;
        if(faceTokens.size()>0){
            addFaceTokens(faceTokens);
        }
        QMap<QString,QVariant>map;
        QJsonDocument documment ;
        map = documment.fromJson(responseData).toVariant().toMap();
        qDebug()<<"responese data:"<<responseData;
        float confidence = map.value("confidence").toFloat();
        qDebug()<<"the confidence is "<<confidence;
    }else{
        qDebug()<<"In finishedQ the error is "<<error<<reply->errorString();
    }
}

void Face::finishedDetect(QNetworkReply *reply)
{
    if(!isError){
        QByteArray responseData = reply->readAll();
        qDebug()<<"responseData"<<responseData;
        QList<QString>faceTokens;
        faceTokens = getfaceToken(responseData);
        if(faceTokens.size()>0){
            for(int i = 0;i<faceTokens.size();i++){
                qDebug()<<"in finishedDetect :"<<faceTokens[i];
                searchFace(faceTokens[i]);
                if(this->confidence>=80.000){
                    qDebug()<<"faceSet已有此人,不将此人脸入库";
                }else{
                    qDebug()<<"加入数据库,关联相关信息";
                }
            }
            addFaceTokens(faceTokens);
        }
    }

}

void Face::finishedSearch(QNetworkReply *reply)
{
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug()<<"httpCodes"<<statusCode;
    qDebug()<<"In finishedSearch :"<<reply->readAll();
    if(reply->error()==QNetworkReply::NoError && statusCode==200){
        QByteArray responseData = reply->readAll();
        QMap<QString,QVariant>map;
        QJsonDocument documment ;
        map = documment.fromJson(responseData).toVariant().toMap();
        double confidence = 0.0;
        QString face_token;
        QJsonArray results = map.value("results").toJsonArray();
        if(!results.isEmpty()){
            QJsonObject obj = results[0].toObject();
            confidence = obj.value("confidence").toDouble();
            face_token = obj.value("face_token").toString();
            qDebug()<<map.value("thresholds").toJsonArray()<<"\n"<<map.value("results").toJsonArray();
    }
        setMaxConfidence(face_token,confidence);
        qDebug()<<map.value("thresholds").toJsonArray()<<"\n"<<map.value("results").toJsonArray();
    }else{
        qDebug()<<"faceSearch error is "<<reply->errorString();
    }


}

欢迎大家 批评指教!~~~
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Daisy_JuJuJu

你们的鼓励将是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值