QT——百度EasyDL深度学习模型调用(人脸检测)

  • 前言:基于QT平台开发的一款人脸口罩检测系统,利用百度AI-EasyDL平台搭建深度学习模型并通过api调用。
准备工作
  • 1、登录百度AI-EasyDL平台,注册账号,按照帮助文档新建模型
  • 2、按照帮助文档建立数据集,并给数据集标注(这里可以直接上传未标注的数据集-图片,然后跟着说明一张一张图片标注)
  • 3、为模型添加数据集、训练模型、校验、发布。
  • 4、点击模型页“服务详情”->立即使用即可获取到API Key和Secret Key保存备用。

数据集:

模型页:
  • 5、布局更改:在上一篇文章布局的基础上添加两个按钮:“打开文件”与“发送请求”,布局在原先的基础上稍微修改一下,如下图所示:
  • 6、添加以上按钮的槽函数(这里不直接右击按钮转到槽函数,而是在代码里使用connect机制)与发送请求的接收数据函数:
  • 7、在构造函数中设置request按钮的文本和不可点击属性,在截图按钮的槽函数中打开request按钮的可点击属性并指定其槽函数
//设置request按钮的文本显示
    ui->request->setText("获取AccessToken");
    ui->request->setDisabled(true);
//设置request按钮的可点击属性
    ui->request->setEnabled(true);
    getAccessToken = connect(ui->request, SIGNAL(clicked()), this, SLOT(on_getAccessToken()));
获取AccessToken
  • 点击获取AccessToken按钮即可触发请求函数。请求函数主要内容是设置apiKey和secretKey的内容,然后按照api文档设置请求头,以及url,最后绑定该请求对应的接收函数即可。这里在使用net相关功能时,.pro文件里需要添加QT += network来支持net应用开发。
