• 【PCL自学:PCLPlotter】PCLPlotter绘制数据分析图


    一、什么是PCLPlotter

       PCLPoltter类似于Matlab的plot函数,用来对点云数据绘制分析图,例如某一行或列点云Z值的变化图。PCLPlotter提供了一个非常直接和简单的绘图界面。我们可以在库中可视化所有类型的重要绘图比如从多项式函数或直方图。在本章节中介绍一些特定概念时,请仔细阅读文档,以了解确切的方法名。
       我们直接从程序片段中学习如何使用PCLPlotter吧。

    二、示例程序

    2.1 基本绘图流程

       从最简单的绘制X,Y相关二次曲线( y = x 2 y=x^2 y=x2)开始。

    #include<vector>
    #include<iostream>
    #include<utility>
    
    #include<pcl/visualization/pcl_plotter.h>
    //...
    
    int
    main ()
    {
      //首先定义一个绘图器 PCLPlotter
      pcl::visualization::PCLPlotter * plotter = new PCLPlotter ();
    
      //然后定义绘图函数的多项式系数, 例如y = x^2.其多项式系数有3个,分别是1,0,0,在定义的容器里,第0个是常数,第1个是x的系数,第2个是x^2的系数。除了x^2系数是1,其余是0。
      std::vector<double> func1 (3,0);
      func1[2] = 1;
    
      //以[- 10,10]为X轴范围,以“y = X ^2”为标题,向绘图器中添加多项式func1
      plotter->addPlotData (func1, -10, 10, "y = x^2");
    
      //显示多项式图像
      plotter->plot ();
    
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

       以上代码运行结束后如下:
    在这里插入图片描述
       由以上代码我们可以总结出PCLPlotter的基本代码结构,其使用方法非常简单,类似于Matlab

    ...
    //1. 定义1个 plotter. 
    pcl::visualization::PCLPlotter *plotter = new PCLPlotter ("My Plotter");
    
    ...
    //2. 使用addPlotData* ()函数 添加多项式系数数据
    plotter->addPlotData* ();
    
    ...
    //3. 设置Plotter界面属性
    plotter->setWindowSize (900, 600);
    plotter->setYTitle ("this is my own function");
    
    ...
    //4. 显示界面
    plotter->plot ()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

      基本使用框架介绍完毕,下面我们将分别介绍更加细节的内容。

    2.2 绘图细节处理

    2.2.1 为图像选择颜色方案

      在addPlotData*()函数中,可以选择将想要的颜色添加到绘图中。但如果不主动设置,Plotter将根据配色方案自动上色。
      默认的颜色方案是vtkColorSeries::SPECTRUM,它在整个光谱中包含7种不同的色调。
      除了默认,也可以选择vtkColorSeries::WARM, vtkColorSeries::COOL, vtkColorSeries::BLUES, vtkColorSeries::WILD_FLOWER, vtkColorSeries::CITRUS.
      你可以通过setColorScheme()函数来改变颜色方案。要将颜色方案的效果反映到所有绘图中,在调用任何addPlotData*()函数之前调用此函数才能生效。

    2.2.2 选择不同类型的数据输入到图表

      在文档中可以查看addPlotData()函数的详细签名。这些原型基本上说明了它们的功能。

    ① Point-Correspondences(特征点匹配)
      这是提供输入数据的最基本方式。使用std::vectorstd::pair;提供点对应,即(x,y)坐标。如下

    ...
    std::vector<std::pair<double, double> > data;
    populateData (data);
    plotter->addPlotData (data,"cos");
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ② Table (表格)
      用户以空格分隔的表的形式将通信存储在文本文件中。这就形成了使用MS Excel绘图的替代。下面是一个非常简单的可执行文件,它执行了MS Excel Plotter的功能。

    #include<pcl/visualization/pcl_plotter.h>
    
    int
    main (int argc, char ** argv)
    {
      pcl::visualization::PCLPlotter * plotter = new PCLPlotter ();
      plotter->addPlotData (argv[1]);
      plotter->plot ();
    
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ③ Polynomial and Rational Functions(多项式和有理函数)
      多项式用系数向量来定义,有理函数用多项式对(分子和分母对)来定义。下面的代码片段绘制了函数y = 1/x的图形.

    ...
    std::vector<double> func1 (1,0);
    func1[0] = 1; // 1
    std::vector<double> func2 (2,0);
    func1[1] = 1; // x
    
    plotter->addPlotData (std::make_pair (func1, func2),-10, 10, "y = 1/x");
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    ④ A custom explicit function(自定义显式函数)
      用户可以指定一个自定义函数,f以回调的形式描述关系:Y = f(X)

    ...
    double
    identity (double val)
    {
      return val;
    }
    ...
    
    ...
    plotter->addPlotData (identity,-10, 10,"identity");
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.2.3 添加其他属性和装饰

      用户可以添加其他属性的情节,如标题,象限标题,图例,背景颜色等。需要在plotter->plot ();函数调用之前的任何时间调用这些函数。

    ...
    plotter->setTitle ("My plot"); //global title
    plotter->setXTitle ("degrees");
    plotter->setYTitle ("cos");
    plotter->setShowLegend (true); //show legends
    ...
    plotter->plot ();
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2.4 直方图和折线图

      PCLPlotter提供了一个非常方便的MATLAB类直方图绘图函数(MATLAB中的hist())。它将原始数据根据频率进行分类并绘制成条形图。

    ...
    
    std::vector<double> freqdata = generateNomalDistData ();
    
    plotter->addHistogramData (freqdata,10); //number of bins are 10
    
    plotter->plot ();
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.2.5 随着数据添加动态显示图形

    ...
    
    //data and callback defined here
    ...
    
    plotter->addPlotData (func1, -10, 10, "y = x^2");
    plotter->spinOnce (2000);    //动态显示频率 2s刷新一次
    
    plotter->clearPlots ();
    plotter->addPlotData (identity,-10, 10,"identity");
    plotter->spinOnce (2000);
    
    plotter->clearPlots ();
    plotter->addPlotData (abs,-5, 5,"abs");
    plotter->spinOnce (2000);
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.3 Demo

      /* \author Kripasindhu Sarkar */
      
      #include<pcl/visualization/pcl_plotter.h>
      
      #include<iostream>
      #include<vector>
      #include<utility>
      #include<cmath>  //for std::abs()
      
     using namespace pcl::visualization;
     
     void
     generateData (double *ax, double *acos, double *asin, int numPoints)
     {
       double inc = 7.5 / (numPoints - 1);
       for (int i = 0; i < numPoints; ++i)
       {
         ax[i] = i*inc;
         acos[i] = std::cos (i * inc);
         asin[i] = sin (i * inc);
       }
     }
     
     //.....................callback functions defining Y= f(X)....................
     double
     step (double val)
     {
       if (val > 0)
         return (double) (int) val;
       else
         return (double) ((int) val - 1);
    }
     
     double
     identity (double val)
    {
       return val;
    }
    //............................................................................
     
     int
     main ()
     {
       //defining a plotter
       PCLPlotter *plotter = new PCLPlotter ("My Plotter");
     
       //setting some properties
       plotter->setShowLegend (true);
     
       //generating point correspondances
       int numPoints = 69;
       double ax[100], acos[100], asin[100];
       generateData (ax, acos, asin, numPoints);
     
       //adding plot data
       plotter->addPlotData (ax, acos, numPoints, "cos");
       plotter->addPlotData (ax, asin, numPoints, "sin");
     
       //display for 2 seconds
       plotter->spinOnce (3000);
       plotter->clearPlots ();
       
       
       //...................plotting implicit functions and custom callbacks....................
     
       //make a fixed axis
       plotter->setYRange (-10, 10);
     
       //defining polynomials
       std::vector<double> func1 (1, 0);
       func1[0] = 1; //y = 1
       std::vector<double> func2 (3, 0);
       func2[2] = 1; //y = x^2
     
       plotter->addPlotData (std::make_pair (func1, func2), -10, 10, "y = 1/x^2", 100, vtkChart::POINTS);
       plotter->spinOnce (2000);
     
       plotter->addPlotData (func2, -10, 10, "y = x^2");
       plotter->spinOnce (2000);
     
       //callbacks
       plotter->addPlotData (identity, -10, 10, "identity");
       plotter->spinOnce (2000);
     
       plotter->addPlotData (std::abs, -10, 10, "abs");
       plotter->spinOnce (2000);
     
       plotter->addPlotData (step, -10, 10, "step", 100, vtkChart::POINTS);
       plotter->spinOnce (2000);
     
       plotter->clearPlots ();
     
       //........................A simple animation..............................
       std::vector<double> fsq (3, 0);
       fsq[2] = -100; //y = x^2
       while (!plotter->wasStopped ())
       {
         if (fsq[2] == 100) fsq[2] = -100;
         fsq[2]++;
        char str[50];
        sprintf (str, "y = %dx^2", (int) fsq[2]);
        plotter->addPlotData (fsq, -10, 10, str);
    
        plotter->spinOnce (100);
        plotter->clearPlots ();
      }
    
      return 1;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109

    【博主简介】
      斯坦福的兔子,男,天津大学工学硕士。毕业至今从事光学三维成像及点云处理相关工作。因工作中使用的三维处理库为公司内部库,不具有普遍适用性,遂自学开源PCL库及其相关数学知识以备使用。谨此将自学过程与君共享。
    博主才疏学浅,尚不具有指导能力,如有问题还请各位在评论处留言供大家共同讨论。

  • 相关阅读:
    打工毁一生,创业治百病,零经验零成本创业三个月收益10W+
    存储过程与触发器的练习题
    数据结构系列-堆排序
    .NET快速实现网页数据抓取
    C#开发的OpenRA游戏之系统参数选项按钮
    C++新特性_1
    数量关系(高照)
    2022年华数杯C题插层熔喷非织造材料的性能控制研究
    CSS动画收缩展开(transition)
    主流的深度学习推理架构有哪些(NCNNN)
  • 原文地址:https://blog.csdn.net/weixin_41966507/article/details/125462802