人脸识别与信息抓取

第三章 人脸识别与信息抓取

1、主要内容:
在人脸识别基础上加一个矩形框,以及兔耳朵。

2、前期准备
需要前期准备一张兔子耳朵头像挂件图片(背景透明那种,没有就抠图),然后放在工程目录下,最好是新建一个专门放图片的文件夹img,把图片放入img文件夹中。
3、插入兔耳朵图片
新建文件,如下图,然后命名为tuer.png。
QT插入图片
在这里插入图片描述
在这里插入图片描述
前缀太长了,可以删一部分,只留一个根目录/,然后点击Add Files,找到图片添加进来。
qt0402.cpp源代码

#include "qt0402.h"
#include "ui_qt0402.h"
qt0402::qt0402(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::qt0402)
    , faceInfo()
{
    ui->setupUi(this);
    faceInfo.setIsable(false);

    //显示了所有摄像头信息
    const QList<QCameraInfo> cameraInfoList = QCameraInfo::availableCameras();
    for (const QCameraInfo &tmpCam:cameraInfoList) {
        qDebug() << tmpCam.deviceName()<< "|||" << tmpCam.description();
        ui->comboBox->addItem(tmpCam.description());

    }
    connect(ui->comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
        [=](int index){
        qDebug() << cameraInfoList.at(index).description();
        refreshTimer->stop();
        camera->stop();
        camera->deleteLater();
        camera = new QCamera(cameraInfoList.at(index));
        imageCapture->deleteLater();
        imageCapture = new QCameraImageCapture(camera);
        camera->setViewfinder(finder);
        camera ->setCaptureMode(QCamera::CaptureStillImage);
        imageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);
        connect(imageCapture, &QCameraImageCapture::imageCaptured,
                this, &qt0402::showPic);
        camera->start();
        refreshTimer->start(40);
    });

    //摄像头配置
    camera = new QCamera(cameraInfoList.at(0));
    finder = new QCameraViewfinder();
    imageCapture = new QCameraImageCapture(camera);
    camera->setViewfinder(finder);
    camera ->setCaptureMode(QCamera::CaptureStillImage);
    imageCapture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer);

    //拍照与按钮绑定
    connect(imageCapture, &QCameraImageCapture::imageCaptured,
            this, &qt0402::showPic);

    camera->start();

    //定时器刷新拍照
    refreshTimer = new QTimer(this);
    connect(refreshTimer, &QTimer::timeout,
            this, [=](){
       imageCapture->capture();
    });
    //开Timer
    refreshTimer->start(40);

    //设置布局
    QVBoxLayout *vboxl = new QVBoxLayout;
    vboxl->addWidget(ui->label);
    vboxl->addWidget(ui->pushButton);
    //竖直盒子
    QVBoxLayout *vboxr = new QVBoxLayout;
    vboxr->addWidget(ui->comboBox);
    vboxr->addWidget(finder);
    vboxr->addWidget(ui->textBrowser);

    //水平盒子
    QHBoxLayout *hbox = new QHBoxLayout;
    hbox->addLayout(vboxl);
    hbox->addLayout(vboxr);

    //最终以水平布局为准hbox
    this->setLayout(hbox);

    imgManager = new QNetworkAccessManager(this);
    connect(imgManager, &QNetworkAccessManager::finished,
            this, [&](QNetworkReply *replay){
            if (replay->error() != QNetworkReply::NoError) {
                qDebug() << replay->errorString();
                return ;
            }
            QByteArray replayData =  replay->readAll();
            qDebug() << replayData;

            QJsonParseError jsonErr;
            //字节数组转成json文档
            QJsonDocument doc = QJsonDocument::fromJson(replayData, &jsonErr);
            if (jsonErr.error != QJsonParseError::NoError) {
                qDebug() << "json parse error" << jsonErr.errorString();
                return ;
            }
            QJsonObject obj = doc.object();

            //QJsonObject resultObj = obj.value("result").toObject();

            //if (!resultObj.contains("face_num")) return ;

            if (!obj.contains("result"))  return ;
            QJsonObject resultObj = obj.value("result").toObject();

            //人脸数目必须大于1
            if (!resultObj.contains("face_num")) return ;
            if (resultObj.value("face_num").toInt() < 1) return ; //人脸数<1直接返回

            if (!resultObj.contains("face_list")) return ;
            QJsonArray faceList = resultObj.value("face_list").toArray();

            //人脸位置信息在location里面
            QJsonObject faceInfoObj = faceList[0].toObject();
            if (!faceInfoObj.contains("location")) return ;
            QJsonObject locationObj = faceInfoObj.value("location").toObject();

            //获得四个位置信息
            if (!locationObj.contains("left")) return ;
            faceInfo.setLeft(locationObj.value("left").toDouble());
            if (!locationObj.contains("top")) return ;
            faceInfo.setTop(locationObj.value("top").toDouble());
            if (!locationObj.contains("width")) return ;
            faceInfo.setWidth(locationObj.value("width").toDouble());
            if (!locationObj.contains("height")) return ;
            faceInfo.setHeight(locationObj.value("height").toDouble());

            qDebug() << faceInfo.getLeft();
            qDebug() << faceInfo.getTop();
            qDebug() << faceInfo.getWidth();
            qDebug() << faceInfo.getHeight();

            if (!faceInfoObj.contains("age")) return ;
            this->faceInfo.setAge(faceInfoObj.value("age").toInt());

            //人脸信息获取
            QJsonObject tmpObj;

            if (!faceInfoObj.contains("face_shape")) return ;
            tmpObj = faceInfoObj.value("face_shape").toObject();
            if (!tmpObj.contains("type")) return ;
            this->faceInfo.setFace_shape(tmpObj.value("type").toString());

            if (!faceInfoObj.contains("gender")) return ;
            tmpObj = faceInfoObj.value("gender").toObject();
            if (!tmpObj.contains("type")) return ;
            this->faceInfo.setGender(tmpObj.value("type").toString());

            if (!faceInfoObj.contains("glasses")) return ;
            tmpObj = faceInfoObj.value("glasses").toObject();
            if (!tmpObj.contains("type")) return ;
            this->faceInfo.setGlasses(tmpObj.value("type").toString());

            if (!faceInfoObj.contains("emotion")) return ;
            tmpObj = faceInfoObj.value("emotion").toObject();
            if (!tmpObj.contains("type")) return ;
            this->faceInfo.setEmotion(tmpObj.value("type").toString());

            if (!faceInfoObj.contains("face_type")) return ;
            tmpObj = faceInfoObj.value("face_type").toObject();
            if (!tmpObj.contains("type")) return ;
            this->faceInfo.setFace_type(tmpObj.value("type").toString());
            
            if (!faceInfoObj.contains("mask")) return ;
            tmpObj = faceInfoObj.value("mask").toObject();
            if (!tmpObj.contains("type")) return ;
            this->faceInfo.setMask(tmpObj.value("type").toInt());

            if (!faceInfoObj.contains("beauty")) return ;
            this->faceInfo.setBeauty(faceInfoObj.value("beauty").toDouble());

            faceInfo.setIsable(true);
            //需要展示的内容,字符串展示append();
            QString faceStr;
            //年龄是int,需要转成string
            faceStr.append("年龄:").append(QString::number(faceInfo.getAge())).append("\n");
            faceStr.append("性别:").append(faceInfo.getGender()).append("\n");
            faceStr.append("戴眼镜:").append(faceInfo.getGlasses()).append("\n");
            faceStr.append("情绪:").append(faceInfo.getEmotion()).append("\n");
            faceStr.append("脸型:").append(faceInfo.getFace_shape()).append("\n");
            faceStr.append("戴口罩:").append(faceInfo.getMask()==1?"了戴":"没戴").append("\n");
            faceStr.append("颜值:").append(QString::number(faceInfo.getBeauty())).append("\n");

            ui->textBrowser->setText(faceStr);
    });

    //设置按钮点击操作
    //[](){}这是lamda函数,也就是槽的定义,[]里=或者&都可以
    connect(ui->pushButton, &QPushButton::clicked,
            this, [&]() {
        //进行人脸检测

        //QThread;
        //qDebug() << 1;
        //进行图片转码,把图片转成base64编码,百度AI

        QByteArray ba;
        QBuffer buff(&ba);
        faceImg.save(&buff, "png");
        //1和2之间卡
        //qDebug() << 2;
        QString b64str = ba.toBase64();
        //qDebug() << b64str;  //特长一串
        //imageCapture->capture();
        //组装请求体
        QJsonObject postJson;
        postJson.insert("image", b64str);
        postJson.insert("image_type", "BASE64");
        postJson.insert("face_field", "age,face_shape,gender,glasses,emotion,face_type,mask,beauty");

        QJsonDocument doc;
        doc.setObject(postJson);
        QByteArray postData =  doc.toJson(QJsonDocument::Compact);   //一行字符串,没有换行

        //组装请求包
        QUrl url("https://aip.baidubce.com/rest/2.0/face/v3/detect");
        QUrlQuery query;
        query.addQueryItem("access_token", accessToken);
        url.setQuery(query);
        QNetworkRequest req;
        req.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
        req.setUrl(url);
        req.setSslConfiguration(sslConfig);
        imgManager->post(req, postData);
    });
    //支持https协议
    tokenManager = new QNetworkAccessManager(this);
    qDebug() << tokenManager->supportedSchemes();

    if (QSslSocket::supportsSsl()) {
        qDebug() << "supporte ssl";
    } else {
        qDebug() << "not support ssl";
    }

    //发起token请求
    QUrl url("https://aip.baidubce.com/oauth/2.0/token");
    QUrlQuery query;   //QUrlQuery提供了一个操纵键值对的方式,;
    query.addQueryItem("grant_type", "client_credentials");     //通过addQueryItem添加 key 和 value
    query.addQueryItem("client_id", "MEEgXrGBVMFeL8NoErsSxaZi");
    query.addQueryItem("client_secret", "cNNHbQiqMWSUBHKI3CoofDO8tXyMW6GN");
    url.setQuery(query);
    qDebug() << url;

    //配置SSL
    sslConfig = QSslConfiguration::defaultConfiguration();  //通过defaultConfiguration()获取ssl的默认配置
    sslConfig.setPeerVerifyMode(QSslSocket::QueryPeer);
    sslConfig.setProtocol(QSsl::TlsV1_2);

    //配置token请求
    QNetworkRequest req;
    req.setUrl(url);
    req.setSslConfiguration(sslConfig);
    tokenManager = new QNetworkAccessManager(this);
    connect(tokenManager, &QNetworkAccessManager::finished,
            this, [=](QNetworkReply *replay){
            //处理应答
            if (replay->error() != QNetworkReply::NoError) {
                qDebug() << replay->errorString();
                return ;
            }
            QByteArray replayData =  replay->readAll();
            //qDebug() << replayData;
            QJsonParseError jsonErr;
            //字节数组转成json文档
            QJsonDocument doc = QJsonDocument::fromJson(replayData, &jsonErr);
            if (jsonErr.error != QJsonParseError::NoError) {
                qDebug() << "json parse error" << jsonErr.errorString();
                return ;
            }
            QJsonObject obj = doc.object();
            if (!obj.contains("access_token")) {
                qDebug() << "no key:" << "access_token";
                return ;
            }
            accessToken = obj.value("access_token").toString();
            ui->textBrowser->setText(accessToken);
    });
    //发送请求
    tokenManager->get(req);
}
qt0402::~qt0402()
{
    delete ui;
}
void qt0402::takePicture(){
    imageCapture->capture();
}
void qt0402::showPic(int id, const QImage &preview){
    Q_UNUSED(id);
    faceImg = preview;
    if (faceInfo.getIsable()) {
        //在头像画个框
        QPainter p(&faceImg); //指定在preview画
        p.setPen(Qt::red);
        p.drawRect(faceInfo.getLeft(),
                   faceInfo.getTop(),
                   faceInfo.getWidth(),
                   faceInfo.getHeight());
        //tuer.png 396*272
        p.drawPixmap(
                    faceInfo.getLeft()+faceInfo.getWidth()/2-396/3,
                    faceInfo.getTop()-350,
                    396,272,
                    QPixmap(":/img/tuer.png"),
                    0,0,0,0);
    }
    ui->label->setPixmap(QPixmap::fromImage(faceImg)); //图形转换
}

