QT+百度AI 手势识别

第四章 手势识别

主要内容:
1、采用子线程解决点拍照瞬间卡顿的问题;
2、百度AI手势识别;
3、人机猜拳游戏。
注意:
百度AI手势识别是可以免费领取的,前10000次免费,超出就要收费了,但也完全够用了。重要的事情说三遍:不需要付费,不需要付费,不需要付费,差点几百大洋又没了。
上代码:
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);
    timeCnt = 3;

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

    }
    connect(ui->comboBox, QOverload::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, &qt0402::takePicture);
    //开Timer
    refreshTimer->start(40);

    gameTimer = new QTimer(this);
    connect(gameTimer, &QTimer::timeout,
            this, &qt0402::timeJudge);
    //开Timer


//    detectTimer = new QTimer(this);
//    connect(detectTimer, &QTimer::timeout,
//            this, xxx);
//    detectTimer->start(1500);
    //设置布局
    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();
            if (!obj.contains("result")) return ;
            QJsonArray resultArray = obj.value("result").toArray();

            QString tmp;
            humanHand = -1; //可能都没识别出来,为了安全起见
            for (int i = 0; i < resultArray.size(); i++) {
                if (!resultArray[i].toObject().contains("classname"))  return ;
                tmp = resultArray[i].toObject().value("classname").toString();
                //lastStr.append(tmp).append("\n");
                if (tmp == "Fist") {
                    humanHand = 0;
                    break;
                } else if(tmp == "Two") {
                    humanHand = 1;
                    break;
                } else if(tmp == "Five"){
                    humanHand = 2;
                    break;
                }
            }
            QString tmpStr;
            if(humanHand < 0){
                tmpStr = "识别失败,请重试!";
            } else {
                int res = (humanHand - computerHand + 3) % 3;
                switch(res) {
                case 0:
                    tmpStr = "平局";
                    break;
                case 1:
                    tmpStr = "你输了,你是个loser!";
                    break;
                case 2:
                    tmpStr = "你赢了,你是个winner!";
                    break;
                }
            }
            ui->textBrowser->setText(tmpStr);

//            //人脸数目必须大于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("mask")) return ;
//            tmpObj = faceInfoObj.value("mask").toObject();
//            if (!tmpObj.contains("type")) return ;
//            this->faceInfo.setMask(tmpObj.value("type").toInt());

//            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("beauty")) return ;
//            this->faceInfo.setBeauty(faceInfoObj.value("beauty").toDouble() + 50);//手动美颜

//            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, &qt0402::beginGame);
    //支持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)); //图形转换
}

void qt0402::handleResults(QByteArray postData, QThread *thisThread){
    //此时子线程可以去死了
    thisThread->quit();
    thisThread->wait();
    if (thisThread->isFinished()) {
        qDebug() << "子线程结束";
    } else {
        qDebug() << "子线程没结束";
    }
    //detectFace();

    //组装请求包
    //QUrl url("https://aip.baidubce.com/rest/2.0/face/v3/detect"); //人脸识别
    QUrl url("https://aip.baidubce.com/rest/2.0/image-classify/v1/gesture"); //手势识别
    QUrlQuery query;
    query.addQueryItem("access_token", accessToken);
    url.setQuery(query);

    QNetworkRequest req;
    req.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));//人脸识别是application/json
    req.setUrl(url);
    req.setSslConfiguration(sslConfig);

    imgManager->post(req, postData);
}
void qt0402::detectFace() {
    //进行人脸检测
    childThread = new QThread(this);
    //新建一个类worker,继承自QObject
    Worker *worker = new Worker; //这个worker只能是孤儿,不能又父母,但可以有孩子
    worker->moveToThread(childThread);
    connect(this, &qt0402::beginWork, worker, &Worker::doWork);
    connect(worker, &Worker::resultReady, this, &qt0402::handleResults);
    connect(childThread, &QThread::finished, worker, &QObject::deleteLater);
    childThread->start();
    //先启动再发送
    emit beginWork(faceImg, childThread);
    //qDebug() << 1;
}
void qt0402::beginGame(){
    QString showStr = "准备出拳: "+QString::number(timeCnt);
    ui->textBrowser->setText(showStr);
    gameTimer->start(1000); //1000ms开启一次
}