//获取AccessToken
void MainWindow::on_getAccessToken(){
    QString apiKey = "x7AfM65W69R5Z6fY8wVYvOct";//替换为个人的apiKey
    QString secretKey = "qw1eG**************AV6d7oNM";//替换为个人的secretKey
    QNetworkRequest request;
    request.setRawHeader("Content-Type", "application/json");
    request.setRawHeader("charset", "UTF-8");
    QUrl url("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + apiKey + "&client_secret=" + secretKey);
    request.setUrl(url);
    QByteArray data;

    get_accessToken =  new QNetworkAccessManager(this);
    connect(get_accessToken, SIGNAL(finished(QNetworkReply*)), this, SLOT(accessTokenResult(QNetworkReply*)));

    get_accessToken->post(request, data);
}
  • 返回结果接收函数主要是将接收到的结果进行json解析,获取其中的access_token值即可,如若收到的值没有错误,则进行修改request按钮的功能函数,修改显示文本、disconnect和重新connect。
//accessToken结果接收
void MainWindow::accessTokenResult(QNetworkReply* pReply){
    if(pReply->error() == QNetworkReply::NoError){
        QByteArray string = pReply->readAll();
        //获取内容
        QJsonParseError jsonErr;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(string, &jsonErr);
        if (jsonDoc.isObject()){
            QJsonObject jsonObj = jsonDoc.object();
            accessToken = jsonObj.take("access_token").toString();
            qDebug()<<"access_token:"+accessToken;

            //替换request按钮功能
            disconnect(getAccessToken);
            ui->request->setText("识别");
            connect(ui->request, SIGNAL(clicked()), this, SLOT(on_recognize()));
        }
    }
}
将获取到的图片转为Base64编码
  • 首先在.h文件里添加私有变量QString imageDatas、公有函数void imageToBase64(QImage image);然后在.cpp文件中具体实现。
void MainWindow::imageToBase64(QImage image){
    //image to base64
    QByteArray imageData;
    QBuffer buff(&imageData);
    image.save(&buff, "jpg");
    imageDatas = imageData.toBase64();
}
识别
  • 首先判断imageDatas和accessToken是否为空,然后再进行发送请求步骤,在发送请求时需要按照api文档要求的json形式发送(此处需要转换),接着绑定接收数据的函数。
//识别
void MainWindow::on_recognize(){
    if (imageDatas.isEmpty())
    {
        qDebug() << "image base64 empty";
        return;
    }
    if (accessToken.isEmpty())
    {
        qDebug() << "accessToken empty";
        return;
    }
    QUrl url;
    url.setUrl("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/classification/moxingkz?access_token="+accessToken);

    QNetworkRequest request;
    request.setUrl(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("Content-Type:application/json;charset=UTF-8"));

    QJsonObject post_data;;
    QJsonDocument document;
    post_data.insert("image", imageDatas);
    post_data.insert("image_type", "BASE64");
    document.setObject(post_data);
    QByteArray post_param = document.toJson(QJsonDocument::Compact);


    to_recoginze = new QNetworkAccessManager(this);
    connect(to_recoginze, SIGNAL(finished(QNetworkReply*)), this, SLOT(recognizeResult(QNetworkReply*)));
    to_recoginze->post(request, post_param);
}
  • 接收数据函数同样需要判断接收数据有没有包含错误,如果没有则按照json格式解析所需要的数据:yes与no的置信度,并打印。
//识别结果接收
void MainWindow::recognizeResult(QNetworkReply* pReply){
    QByteArray replaystring = pReply->readAll();
    qDebug()<<"reganizeResult()"+replaystring;
    QNetworkReply::NetworkError err = pReply->error();
    if(err != QNetworkReply::NoError) {
        qDebug() << "Failed: " << replaystring;
    }else {
        //获取内容
        QJsonParseError jsonErr;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(replaystring, &jsonErr);
        //qDebug()<<jsonDoc.object();
        double yesNum = 0, noNum = 0;
        if (jsonDoc.isObject()){
            QJsonObject jsonObj = jsonDoc.object();
            QJsonValue results = jsonObj.value("results");
            if (results.isArray()) {
                QJsonArray resultsArray = results.toArray();
                for (int i = 0; i < resultsArray.count(); i++) {
                      QJsonObject temp = resultsArray[i].toObject();
                      if(temp.take("name") == "yes")
                          yesNum = temp.take("score").toDouble();
                      else
                          noNum = temp.take("score").toDouble();
                }
            }
        }
        qDebug()<<yesNum;
        qDebug()<<noNum;
    }
}
  • 识别结果如下图:
打开图片进行识别
void MainWindow::on_openfile_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(
                    this, tr("open image file"),
                    "./", tr("Image files(*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm);;All files (*.*)"));
    if(fileName.isEmpty())
    {
        QMessageBox mesg;
        mesg.warning(this,"警告","打开图片失败!");
        return;
    }
    qDebug()<<fileName;
    QImage image(fileName);
    ui->imageview->setPixmap(QPixmap::fromImage(image));

    //设置request按钮的可点击属性
    ui->request->setEnabled(true);
    getAccessToken = connect(ui->request, SIGNAL(clicked()), this, SLOT(on_getAccessToken()));

    imageToBase64(image);
}
  • 识别结果如下:
按照惯例——上完整工程代码
  • 项目文件目录:
  • Camera.pro
QT       += core gui multimedia multimediawidgets
QT += network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

  • mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QCamera>
#include <QCameraViewfinder>
#include <QCameraImageCapture>
#include <QComboBox>
#include <QNetworkAccessManager>
#include <QNetworkReply>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void setfblComobox(QCamera *camera);
    void imageToBase64(QImage image);

private slots:
    void on_screenshot_clicked();

    void on_cameraType_activated(int index);

    void on_imageCaptured(int id, const QImage &preview);

    void on_fbl_activated(int index);

    void on_openfile_clicked();


    //获取AccessToken
    void on_getAccessToken();
    //识别
    void on_recognize();
    //accessToken结果接收
    void accessTokenResult(QNetworkReply* pReply);
    //识别结果接收
    void recognizeResult(QNetworkReply* pReply);


