Qt QImage实现频谱图绘制

频谱图,又称光谱图,显示了信号的频谱强度随时间的变化,不同的强度采用不同的颜色显示,呈线性映射关系。在频谱图上,横轴表示频率,纵轴表示时间,每个点用不同颜色表示信号的强度。

在项目中遇到需要用Qt来实现频谱图绘制,数据每隔1秒发一批,每批数据包含不同频率对应的信号强度,频率最大到23300Hz,同时需要记录过去360秒的数据,最终程序需要运行在国产目标机上。

分析一下,需要建立坐标系来绘制,横轴有23300个维度,纵轴有360个维度,图上有23300×360=8388000个点,每秒更新一次。

实现方法有很多种,可以用QPainter、paintGL、QChart、QCustomPlot等,不同方法各有利弊,比如用QPainter实现的话性能较差,容易卡死;paintGL需要依赖OpenGL环境,国产机不一定支持;QChart只支持Qt5.7之后的版本;QCustomPlot功能强大,性能较好,而且开源,但是封装程度高,自由度小,可扩展接口较少。

这里提供另一种实现方法:

用QImage实时存储并显示,将信号强度对应的颜色存储到QImage中,每次更新时去掉第一个横向维度的数据,在最后添加一个横向维度的数据,组成新的图片更新显示。实测效果还不错,性能优良。

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTimer>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

protected:
    void initSetting();     // 初始化设置图片参数
    QRgb getRgb();          // 获取每个像素点的rgb(可自定义)
    void showToLabel();     // 图片显示到界面

protected slots:
    void updateImage();     // 定时器更新图片

private:
    Ui::Widget *ui;

    QImage m_image;     // 图片
    int m_width;        // 宽度
    int m_height;       // 高度
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

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

    // 定时器
    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateImage()));
    timer->start(1000);

    // 初始化设置
    initSetting();
}

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

void Widget::initSetting()
{
    m_width = 23300;
    m_height = 360;
    m_image = QImage(m_width, m_height, QImage::Format_RGB32);
    for (int i = 0; i < m_width; ++i)
    {
        for (int j = 0; j < m_height; ++j)
        {
            m_image.setPixel(QPoint(i, j), qRgb(21, 197, 212));     // 设置默认的背景颜色
        }
    }
    showToLabel();
}

QRgb Widget::getRgb()
{
    // 自定义强度和颜色的映射关系,暂用随机数
    int a = qrand() % 256;
    int b = qrand() % 256;
    int c = qrand() % 256;
    return qRgb(a, b, c);
}

void Widget::showToLabel()
{
    // 显示到label
    int pxWidth = this->width(), pxHeight = this->height();
    QImage imageTemp = m_image.scaled(pxWidth, pxHeight);
    QPixmap pixmap;
    pixmap.convertFromImage(imageTemp);
    ui->label->setPixmap(pixmap);
}

void Widget::updateImage()
{
    // 注:copy和setPixel接口的x和y指的是第x列,第y行
    QImage tempImage = m_image.copy(0, -1, m_width, m_height);      // 复制上一时刻背景,去掉最后一行,保留第一行为空(空即为黑色)
    for (int i = 0; i < m_width; ++i)       // 第一行赋值新的rgb
        tempImage.setPixel(QPoint(i, 0), getRgb());
    m_image = tempImage;
    showToLabel();
}

运行效果:

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值