Qt实用技巧:测试80*1080p拼接后显示刷新帧率

简介: Qt实用技巧:测试80*1080p拼接后显示刷新帧率

若该文为原创文章,未经允许不得转载

原博主博客地址:https://blog.csdn.net/qq21497936

原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062

本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79557290

各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)

Qt开发专栏:实用技巧(点击传送门)

 

需求

       服务器拼接,测试图像16个,需要不断切换(图像已在内存中),仅测试超大拼接区域的刷新帧率。

 

Demo

       下载地址:https://download.csdn.net/download/qq21497936/10286699

 

ReadMe

 

效果

可以看到,当图片覆盖屏幕(1080p)时,帧率最小,笔者最大帧率为60+fps

但是我们也同时看到,解码jpg文件的时间较长,一张图片200ms左右(1080p)

 

原理

       加载5组,每组16个6*1080p横向凭借的jpg文件(一行80个1080p),不断循环从1组切至5组,测试刷新帧率。

 

代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPaintEvent>
#include "hmfpaintwidget.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
protected slots:
    void timeout();
    void clean();
protected:
    void paintEvent(QPaintEvent *event);
private slots:
    void on_action_triggered();
    void on_action2_triggered();
    void on_action3_triggered();
    void on_action4_triggered();
    void on_action5_triggered();
    void on_actionStop_triggered();
    void on_action1_triggered();
    void on_action2_2_triggered();
private:
    Ui::MainWindow *ui;
    HMFPaintWidget * _pHMFPaintWigdet;
    QList<QList<QPixmap *>> _listListPPixmap;
    QList<QImage *> _listImage;
    int _currentIndex;
    QTimer *_pTimer;
    int _dirs;
    bool _start;
    int _interval;
    int _factor;
    int _count;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QUrl>
