PCLPoltter类似于Matlab的plot函数,用来对点云数据绘制分析图,例如某一行或列点云Z值的变化图。PCLPlotter提供了一个非常直接和简单的绘图界面。我们可以在库中可视化所有类型的重要绘图比如从多项式函数或直方图。在本章节中介绍一些特定概念时,请仔细阅读文档,以了解确切的方法名。
我们直接从程序片段中学习如何使用PCLPlotter吧。
从最简单的绘制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;
}
以上代码运行结束后如下:
由以上代码我们可以总结出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 ()
基本使用框架介绍完毕,下面我们将分别介绍更加细节的内容。
在addPlotData*()函数中,可以选择将想要的颜色添加到绘图中。但如果不主动设置,Plotter将根据配色方案自动上色。
默认的颜色方案是vtkColorSeries::SPECTRUM,它在整个光谱中包含7种不同的色调。
除了默认,也可以选择vtkColorSeries::WARM, vtkColorSeries::COOL, vtkColorSeries::BLUES, vtkColorSeries::WILD_FLOWER, vtkColorSeries::CITRUS.
你可以通过setColorScheme()函数来改变颜色方案。要将颜色方案的效果反映到所有绘图中,在调用任何addPlotData*()函数之前调用此函数才能生效。
在文档中可以查看addPlotData()函数的详细签名。这些原型基本上说明了它们的功能。
① Point-Correspondences(特征点匹配)
这是提供输入数据的最基本方式。使用std::vectorstd::pair;提供点对应,即(x,y)坐标。如下
...
std::vector<std::pair<double, double> > data;
populateData (data);
plotter->addPlotData (data,"cos");
...
② 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;
}
③ 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");
...
④ A custom explicit function(自定义显式函数)
用户可以指定一个自定义函数,f以回调的形式描述关系:Y = f(X)
...
double
identity (double val)
{
return val;
}
...
...
plotter->addPlotData (identity,-10, 10,"identity");
...
用户可以添加其他属性的情节,如标题,象限标题,图例,背景颜色等。需要在plotter->plot ();函数调用之前的任何时间调用这些函数。
...
plotter->setTitle ("My plot"); //global title
plotter->setXTitle ("degrees");
plotter->setYTitle ("cos");
plotter->setShowLegend (true); //show legends
...
plotter->plot ();
...
PCLPlotter提供了一个非常方便的MATLAB类直方图绘图函数(MATLAB中的hist())。它将原始数据根据频率进行分类并绘制成条形图。
...
std::vector<double> freqdata = generateNomalDistData ();
plotter->addHistogramData (freqdata,10); //number of bins are 10
plotter->plot ();
...
...
//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);
...
/* \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;
}
【博主简介】
斯坦福的兔子,男,天津大学工学硕士。毕业至今从事光学三维成像及点云处理相关工作。因工作中使用的三维处理库为公司内部库,不具有普遍适用性,遂自学开源PCL库及其相关数学知识以备使用。谨此将自学过程与君共享。
博主才疏学浅,尚不具有指导能力,如有问题还请各位在评论处留言供大家共同讨论。