faceinfo.h源代码

#ifndef FACEINFO_H
#define FACEINFO_H
#include <QString>

class faceinfo
{
private:
    bool isable;
    int mask;
    int age;

    double left;
    double top;
    double height;
    double width;
    double beauty;

    QString  face_shape;
    QString  gender;
    QString  glasses;
    QString  emotion;
    QString  face_type;


public:
    faceinfo();
    int getMask() const;
    void setMask(int newMask);
    int getAge() const;
    void setAge(int newAge);
    double getLeft() const;
    void setLeft(double newLeft);
    double getTop() const;
    void setTop(double newTop);
    double getHeight() const;
    void setHeight(double newHeight);
    double getWidth() const;
    void setWidth(double newWidth);
    double getBeauty() const;
    void setBeauty(double newBeauty);
    const QString &getFace_shape() const;
    void setFace_shape(const QString &newFace_shape);
    const QString &getGender() const;
    void setGender(const QString &newGender);
    const QString &getGlasses() const;
    void setGlasses(const QString &newGlasses);
    const QString &getEmotion() const;
    void setEmotion(const QString &newEmotion);
    const QString &getFace_type() const;
    void setFace_type(const QString &newFace_type);
    bool getIsable() const;
    void setIsable(bool newIsable);
};

#endif // FACEINFO_H