void qt0402::timeJudge(){
    if (--timeCnt > 0) {
        QString showStr = "准备出拳: "+QString::number(timeCnt);
        ui->textBrowser->setText(showStr);
        return;
    } else {
        //电脑出拳:0石头、1剪刀、2布
        computerHand = QRandomGenerator::global()->generate()%3;
        QString tmpHand;
        switch (computerHand) {
            case 0:
                tmpHand = "石头";
                break;
            case 1:
                tmpHand = "剪刀";
                break;
            case 2:
                tmpHand = "布";
                break;
        }
        gameTimer->stop();
        timeCnt = 3;
        QString showStr = "出拳!电脑出了:" +tmpHand
                +"你出了:...正在分析";
        ui->textBrowser->setText(showStr);
        detectFace();
    }
}

该章节增加了两个类:workergameinfo
faceinfo.h源代码

#include "qt0402.h"
#include "ui_qt0402.h"


qt0402::qt0402(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::qt0402)
    , faceInfo()
{
    ui->setupUi(this);
    faceInfo.setIsable(false);
    timeCnt = 3;

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

    }
    connect(ui->comboBox, QOverload::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, &qt0402::takePicture);
    //开Timer
    refreshTimer->start(40);

    gameTimer = new QTimer(this);
    connect(gameTimer, &QTimer::timeout,
            this, &qt0402::timeJudge);
    //开Timer


//    detectTimer = new QTimer(this);
//    connect(detectTimer, &QTimer::timeout,
//            this, xxx);
//    detectTimer->start(1500);
    //设置布局
    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();
            if (!obj.contains("result")) return ;

            QJsonArray resultArray = obj.value("result").toArray();

            QString tmp;
            humanHand = -1; //可能都没识别出来,为了安全起见
            for (int i = 0; i < resultArray.size(); i++) {
                if (!resultArray[i].toObject().contains("classname"))  return ;
                tmp = resultArray[i].toObject().value("classname").toString();
                //lastStr.append(tmp).append("\n");
                if (tmp == "Fist") {
                    humanHand = 0;
                    break;
                } else if(tmp == "Two") {
                    humanHand = 1;
                    break;
                } else if(tmp == "Five"){
                    humanHand = 2;
                    break;
                }
            }

            QString tmpStr;
            if(humanHand < 0){
                tmpStr = "识别失败,请重试!";
            } else {
                int res = (humanHand - computerHand + 3) % 3;
                switch(res) {
                case 0:
                    tmpStr = "平局";
                    break;
                case 1:
                    tmpStr = "你输了,你是个loser!";
                    break;
                case 2:
                    tmpStr = "你赢了,你是个winner!";
                    break;
                }
            }
            ui->textBrowser->setText(tmpStr);

//            //人脸数目必须大于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("mask")) return ;
//            tmpObj = faceInfoObj.value("mask").toObject();
//            if (!tmpObj.contains("type")) return ;
//            this->faceInfo.setMask(tmpObj.value("type").toInt());

//            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("beauty")) return ;
//            this->faceInfo.setBeauty(faceInfoObj.value("beauty").toDouble() + 50);//手动美颜

