一.Qwt库
1.Qwt库功能说明
Qwt是一个用于数据可视化的开源软件库,它提供了丰富的图表绘制功能,使得开发者可以轻松地创建各种类型的图表,如曲线图、散点图、柱状图等。Qwt库基于Qt框架开发,可以与Qt应用程序无缝集成,为用户提供了强大的数据可视化能力。
Qwt是一个强大的数据可视化工具,提供了丰富的图表绘制功能和交互功能,以及灵活的扩展性。它可以帮助开发者快速、高效地实现数据可视化需求,提高数据分析和决策的效果。无论是在科学研究、工程设计还是商业分析等领域,Qwt都能发挥重要的作用,为用户提供优秀的数据可视化体验。
2.下载
qwt - snapshot.debian.org
3.官方文档
https://qwt.sourceforge.io/class_qwt_plot_spectrogram.html
二.Qwt库应用
频谱图(Spectrogram)是一种用于表示信号频率特性的图形表示,广泛应用于信号处理、音频处理、语音识别等领域。
频谱图通过将信号分解成不同频率的成分,并计算每个成分的幅度和相位信息,从而将信号的频率特性以可视化的方式呈现出来。在频谱图中,横轴表示时间,纵轴表示频率,颜色或灰度表示该频率分量的幅度或相位。
频谱图可以分为线性频谱图和对数频谱图两种类型。线性频谱图将幅度信息线性映射到颜色或灰度上,通常用于表示信号的细节和动态范围。对数频谱图则将幅度信息对数映射到颜色或灰度上,可以更好地突出不同频率分量的相对大小,尤其是在信号中有较大动态范围的情况下。
频谱图可以通过各种算法和工具来生成,例如快速傅里叶变换(FFT)、短时傅里叶变换(STFT)等。在MATLAB等数学软件中,也有专门的函数来生成频谱图。
频谱图在许多领域中都有广泛的应用,例如:
(1).音频处理:频谱图常用于音频信号处理中,如音频分析、音乐信息检索、语音识别等。通过对音频信号进行频谱分析,可以提取出音频的音高、音色、音量等特征信息。
(2).故障诊断:在机械故障诊断中,通过对机器产生的声音或振动信号进行频谱分析,可以识别出异常频率成分,从而判断故障的类型和位置。
(3).通信系统:在通信系统中,频谱图可以用于信号的调制、解调、干扰抑制等方面。通过对信号的频谱进行分析和处理,可以提高通信系统的性能和可靠性。
(4).生物医学工程:在生物医学工程领域,频谱图可以用于心电图(ECG)、脑电图(EEG)等生理信号的分析和处理,帮助医生更好地诊断疾病和监测病人的生理状态。
(5).雷达和声呐:在雷达和声呐领域,频谱图可以用于目标检测、信号处理等方面。通过对接收到的信号进行频谱分析,可以提取出目标的信息和特征。
(6).总之,频谱图作为一种可视化工具,在信号处理、音频处理、通信、生物医学工程等领域中都有着广泛的应用。通过频谱图,人们可以更好地理解信号的频率特性和动态变化情况,从而为各种应用提供重要的支持和参考。
3.Qwt库Spectrogram频谱图代码实现
(1)矩阵数据输入方式
#include "Plot.h"
#include "qwt_color_map.h"
#include "qwt_plot_spectrogram.h"
#include "qwt_scale_widget.h"
#include "qwt_scale_draw.h"
#include "qwt_plot_zoomer.h"
#include "qwt_plot_panner.h"
#include "qwt_plot_layout.h"
#include "qwt_plot_renderer.h"
#include "qwt_interval.h"
#include "qwt_painter.h"
#include "qwt_plot_canvas.h"
#include "qwt_plot_magnifier.h"
#include
#include
#include
#include
#include
#include
namespace
{
class RasterData : public QwtMatrixRasterData
{
public:
RasterData()
{
const double matrix[] =
{
1, 2, 4, 1,
6, 3, 5, 2,
4, 2, 1, 5,
5, 4, 2, 3
};
QVector< double > values;
for ( uint i = 0; i < sizeof( matrix ) / sizeof( double ); i++ )
{
values += matrix[i];
qDebug()< } const int numColumns = 4; setValueMatrix( values, numColumns ); setInterval( Qt::XAxis, QwtInterval( -0.5, 13.5, QwtInterval::ExcludeMaximum ) ); setInterval( Qt::YAxis, QwtInterval( -0.5, 14.5, QwtInterval::ExcludeMaximum ) ); setInterval( Qt::ZAxis, QwtInterval( 1.0, 6.0 ) ); } }; class ColorMap : public QwtLinearColorMap { public: ColorMap() : QwtLinearColorMap( Qt::darkBlue, Qt::darkRed ) { addColorStop( 0.2, Qt::blue ); addColorStop( 0.4, Qt::cyan ); addColorStop( 0.6, Qt::yellow ); addColorStop( 0.8, Qt::red ); } }; } Plot::Plot( QWidget* parent ): QwtPlot( parent ) { QwtPlotCanvas* canvas = new QwtPlotCanvas(); canvas->setBorderRadius( 10 ); setCanvas( canvas ); #if 0 QwtPlotGrid* grid = new QwtPlotGrid(); grid->setPen( Qt::DotLine ); grid->attach( this ); #endif m_spectrogram = new QwtPlotSpectrogram(); m_spectrogram->setRenderThreadCount( 0 ); // use system specific thread count m_spectrogram->setColorMap( new ColorMap() ); m_spectrogram->setData( new RasterData() ); m_spectrogram->attach( this ); const QwtInterval zInterval = m_spectrogram->data()->interval( Qt::ZAxis ); // A color bar on the right axis QwtScaleWidget* rightAxis = axisWidget( QwtAxis::YRight ); rightAxis->setColorBarEnabled( true ); rightAxis->setColorBarWidth( 40 ); rightAxis->setColorMap( zInterval, new ColorMap() ); setAxisScale( QwtAxis::YRight, zInterval.minValue(), zInterval.maxValue() ); setAxisVisible( QwtAxis::YRight ); plotLayout()->setAlignCanvasToScales( true ); setAxisScale( QwtAxis::XBottom, 0.0, 13.0 ); setAxisMaxMinor( QwtAxis::XBottom, 0 ); setAxisScale( QwtAxis::YLeft, 0.0, 13.0 ); setAxisMaxMinor( QwtAxis::YLeft, 0 ); QwtPlotMagnifier* magnifier = new QwtPlotMagnifier( canvas ); magnifier->setAxisEnabled( QwtAxis::YRight, false ); QwtPlotPanner* panner = new QwtPlotPanner( canvas ); panner->setAxisEnabled( QwtAxis::YRight, false ); } void Plot::exportPlot() { QwtPlotRenderer renderer; renderer.exportTo( this, "rasterview.pdf" ); } void Plot::setResampleMode( int mode ) { RasterData* rasterData = static_cast< RasterData* >( m_spectrogram->data() ); rasterData->setResampleMode( static_cast< QwtMatrixRasterData::ResampleMode >( mode ) ); replot(); } (2).模拟生成数据方式 #include "Plot.h" #include "qwt_color_map.h" #include "qwt_plot_spectrogram.h" #include "qwt_scale_widget.h" #include "qwt_scale_draw.h"" #include "qwt_plot_zoomer.h"" #include "qwt_plot_panner.h"" #include "qwt_plot_layout.h"" #include "qwt_plot_renderer.h"" #include "qwt_interval.h"" #include "qwt_painter.h"" #include #include #include #include namespace { class MyZoomer : public QwtPlotZoomer { public: MyZoomer( QWidget* canvas ) : QwtPlotZoomer( canvas ) { setTrackerMode( AlwaysOn ); } virtual QwtText trackerTextF( const QPointF& pos ) const QWT_OVERRIDE { QColor bg( Qt::white ); bg.setAlpha( 200 ); QwtText text = QwtPlotZoomer::trackerTextF( pos ); text.setBackgroundBrush( QBrush( bg ) ); return text; } }; class SpectrogramData : public QwtRasterData { public: SpectrogramData() { // some minor performance improvements when the spectrogram item // does not need to check for NaN values setAttribute( QwtRasterData::WithoutGaps, true ); m_intervals[ Qt::XAxis ] = QwtInterval( -1.5, 1.5 ); m_intervals[ Qt::YAxis ] = QwtInterval( -1.5, 1.5 ); m_intervals[ Qt::ZAxis ] = QwtInterval( 0.0, 10.0 ); } virtual QwtInterval interval( Qt::Axis axis ) const QWT_OVERRIDE { if ( axis >= 0 && axis <= 2 ) return m_intervals[ axis ]; return QwtInterval(); } virtual double value( double x, double y ) const QWT_OVERRIDE { const double c = 0.842; //const double c = 0.33; const double v1 = x * x + ( y - c ) * ( y + c ); const double v2 = x * ( y + c ) + x * ( y + c ); return 1.0 / ( v1 * v1 + v2 * v2 ); } private: QwtInterval m_intervals[3]; }; class LinearColorMap : public QwtLinearColorMap { public: LinearColorMap( int formatType ) : QwtLinearColorMap( Qt::darkCyan, Qt::red ) { setFormat( ( QwtColorMap::Format ) formatType ); addColorStop( 0.1, Qt::cyan ); addColorStop( 0.6, Qt::green ); addColorStop( 0.95, Qt::yellow ); } }; class HueColorMap : public QwtHueColorMap { public: HueColorMap( int formatType ) : QwtHueColorMap( QwtColorMap::Indexed ) { setFormat( ( QwtColorMap::Format ) formatType ); //setHueInterval( 240, 60 ); //setHueInterval( 240, 420 ); setHueInterval( 0, 359 ); setSaturation( 150 ); setValue( 200 ); } }; class SaturationColorMap : public QwtSaturationValueColorMap { public: SaturationColorMap( int formatType ) { setFormat( ( QwtColorMap::Format ) formatType ); setHue( 220 ); setSaturationInterval( 0, 255 ); setValueInterval( 255, 255 ); } }; class ValueColorMap : public QwtSaturationValueColorMap { public: ValueColorMap( int formatType ) { setFormat( ( QwtColorMap::Format ) formatType ); setHue( 220 ); setSaturationInterval( 255, 255 ); setValueInterval( 70, 255 ); } }; class SVColorMap : public QwtSaturationValueColorMap { public: SVColorMap( int formatType ) { setFormat( ( QwtColorMap::Format ) formatType ); setHue( 220 ); setSaturationInterval( 100, 255 ); setValueInterval( 70, 255 ); } }; class AlphaColorMap : public QwtAlphaColorMap { public: AlphaColorMap( int formatType ) { setFormat( ( QwtColorMap::Format ) formatType ); //setColor( QColor("DarkSalmon") ); setColor( QColor("SteelBlue") ); } }; class Spectrogram : public QwtPlotSpectrogram { public: int elapsed() const { return m_elapsed; } QSize renderedSize() const { return m_renderedSize; } protected: virtual QImage renderImage( const QwtScaleMap& xMap, const QwtScaleMap& yMap, const QRectF& area, const QSize& imageSize ) const QWT_OVERRIDE { QElapsedTimer t; t.start(); QImage image = QwtPlotSpectrogram::renderImage( xMap, yMap, area, imageSize ); m_elapsed = t.elapsed(); m_renderedSize = imageSize; return image; } private: mutable int m_elapsed; mutable QSize m_renderedSize; }; } Plot::Plot( QWidget* parent ) : QwtPlot( parent ) , m_alpha(255) { m_spectrogram = new Spectrogram(); m_spectrogram->setRenderThreadCount( 0 ); // use system specific thread count m_spectrogram->setCachePolicy( QwtPlotRasterItem::PaintCache ); QList< double > contourLevels; for ( double level = 0.5; level < 10.0; level += 1.0 ) contourLevels += level; m_spectrogram->setContourLevels( contourLevels ); m_spectrogram->setData( new SpectrogramData() ); m_spectrogram->attach( this ); const QwtInterval zInterval = m_spectrogram->data()->interval( Qt::ZAxis ); // A color bar on the right axis QwtScaleWidget* rightAxis = axisWidget( QwtAxis::YRight ); rightAxis->setTitle( "Intensity" ); rightAxis->setColorBarEnabled( true ); setAxisScale( QwtAxis::YRight, zInterval.minValue(), zInterval.maxValue() ); setAxisVisible( QwtAxis::YRight ); plotLayout()->setAlignCanvasToScales( true ); setColorMap( Plot::RGBMap ); // LeftButton for the zooming // MidButton for the panning // RightButton: zoom out by 1 // Ctrl+RighButton: zoom out to full size QwtPlotZoomer* zoomer = new MyZoomer( canvas() ); zoomer->setMousePattern( QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier ); zoomer->setMousePattern( QwtEventPattern::MouseSelect3, Qt::RightButton ); QwtPlotPanner* panner = new QwtPlotPanner( canvas() ); panner->setAxisEnabled( QwtAxis::YRight, false ); panner->setMouseButton( Qt::MiddleButton ); // Avoid jumping when labels with more/less digits // appear/disappear when scrolling vertically const int extent = QwtPainter::horizontalAdvance( axisWidget( QwtAxis::YLeft )->fontMetrics(), "100.00" ); axisScaleDraw( QwtAxis::YLeft )->setMinimumExtent( extent ); const QColor c( Qt::darkBlue ); zoomer->setRubberBandPen( c ); zoomer->setTrackerPen( c ); } void Plot::showContour( bool on ) { m_spectrogram->setDisplayMode( QwtPlotSpectrogram::ContourMode, on ); replot(); } void Plot::showSpectrogram( bool on ) { m_spectrogram->setDisplayMode( QwtPlotSpectrogram::ImageMode, on ); m_spectrogram->setDefaultContourPen( on ? QPen( Qt::black, 0 ) : QPen( Qt::NoPen ) ); replot(); } void Plot::setColorTableSize( int type ) { int numColors = 0; switch( type ) { case 1: numColors = 256; break; case 2: numColors = 1024; break; case 3: numColors = 16384; break; } m_spectrogram->setColorTableSize( numColors ); replot(); } void Plot::setColorMap( int type ) { QwtScaleWidget* axis = axisWidget( QwtAxis::YRight ); const QwtInterval zInterval = m_spectrogram->data()->interval( Qt::ZAxis ); m_mapType = type; const QwtColorMap::Format format = QwtColorMap::RGB; int alpha = m_alpha; switch( type ) { case Plot::HueMap: { m_spectrogram->setColorMap( new HueColorMap( format ) ); axis->setColorMap( zInterval, new HueColorMap( format ) ); break; } case Plot::SaturationMap: { m_spectrogram->setColorMap( new SaturationColorMap( format ) ); axis->setColorMap( zInterval, new SaturationColorMap( format ) ); break; } case Plot::ValueMap: { m_spectrogram->setColorMap( new ValueColorMap( format ) ); axis->setColorMap( zInterval, new ValueColorMap( format ) ); break; } case Plot::SVMap: { m_spectrogram->setColorMap( new SVColorMap( format ) ); axis->setColorMap( zInterval, new SVColorMap( format ) ); break; } case Plot::AlphaMap: { alpha = 255; m_spectrogram->setColorMap( new AlphaColorMap( format ) ); axis->setColorMap( zInterval, new AlphaColorMap( format ) ); break; } case Plot::RGBMap: default: { m_spectrogram->setColorMap( new LinearColorMap( format ) ); axis->setColorMap( zInterval, new LinearColorMap( format ) ); } } m_spectrogram->setAlpha( alpha ); replot(); } void Plot::setAlpha( int alpha ) { // setting an alpha value doesn't make sense in combination // with a color map interpolating the alpha value m_alpha = alpha; if ( m_mapType != Plot::AlphaMap ) { m_spectrogram->setAlpha( alpha ); replot(); } } void Plot::drawItems( QPainter* painter, const QRectF& canvasRect, const QwtScaleMap maps[QwtAxis::AxisPositions] ) const { QwtPlot::drawItems( painter, canvasRect, maps ); if ( m_spectrogram ) { Spectrogram* spectrogram = static_cast< Spectrogram* >( m_spectrogram ); QString info( "%1 x %2 pixels: %3 ms" ); info = info.arg( spectrogram->renderedSize().width() ); info = info.arg( spectrogram->renderedSize().height() ); info = info.arg( spectrogram->elapsed() ); Plot* plot = const_cast< Plot* >( this ); plot->Q_EMIT rendered( info ); } } #ifndef QT_NO_PRINTER void Plot::printPlot() { QPrinter printer( QPrinter::HighResolution ); #if QT_VERSION >= 0x050300 printer.setPageOrientation( QPageLayout::Landscape ); #else printer.setOrientation( QPrinter::Landscape ); #endif printer.setOutputFileName( "spectrogram.pdf" ); QPrintDialog dialog( &printer ); if ( dialog.exec() ) { QwtPlotRenderer renderer; if ( printer.colorMode() == QPrinter::GrayScale ) { renderer.setDiscardFlag( QwtPlotRenderer::DiscardBackground ); renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasBackground ); renderer.setDiscardFlag( QwtPlotRenderer::DiscardCanvasFrame ); renderer.setLayoutFlag( QwtPlotRenderer::FrameWithScales ); } renderer.renderTo( this, printer ); } } 可以再本博客的资源中直接下载工程代码。