#include <QTimer>
#include <QPainter>
#include <QPixmap>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    _dirs(5),
    _interval(40),
    _start(false),
    _factor(1),
    _count(16)
{
    ui->setupUi(this);
    _pHMFPaintWigdet = new HMFPaintWidget;
    setCentralWidget(_pHMFPaintWigdet);
    _currentIndex = 0;
    _pTimer = new QTimer(this);
    connect(_pTimer, SIGNAL(timeout()), this, SLOT(timeout()));
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::timeout()
{
    static int number = 0;
    number++;
    if(_listListPPixmap.size() != 0)
    {
        _pHMFPaintWigdet->setListPixmap(_listListPPixmap.at(number%_listListPPixmap.size()));
    }
    if(_listImage.size() != 0)
    {
        _pHMFPaintWigdet->setImage(_listImage.at(number%_listImage.size()));
    }
}
void MainWindow::clean()
{
    _pTimer->stop();
    _dirs = 1;
    _start = false;
    _pHMFPaintWigdet->clear();
    qDebug() << __FILE__ << __LINE__;
    for(int index = 0; index < _listListPPixmap.size(); index++)
    {
        QList<QPixmap *> listPPixmap = _listListPPixmap.at(index);
         qDebug() << __FILE__ << __LINE__ << index << listPPixmap;
        for(int index2 = 0; index2 < listPPixmap.size(); index2++)
        {
            delete listPPixmap.at(index2);
            qDebug() << __FILE__ << __LINE__ << index2 << listPPixmap.at(index2);
        }
    }
    qDebug() << __FILE__ << __LINE__;
    _listListPPixmap.clear();
    qDebug() << __FILE__ << __LINE__;
}
#if 1
#if 1
void MainWindow::paintEvent(QPaintEvent *event)
{
    if(_start)
    {
        qint64 total = 0;
        QPainter painter(this);
        for(int index = 0; index < _dirs; index++)
        {
            QList<QPixmap *> listPPixmap;
            for(int index2 = 0; index2 < _count; index2++)
            {
                QElapsedTimer t;
                t.start();
                QString file = QString("./images/images%1/%2.jpg").arg(index+1).arg(index2+1);
                QImage  image(file);
                painter.drawText(0,50, QString("正在读取文件:%1").arg(file));
                QPixmap * pPixmap = new QPixmap(image.width(), image.height());
                *pPixmap = QPixmap::fromImage(image);
                listPPixmap.push_back(pPixmap);
                QString str = QString("file: %1 time:%2").arg(file).arg(t.elapsed());
                total += t.elapsed();
                DEBUG(str);
            }
            _listListPPixmap.push_back(listPPixmap);
        }
        _pTimer->start(_interval);
        _start = false;
    }
    QMainWindow::paintEvent(event);
}
#else
void MainWindow::paintEvent(QPaintEvent *event)
{
    if(_start)
    {
        for(int index = 0; index < _dirs; index++)
        {
            QPixmap *pPixmap = new QPixmap(9600/_factor*_count, 1080/_factor);  // 若_factor=1,则静态对多2幅图 动态最多1幅图 可存入内存
            pPixmap->fill(Qt::white);
            QPainter painter(pPixmap);
            for(int index2 = 0; index2 < _count; index2++)
            {
                QPixmap pixmap2(QString("./images/images%1/%2.jpg").arg(index+1).arg(index2+1));
                painter.drawPixmap(index2*(9600/_factor), 0, 9600/_factor, 1080/_factor, pixmap2);
            }
            _listPixmap.push_back(pPixmap);
        }
        _pTimer->start(_interval);
        _start = false;
    }
    QMainWindow::paintEvent(event);
}
#endif
#else
void MainWindow::paintEvent(QPaintEvent *event)
{
    if(_start)
    {
        for(int index = 0; index < _dirs; index++)
        {
            QImage *pImage = new QImage(9600/_factor*_count, 1080/_factor, QImage::Format_RGB32);  // 若_factor=1,则静态对多2幅图 动态最多1幅图 可存入内存
            pImage->fill(Qt::white);
            QPainter painter(pImage);
            for(int index2 = 0; index2 < _count; index2++)
            {
                QImage image2(QString("./images/images%1/%2.jpg").arg(index+1).arg(index2+1));
                painter.drawImage(QRect(index2*(9600/_factor), 0, 9600/_factor, 1080/_factor), image2);
            }
            _listImage.push_back(pImage);
        }
        _pTimer->start(_interval);
        _start = false;
    }
    QMainWindow::paintEvent(event);
}
#endif
void MainWindow::on_action_triggered()
{
    clean();
    _dirs = 1;
    _start = true;
    update();
}
void MainWindow::on_action2_triggered()
{
    clean();
    _dirs = 2;
    _start = true;
    update();
}
void MainWindow::on_action3_triggered()
{
    clean();
    _dirs = 3;
    _start = true;
    update();
}
void MainWindow::on_action4_triggered()
{
    clean();
    _dirs = 4;
    _start = true;
    update();
}
void MainWindow::on_action5_triggered()
{
    clean();
    _dirs = 5;
    _start = true;
    update();
}
void MainWindow::on_actionStop_triggered()
{
    clean();
}
void MainWindow::on_action1_triggered()
{
    _factor = 1;
}
void MainWindow::on_action2_2_triggered()
{
    _factor = 2;
}

 

hmfpaintwidget.h

 

#ifndef HMFPAINTWIDGET_H
#define HMFPAINTWIDGET_H
#define DEBUG(msg) \
    (qDebug()<<QString("[%1][%2:%3:%4]%5").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")) \
                                          .arg(__FILE__) \
                                          .arg(__FUNCTION__) \
                                          .arg(__LINE__).arg(msg));
#include <QDateTime>
#include <QDebug>
#include <QWidget>
#include <QElapsedTimer>
#include <QList>
class QRect;
class QPaintEvent;
class QResizeEvent;
class QPixmap;
class HMFPaintWidget : public QWidget
{
    Q_OBJECT
public:
    explicit HMFPaintWidget(QWidget *parent = nullptr);
signals:
public slots:
    void setListPixmap(QList<QPixmap *> listPPixmap, bool reload = false);
    void setPixmap(QPixmap *pixmap, bool reload = false);
    void setImage(QImage *image, bool reload = false);
    void setPicture(QPicture *picture, bool reload = false);
    void flushBackground();
    void clear();
    void scaleToRect(QRect desRect);
    void render();
protected:
    void drawBackground(QPainter &painter);
    void drawPixmap(QPainter &painter);
    void drawListPixmap(QPainter &painter);
    void drawImage(QPainter &painter);
    void drawPicture(QPainter &painter);
    void drawFps(QPainter &painter);
protected:
    void paintEvent(QPaintEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;
    void timerEvent(QTimerEvent *event) override;
private:
    QColor _colorBackgound;
    bool _clearBackgroud;
    QRectF _rectOrigin;
    QRectF _rectUse;
    QRectF _rectVisible;
    QList<QPixmap *> _listPPixmap;
    QPixmap _pixmapFull;
    QPixmap _pixmap;
    QImage *_imageFull;
    QImage _image;
    float _scaleStep;
    bool _leftButtonPressed;
    QPoint _pointLast;
    QElapsedTimer _time;
    bool _updateFps;
    float _fps;
    float _fpsAverage;
};
#endif // HMFPAINTWIDGET_H

hmfpaintwidget.cpp

#include "hmfpaintwidget.h"
#include <QPainter>
#include <QDebug>
#include <QPixmap>
#include <QWheelEvent>
#include <QTimer>
#include <QElapsedTimer>
HMFPaintWidget::HMFPaintWidget(QWidget *parent)
    : QWidget(parent),
      _colorBackgound(QColor(Qt::white)),
      _clearBackgroud(true),
      _scaleStep(0.01f),
      _leftButtonPressed(false),
      _updateFps(false)
{
    setCursor(Qt::OpenHandCursor);
    startTimer(1000);
    _imageFull = 0;
    render();
}
void HMFPaintWidget::setListPixmap(QList<QPixmap *> listPPixmap, bool reload)
{
    if(_listPPixmap.size() == 0 || reload)
    {
        _listPPixmap = listPPixmap;
        _rectOrigin = QRect(0, 0, _listPPixmap.at(0)->rect().width()*_listPPixmap.size(), _listPPixmap.at(0)->rect().height());
        scaleToRect(rect());
        _fps = 0;
        _fpsAverage = 0;
        _time.start();
    }else
    {
        _listPPixmap = listPPixmap;
    }
}
void HMFPaintWidget::setPixmap(QPixmap *pixmap, bool reload)
{
    if(_pixmapFull.isNull() || reload)
    {
        _pixmapFull = *pixmap;
        _rectOrigin = QRect(_pixmapFull.rect());
        scaleToRect(rect());
        _fps = 0;
        _fpsAverage = 0;
        _time.start();
//        _pixmapFull.save("./ouput.png");
    }else
    {
        _pixmapFull = *pixmap;
    }
    update();
}
void HMFPaintWidget::setImage(QImage *image, bool reload)
{
    if(_pixmapFull.isNull() || reload)
    {
        _imageFull = image;
        _rectOrigin = QRect(_imageFull->rect());
        scaleToRect(rect());
        _fps = 0;
        _fpsAverage = 0;
        _time.start();
//        _imageFull.save("./ouput.png");
    }else
    {
        _imageFull = image;
    }
    update();
}
void HMFPaintWidget::setPicture(QPicture *picture, bool reload)
{
}
void HMFPaintWidget::flushBackground()
{
    _clearBackgroud = true;
}
void HMFPaintWidget::clear()
{
    _clearBackgroud = true;
    _pixmapFull = QPixmap();
    _pixmap = QPixmap();
    _listPPixmap.clear();
}
void HMFPaintWidget::scaleToRect(QRect desRect)
{
    float scaleOrigin = _rectOrigin.width() / (float)_rectOrigin.height();
    float scaleWidget = desRect.width() / (float)desRect.height();
    if(scaleOrigin > scaleWidget)
    {
        float scale;
        scale = this->rect().width() / (float)_rectOrigin.width();
        _rectUse.setWidth(_rectOrigin.width()*scale);
        _rectUse.setHeight(_rectOrigin.height()*scale);
        // rect直接使用setx sety 会导致 height width 发生改变,必须使用moveTo
        _rectUse.moveTo(0, (desRect.height()-_rectUse.height())/2 );
    }else{
        float scale;
        scale = this->rect().height() / _rectOrigin.height();
        _rectUse.setWidth(_rectOrigin.width()*scale);
        _rectUse.setHeight(_rectOrigin.height()*scale);
        _rectUse.moveTo((desRect.width()-_rectUse.width())/2, 0);
    }
}
void HMFPaintWidget::drawBackground(QPainter &painter)
{
    painter.save();
    painter.setBrush(_colorBackgound);
    painter.drawRect(0, 0, rect().width(), rect().height());
    painter.restore();
}
void HMFPaintWidget::drawPixmap(QPainter &painter)
{
    painter.save();
    painter.drawPixmap(_rectUse.toRect(), _pixmapFull);
    painter.restore();
}
void HMFPaintWidget::drawListPixmap(QPainter &painter)
{
    if(_listPPixmap.size() == 0)
        return;
    painter.save();
    float width = _rectUse.width()/(float)_listPPixmap.size();
    float lastX = _rectUse.x();
    for(int index = 0; index < _listPPixmap.size(); index++)
    {
        painter.drawPixmap(lastX,
                           _rectUse.y(),
                           width,
                           _rectUse.height(),
                           *_listPPixmap.at(index));
        lastX += width-1;
    }
    painter.restore();
}
void HMFPaintWidget::drawImage(QPainter &painter)
{
    DEBUG("");
    painter.save();
    if(_imageFull != NULL)
        painter.drawImage(_rectUse.toRect(), *_imageFull);
    painter.restore();
}
void HMFPaintWidget::drawPicture(QPainter &painter)
{
}
void HMFPaintWidget::drawFps(QPainter &painter)
{
    painter.save();
    painter.drawText(1, rect().height()-1, QString("fps:%1    average fps:%2").arg(_fps).arg(_fpsAverage/(_time.elapsed()/1000)));
    painter.restore();
}
void HMFPaintWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    if(_clearBackgroud)
    {
        drawBackground(painter);
        _clearBackgroud = false;
    }
    drawListPixmap(painter);
    drawFps(painter);
    static int fps = 0;
    if(_updateFps)
    {
        _fps = fps;
        fps = 0;
        _updateFps = false;
    }
    fps++;
    _fpsAverage++;
}
void HMFPaintWidget::resizeEvent(QResizeEvent *event)
{
}
void HMFPaintWidget::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        _leftButtonPressed = true;
        _pointLast = event->pos();
        setCursor(Qt::ClosedHandCursor);
    }
}
void HMFPaintWidget::mouseMoveEvent(QMouseEvent *event)
{
    if(_leftButtonPressed)
    {
        static QPoint dPoint;
        dPoint = event->pos() - _pointLast;
        _pointLast = event->pos();
        _rectUse.moveTopLeft(_rectUse.topLeft() + dPoint);
    }
}
void HMFPaintWidget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        _leftButtonPressed = false;
        setCursor(Qt::OpenHandCursor);
    }
}
void HMFPaintWidget::wheelEvent(QWheelEvent *event)
{
    if(event->angleDelta().ry() > 0)
    {
        float scale = 1.0f + _scaleStep;
        float dx = (event->pos().x() - _rectUse.x()) * scale - (event->pos().x() - _rectUse.x());
        float dy = (event->pos().y() - _rectUse.y()) * scale - (event->pos().y() - _rectUse.y());
        _rectUse = QRectF(_rectUse.x()-dx, _rectUse.y()-dy, _rectUse.width()*scale, _rectUse.height()*scale);
    }else
    {
        float scale = 1.0f - _scaleStep;
        float dx = (event->pos().x() - _rectUse.x()) * scale - (event->pos().x() - _rectUse.x());
        float dy = (event->pos().y() - _rectUse.y()) * scale - (event->pos().y() - _rectUse.y());
        _rectUse = QRectF(_rectUse.x()-dx, _rectUse.y()-dy, _rectUse.width()*scale, _rectUse.height()*scale);
    }
}
void HMFPaintWidget::timerEvent(QTimerEvent *event)
{
    _updateFps = true;
}
void HMFPaintWidget::render()
{
    static int count = 0;
    if(count == 0)
        _time.start();
    update();
    count++;
    QTimer::singleShot(0, this, SLOT(render()));
}

 