//            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, &qt0402::beginGame);

    //支持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)); //图形转换
}
void qt0402::handleResults(QByteArray postData, QThread *thisThread){
    //此时子线程可以去死了
    thisThread->quit();
    thisThread->wait();
    if (thisThread->isFinished()) {
        qDebug() << "子线程结束";
    } else {
        qDebug() << "子线程没结束";
    }
    //detectFace();
    //组装请求包
    //QUrl url("https://aip.baidubce.com/rest/2.0/face/v3/detect"); //人脸识别
    QUrl url("https://aip.baidubce.com/rest/2.0/image-classify/v1/gesture"); //手势识别
    QUrlQuery query;
    query.addQueryItem("access_token", accessToken);
    url.setQuery(query);
    QNetworkRequest req;
    req.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));//人脸识别是application/json
    req.setUrl(url);
    req.setSslConfiguration(sslConfig);
    imgManager->post(req, postData);
}
void qt0402::detectFace() {
    //进行人脸检测
    childThread = new QThread(this);
    //新建一个类worker,继承自QObject

    Worker *worker = new Worker; //这个worker只能是孤儿,不能又父母,但可以有孩子
    worker->moveToThread(childThread);
    connect(this, &qt0402::beginWork, worker, &Worker::doWork);
    connect(worker, &Worker::resultReady, this, &qt0402::handleResults);
    connect(childThread, &QThread::finished, worker, &QObject::deleteLater);
    childThread->start();
    //先启动再发送
    emit beginWork(faceImg, childThread);
    //qDebug() << 1;
}
void qt0402::beginGame(){
    QString showStr = "准备出拳: "+QString::number(timeCnt);
    ui->textBrowser->setText(showStr);
    gameTimer->start(1000); //1000ms开启一次
}
void qt0402::timeJudge(){
    if (--timeCnt > 0) {
        QString showStr = "准备出拳: "+QString::number(timeCnt);
        ui->textBrowser->setText(showStr);
        return;
    } else {
        //电脑出拳:0石头、1剪刀、2布
        computerHand = QRandomGenerator::global()->generate()%3;
        QString tmpHand;
        switch (computerHand) {
            case 0:
                tmpHand = "石头";
                break;
            case 1:
                tmpHand = "剪刀";
                break;
            case 2:
                tmpHand = "布";
                break;
        }
        gameTimer->stop();
        timeCnt = 3;
        QString showStr = "出拳!电脑出了:" +tmpHand
                +"你出了:...正在分析";
        ui->textBrowser->setText(showStr);
        detectFace();
    }
}

gameinfo.h源代码:

#ifndef GAMEINFO_H
#define GAMEINFO_H
class GameInfo
{
private:
    int timeCnt;

public:
    GameInfo();
};
#endif // GAMEINFO_H

qt0402.h源代码

#ifndef QT0402_H
#define QT0402_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "worker.h"

//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);
public slots:
    void handleResults(QByteArray postData, QThread *thisThread);
    void detectFace();
    void beginGame();
    void timeJudge(); //猜拳时间判断
private:
    Ui::qt0402 *ui;
    QCamera *camera;
    QCameraViewfinder *finder;
    QCameraImageCapture *imageCapture;
    QTimer *refreshTimer;
    QTimer *detectTimer;
    QTimer *gameTimer;
    void takePicture();
    QSslConfiguration sslConfig;
    QNetworkAccessManager *tokenManager;
    QNetworkAccessManager *imgManager;
    QString accessToken;
    QImage faceImg;
    faceinfo faceInfo;
    QThread *childThread;

    int timeCnt;
    int computerHand;
    int humanHand;

signals:
    void beginWork(QImage faceImg, QThread *thisThread);
};
#endif // QT0402_H

worker.h源代码

#ifndef WORKER_H
#define WORKER_H
#include 
#include 
#include 
#include 
#include 
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr);
public slots:
    void doWork(QImage faceImg, QThread *thisThread);

signals:
    void resultReady(QByteArray postData, QThread *thisThread);

};
#endif // WORKER_H

gameinfo.cpp不需要任何添加

worker.cpp源代码

#include "worker.h"
Worker::Worker(QObject *parent)
    : QObject{parent}
{
}
//信号不用定义,只定义槽就行
void Worker::doWork(QImage faceImg, QThread *thisThread){
    //进行图片转码,把图片转成base64编码,百度AI
    QByteArray ba;
    QBuffer buff(&ba);
    faceImg.save(&buff, "png"); //只能作为参数传进来
    //1和2之间卡
    //qDebug() << 2;
    //QString b64str = ba.toBase64();//人脸识别
    QString b64str = ba.toBase64().toPercentEncoding();//收拾识别需要转成
    //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("image=");   //一行字符串,没有换行
    postData.append(b64str);
    emit resultReady(postData, thisThread); //工人活干完了发信号,把信号postData丢出去
}

以上就是所有的源代码了
QT+百度AI 手势识别_第1张图片
然后就可以愉快的跟电脑玩猜拳游戏了。

你可能感兴趣的:(QT,人工智能,qt)