主要内容:
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();
}
}
该章节增加了两个类:worker 和 gameinfo
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丢出去
}