原博主博客地址:https://blog.csdn.net/qq21497936

原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062

本文章博客地址:https://blog.csdn.net/qq21497936/article/details/79557290

 



相关文章
|
7月前
|
测试技术 Python
软件测试|Python字符串拼接详细解析
软件测试|Python字符串拼接详细解析
77 0
|
8月前
|
存储 关系型数据库 MySQL
深聊性能测试,从入门到放弃之:性能测试技术栈,看完这篇,保证刷新你对性能测试的认知~~
深聊性能测试,从入门到放弃之:性能测试技术栈,看完这篇,保证刷新你对性能测试的认知~~
156 1
|
安全 Java 数据库
案例之刷新token测试|学习笔记
快速学习案例之刷新token测试
322 0
案例之刷新token测试|学习笔记
|
存储 Cloud Native 多模数据库
阿里云数据库Lindorm刷新TPC物联网测试纪录:性能比第二名高40%
国际处理性能委员会TPC官方披露,在该机构组织的衡量物联网网关系统性能的基准测试中,阿里自研云原生多模数据库Lindorm性能指标创下新纪录,达到485万IoTps,比第二名高出40%,同时成本降低60%以上。
3500 0
阿里云数据库Lindorm刷新TPC物联网测试纪录:性能比第二名高40%
|
机器人 定位技术 计算机视觉
Qt实用技巧:使用Qt加载超大图片的耗时测试
Qt实用技巧:使用Qt加载超大图片的耗时测试
Qt实用技巧:使用Qt加载超大图片的耗时测试
|
JSON 数据格式 计算机视觉
案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo
案例分享:Qt的80路显示超大屏幕拼接(十台服务器,每台八路摄像头)方案和Demo
Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗
Qt实用技巧:测试QImage加载解码、QImage使用原数据、QImage格式转换等等的时间消耗
|
计算机视觉
案例分享:Qt用于服务器多图像拼接存在误差的标定工具(像素误差校准)
案例分享:Qt用于服务器多图像拼接存在误差的标定工具(像素误差校准)
|
网络协议 测试技术
gprs实用技巧:gprs模块tcp连接稳定性测试
gprs实用技巧:gprs模块tcp连接稳定性测试
gprs实用技巧:gprs模块tcp连接稳定性测试
|
缓存 Java Shell
专项测试实战 | 如何测试 App 流畅度(基于 FPS 和丢帧率)?
专项测试实战 | 如何测试 App 流畅度(基于 FPS 和丢帧率)?

推荐镜像

更多