在faceinfo.h文件中,在private下定义各个参数,如下

int age;
double beauty;
QString  face_shape;

理论上来说同类型的参数放在一起,小的(int)放在前面,节省空间,提升效率。

构建类的set 、get方法,右键reactor,选择第二个,然后勾选前两个getter和setter,就自动把所有参数都选上了。

在faceinfo.cpp中就生成了代码,并且头文件和函数声明都定义好了,节省了时间。

qt0402.h源代码

#ifndef QT0402_H
#define QT0402_H

#include <QWidget>
#include <QNetworkReply>
#include <QWidget>
#include <QDebug>
#include <QString>
#include <QCamera>
#include <QCameraInfo>
#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QUrlQuery>
#include <QSslConfiguration>
#include <QSslSocket>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QBuffer>
#include <QJsonValue>
#include <QJsonArray>
#include <faceinfo.h>
#include <QPainter>
#include <QThread>

//1、当前路径找头文件<>,最快的
//2、gcc xxx -I xxx自定义头文件路径
//3、系统设置的(头文件)路径

QT_BEGIN_NAMESPACE
namespace Ui { class qt0402; }
QT_END_NAMESPACE

class qt0402 : public QWidget
{
    Q_OBJECT

public:
    qt0402(QWidget *parent = nullptr);
    ~qt0402();
    void showPic(int id, const QImage &preview);
private:
    Ui::qt0402 *ui;
    QCamera *camera;
    QCameraViewfinder *finder;
    QCameraImageCapture *imageCapture;
    QTimer *refreshTimer;

    void takePicture();
    QSslConfiguration sslConfig;
    QNetworkAccessManager *tokenManager;
    QNetworkAccessManager *imgManager;
    QString accessToken;
    QImage faceImg;
    faceinfo faceInfo;
};
#endif // QT0402_H

附上兔子耳朵图片
兔耳朵(透明背景)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值