private:
    Ui::MainWindow *ui;
    QCamera *camera;
    QCameraViewfinder *viewfind;
    QList<QCameraInfo> cameras;
    QCameraImageCapture *imageCapture;
    QList<QSize> mResSize = {};//分辨率List 定义
    QComboBox *box;

    QMetaObject::Connection getAccessToken;

    QNetworkAccessManager *get_accessToken;
    QNetworkAccessManager *to_recoginze;
    QString accessToken, imageDatas;
};
#endif // MAINWINDOW_H

  • main.cpp
#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QCameraInfo>
#include <QJsonParseError>
#include <QJsonObject>
#include <QBuffer>
#include <QJsonArray>
#include <QFileDialog>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QComboBox *cameraType = new QComboBox();
    box = ui->fbl;
    cameraType = ui->cameraType;
    cameraType->clear();

    cameras = QCameraInfo::availableCameras();
    foreach(const QCameraInfo &cameraInfo, cameras) {
        //qDebug() << "CameraInfo:" << cameraInfo;
        cameraType->addItem(cameraInfo.description());
    }
    camera = new QCamera(this);
    viewfind = new QCameraViewfinder();
    viewfind->show();
    camera->setViewfinder(viewfind);
    imageCapture = new QCameraImageCapture(camera);
    camera->start();

    connect(imageCapture, SIGNAL(imageCaptured(int, QImage)), this, SLOT(on_imageCaptured(int, QImage)));
    setfblComobox(camera);
    //设置request按钮的文本显示
    ui->request->setText("获取AccessToken");
    ui->request->setDisabled(true);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_cameraType_activated(int index)
{
    index = ui->cameraType->currentIndex();
    qDebug()<<"Index"<< index <<": "<< ui->cameraType->currentText();
    camera->stop();
    camera = new QCamera(cameras[index]);
    camera->setCaptureMode(QCamera::CaptureVideo);
    camera->setViewfinder(viewfind);
    imageCapture = new QCameraImageCapture(camera);
    camera->start();
    connect(imageCapture, SIGNAL(imageCaptured(int, QImage)), this, SLOT(on_imageCaptured(int, QImage)));
    setfblComobox(camera);
}

void MainWindow::on_imageCaptured(int id, const QImage &preview){
    Q_UNUSED(id);
    int with = ui->imageview->width();
    int height = ui->imageview->height();
    QPixmap pixmap = QPixmap::fromImage(preview);
    //QPixmap fitpixmap = pixmap.scaled(with, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);  // 饱满填充
    QPixmap fitpixmap = pixmap.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 按比例缩放
    ui->imageview->setPixmap(fitpixmap);

    if(ui->request->text() != "识别"){
        //设置request按钮的可点击属性
        ui->request->setEnabled(true);
        getAccessToken = connect(ui->request, SIGNAL(clicked()), this, SLOT(on_getAccessToken()));
    }
    imageToBase64(preview);
}

void MainWindow::on_screenshot_clicked()
{
    qDebug()<<"ScreenShot";

    imageCapture->capture();
}

void MainWindow::on_fbl_activated(int index){
    index = ui->fbl->currentIndex();
    //qDebug()<<"Index"<< index <<": "<< ui->fbl->currentText();
    //qDebug()<<"mResSize:"<<mResSize[index];
    //设置摄像头参数
    QCameraViewfinderSettings set;
    set.setResolution(mResSize[index]);
    camera->setViewfinderSettings(set);
}

void MainWindow::setfblComobox(QCamera *camera){

    mResSize.clear();
    mResSize = camera->supportedViewfinderResolutions();
    box->clear();
    int i=0;
    foreach (QSize msize, mResSize) {
       //qDebug()<<msize;
       box->addItem(QString::number(msize.width(),10)+"*"+QString::number(msize.height(),10), i++);
    }  //摄像头支持分辨率打印
    box->setCurrentIndex(i-1);
}

void MainWindow::on_openfile_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(
                    this, tr("open image file"),
                    "./", tr("Image files(*.bmp *.jpg *.pbm *.pgm *.png *.ppm *.xbm *.xpm);;All files (*.*)"));
    if(fileName.isEmpty())
    {
        QMessageBox mesg;
        mesg.warning(this,"警告","打开图片失败!");
        return;
    }
    qDebug()<<fileName;
    QImage image(fileName);

    //等比缩放显示图片
    int with = ui->imageview->width();
    int height = ui->imageview->height();
    QPixmap pixmap = QPixmap::fromImage(image);
    //QPixmap fitpixmap = pixmap.scaled(with, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);  // 饱满填充
    QPixmap fitpixmap = pixmap.scaled(with, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);  // 按比例缩放
    ui->imageview->setPixmap(fitpixmap);

    //设置request按钮的可点击属性
    ui->request->setEnabled(true);
    getAccessToken = connect(ui->request, SIGNAL(clicked()), this, SLOT(on_getAccessToken()));

    imageToBase64(image);
}


//获取AccessToken
void MainWindow::on_getAccessToken(){
    QString apiKey = "x7AfM65W69R5Z6fY8wVYvOct";//替换为个人的apiKey
    QString secretKey = "qw1eG**************AV6d7oNM";//替换为个人的secretKey
    QNetworkRequest request;
    request.setRawHeader("Content-Type", "application/json");
    request.setRawHeader("charset", "UTF-8");
    QUrl url("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + apiKey + "&client_secret=" + secretKey);
    request.setUrl(url);
    QByteArray data;

    get_accessToken =  new QNetworkAccessManager(this);
    connect(get_accessToken, SIGNAL(finished(QNetworkReply*)), this, SLOT(accessTokenResult(QNetworkReply*)));

    get_accessToken->post(request, data);
}
//识别
void MainWindow::on_recognize(){
    if (imageDatas.isEmpty())
    {
        qDebug() << "image base64 empty";
        return;
    }
    if (accessToken.isEmpty())
    {
        qDebug() << "accessToken empty";
        return;
    }
    QUrl url;
    url.setUrl("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/classification/moxingkz?access_token="+accessToken);

    QNetworkRequest request;
    request.setUrl(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("Content-Type:application/json;charset=UTF-8"));

    QJsonObject post_data;;
    QJsonDocument document;
    post_data.insert("image", imageDatas);
    post_data.insert("image_type", "BASE64");
    document.setObject(post_data);
    QByteArray post_param = document.toJson(QJsonDocument::Compact);


    to_recoginze = new QNetworkAccessManager(this);
    connect(to_recoginze, SIGNAL(finished(QNetworkReply*)), this, SLOT(recognizeResult(QNetworkReply*)));
    to_recoginze->post(request, post_param);
}

//accessToken结果接收
void MainWindow::accessTokenResult(QNetworkReply* pReply){
    if(pReply->error() == QNetworkReply::NoError){
        QByteArray string = pReply->readAll();
        //获取内容
        QJsonParseError jsonErr;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(string, &jsonErr);
        if (jsonDoc.isObject()){
            QJsonObject jsonObj = jsonDoc.object();
            accessToken = jsonObj.take("access_token").toString();
            qDebug()<<"access_token:"+accessToken;

            //替换request按钮功能
            disconnect(getAccessToken);
            ui->request->setText("识别");
            connect(ui->request, SIGNAL(clicked()), this, SLOT(on_recognize()));
        }
    }
}
//识别结果接收
void MainWindow::recognizeResult(QNetworkReply* pReply){
    QByteArray replaystring = pReply->readAll();
    qDebug()<<"reganizeResult()"+replaystring;
    QNetworkReply::NetworkError err = pReply->error();
    if(err != QNetworkReply::NoError) {
        qDebug() << "Failed: " << replaystring;
    }else {
        //获取内容
        QJsonParseError jsonErr;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(replaystring, &jsonErr);
        //qDebug()<<jsonDoc.object();
        double yesNum = 0, noNum = 0;
        if (jsonDoc.isObject()){
            QJsonObject jsonObj = jsonDoc.object();
            QJsonValue results = jsonObj.value("results");
            if (results.isArray()) {
                QJsonArray resultsArray = results.toArray();
                for (int i = 0; i < resultsArray.count(); i++) {
                      QJsonObject temp = resultsArray[i].toObject();
                      if(temp.take("name") == "yes")
                          yesNum = temp.take("score").toDouble();
                      else
                          noNum = temp.take("score").toDouble();
                }
            }
        }
        qDebug()<<yesNum;
        qDebug()<<noNum;
    }
}

void MainWindow::imageToBase64(QImage image){
    //image to base64
    QByteArray imageData;
    QBuffer buff(&imageData);
    image.save(&buff, "jpg");
    imageDatas = imageData.toBase64();
}

  • mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>824</width>
    <height>549</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <property name="font">
    <font>
     <pointsize>7</pointsize>
    </font>
   </property>
   <layout class="QHBoxLayout" stretch="4,2">
    <property name="sizeConstraint">
     <enum>QLayout::SetDefaultConstraint</enum>
    </property>
    <item>
     <widget class="QWidget" name="widget" native="true">
      <layout class="QVBoxLayout" name="verticalLayout">
       <item>
        <widget class="QLabel" name="imageview">
         <property name="maximumSize">
          <size>
           <width>680</width>
           <height>400</height>
          </size>
         </property>
         <property name="text">
          <string/>
         </property>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
    <item>
     <widget class="QWidget" name="widget_2" native="true">
      <widget class="QWidget" name="widget_3" native="true">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>100</y>
         <width>261</width>
         <height>161</height>
        </rect>
       </property>
       <widget class="QLabel" name="label_2">
        <property name="geometry">
         <rect>
          <x>0</x>
          <y>40</y>
          <width>61</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <pointsize>12</pointsize>
         </font>
        </property>
        <property name="text">
         <string>摄像头</string>
        </property>
       </widget>
       <widget class="QComboBox" name="cameraType">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>50</y>
          <width>181</width>
          <height>23</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <pointsize>10</pointsize>
         </font>
        </property>
       </widget>
       <widget class="QLabel" name="label_3">
        <property name="geometry">
         <rect>
          <x>0</x>
          <y>110</y>
          <width>71</width>
          <height>31</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <pointsize>12</pointsize>
         </font>
        </property>
        <property name="text">
         <string>分辨率</string>
        </property>
       </widget>
       <widget class="QComboBox" name="fbl">
        <property name="geometry">
         <rect>
          <x>70</x>
          <y>110</y>
          <width>181</width>
          <height>23</height>
         </rect>
        </property>
        <property name="font">
         <font>
          <pointsize>10</pointsize>
         </font>
        </property>
       </widget>
      </widget>
      <widget class="QWidget" name="widget_4" native="true">
       <property name="geometry">
        <rect>
         <x>0</x>
         <y>320</y>
         <width>261</width>
         <height>181</height>
        </rect>
       </property>
       <layout class="QVBoxLayout" name="verticalLayout_2">
        <item>
         <widget class="QPushButton" name="screenshot">
          <property name="text">
           <string>截图</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QPushButton" name="openfile">
          <property name="text">
           <string>打开图片</string>
          </property>
         </widget>
        </item>
        <item>
         <widget class="QPushButton" name="request">
          <property name="text">
           <string>识别</string>
          </property>
         </widget>
        </item>
       </layout>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

  • 以上代码个人通过多方渠道搜集学习得来,不免有些问题,如有问题请留言交流~
  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值