创建一个PCD文件
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int
main(int argc, char** argv)
{
//创建一个PointXYZ类型的点云对象
pcl::PointCloud<pcl::PointXYZ> cloud;
// Fill in the cloud data
cloud.width = 5;//默认为0
cloud.height = 1;//默认为0
cloud.is_dense = false;//默认为true,如果没有无效点(例如,具有NaN或Inf值),则为True
//points是一个vector容器,存储类型为PointT模板类,当前为PointXYZ
cloud.points.resize(cloud.width * cloud.height);
//随机填充
for (auto& point : cloud)
{
point.x = 1024 * rand() / (RAND_MAX + 1.0f);
point.y = 1024 * rand() / (RAND_MAX + 1.0f);
point.z = 1024 * rand() / (RAND_MAX + 1.0f);
}
//将点云保存至test_pcd.pcd文件
pcl::io::savePCDFileASCII("test_pcd.pcd", cloud);
std::cerr << "Saved " << cloud.size() << " data points to test_pcd.pcd." << std::endl;
//打印出来
for (const auto& point : cloud)
std::cerr << " " << point.x << " " << point.y << " " << point.z << std::endl;
return (0);
}
从pcd文件中读取点云
#include<iostream>
#include<pcl/io/pcd_io.h>//PCD读写类相关的头文件
#include<pcl/point_types.h>//点云类型头文件
int
main(int argc,char** argv) {
//typedef boost::shared_ptr<PointCloud<PointT> > Ptr;
//Ptr 是一个共享指针,使用pcl::PointXYZ类型来保存点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud < pcl::PointXYZ>);
//如果打开点云失败
if (pcl::io::loadPCDFile<pcl::PointXYZ>("test_pcd.pcd", *cloud) == -1)
{
PCL_ERROR("Couldn't read file test_pcd.pcd\n");
return (1);
}
std::cout << "Loaded "
<< cloud->width * cloud->height
<< " data points from test_pcd.pcd with the following fields: "
<< std::endl;
for (size_t i = 0; i < cloud->points.size(); ++i) {
std::cout << " " << cloud->points[i].x
<< " " << cloud->points[i].y
<< " " << cloud->points[i].z << std::endl;
}
return (0);
}
点云数据拼接和字段拼接
main函数参数知识回顾:
argc、argv的具体含义
argc和argv参数在用命令行编译程序时有用。main( int argc, char* argv[], char **env ) 中
第一个参数,int型的argc,为整型,用来统计程序运行时发送给main函数的命令行参数的个数,在VS中默认值为1。
第二个参数,char*型的argv[],为字符串数组,用来存放指向的字符串参数的指针数组,每一个元素指向一个参数。各成员含义如下:
argv[0]指向程序运行的全路径名
argv[1]指向在DOS命令行中执行程序名后的第一个字符串
argv[2]指向执行程序名后的第二个字符串
argv[3]指向执行程序名后的第三个字符串
argv[argc]为NULL
第三个参数,char**型的env,为字符串数组。env[]的每一个元素都包含ENVVAR=value形式的字符串,其中ENVVAR为环境变量,value为其对应的值。平时使用到的比较少。
字段拼接:点云字段连接函数concatenateFields ()
/** \brief Concatenate two datasets representing different fields.
*
* \note If the input datasets have overlapping fields (i.e., both contain
* the same fields), then the data in the second cloud (cloud2_in) will
* overwrite the data in the first (cloud1_in).
*
* \param[in] cloud1_in the first input dataset
* \param[in] cloud2_in the second input dataset (overwrites the fields of the first dataset for those that are shared)
* \param[out] cloud_out the resultant output dataset created by the concatenation of all the fields in the input datasets
* \ingroup common
*/
template <typename PointIn1T, typename PointIn2T, typename PointOutT> void
concatenateFields (const pcl::PointCloud<PointIn1T> &cloud1_in,
const pcl::PointCloud<PointIn2T> &cloud2_in,
pcl::PointCloud<PointOutT> &cloud_out);
- 连接两个表示不同字段的数据集。
- 如果输入数据集有重叠的字段(即,两个包含相同的字段),那么在第二个云(cloud2 in)中的数据将覆盖在第一个云(cloud1 in)中的数据。
- 参数cloud1_in在第一输入数据集
- 参数cloud2_in第二输入数据集(覆盖字段的第一个数据集对于那些共享)
- 参数cloud_out的合成输出数据集创建的连接中的所有字段输入数据集
点云数据拼接:直接相加
//cloud_c = cloud_a; //cloud_c += cloud_b; //cloud_c = cloud_b + cloud_a; cloud_c = cloud_a + cloud_b;
拼接结果与相加数据的顺序有关
测试
测试代码,包含字段拼接和数据拼接,通过输入参数“-f”或“-p”,来实现字段拼接和字符拼接示例:
#include<iostream>
#include<pcl/io/pcd_io.h>
#include<pcl/point_types.h>
using namespace std;
int
main(int argc, char** argv)
{
//判断输入参数个数是否正确,默认为1,如果输入一个,则为2
if (argc != 2)
{
cerr << "please specify command line arg '-f' or '-p'" << endl;
exit(0);
}
//创建点云类型存储
// 点云数据拼接:点云a + 点云b = 点云c
pcl::PointCloud<pcl::PointXYZ> cloud_a, cloud_b, cloud_c;
// 点云字段拼接: PointXYZ点云a + Normal 点云b = PointNormal 点云c
pcl::PointCloud<pcl::Normal> n_cloud_b;
pcl::PointCloud<pcl::PointNormal> p_n_cloud_c;
//通过输入参数判断是点云数据拼接还是字段拼接
bool isCatField = strcmp(argv[1],"-f") == 0;//默认是数据拼接,-p
//先创建点云数据
//创建cloud_a
cloud_a.width = 5;//宽为5,在无序点云中,宽即为点云个数
cloud_a.height = cloud_b.height = n_cloud_b.height = 1;//高度为1,说明为无序点云
cloud_a.points.resize(cloud_a.width*cloud_a.height);// 重置点云个数
//使用随机数填充点云a
for (size_t i = 0; i < cloud_a.points.size(); ++i)
{
cloud_a.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_a.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_a.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
}
//先把点云a打印出来:
cout << "Cloud A:" << endl;
for (size_t i = 0; i < cloud_a.points.size(); ++i) {
cout << " " << cloud_a.points[i].x << " " << cloud_a.points[i].y << " " << cloud_a.points[i].z << endl;
}
//如果是字段拼接
if (isCatField) {
//先初始化Normal类型点云n_cloud_b;
//字段拼接的话,要确保两个点云个数相同
n_cloud_b.width = cloud_a.width;//等于cloud_a的个数
n_cloud_b.points.resize(n_cloud_b.width*n_cloud_b.height);
for (size_t i = 0; i < n_cloud_b.points.size(); ++i) {
n_cloud_b.points[i].normal[0] = 1024 * rand() / (RAND_MAX + 1.0f);;
n_cloud_b.points[i].normal[1] = 1024 * rand() / (RAND_MAX + 1.0f);;
n_cloud_b.points[i].normal[2] = 1024 * rand() / (RAND_MAX + 1.0f);;
}
//先把点云b打印出来:
cout << "Cloud B:" << endl;
for (size_t i = 0; i < n_cloud_b.points.size(); ++i) {
cout << " " << n_cloud_b.points[i].normal[0] << " " << n_cloud_b.points[i].normal[1] << " " << n_cloud_b.points[i].normal[2] << endl;
}
//使用字段连接函数concatenateFields
pcl::concatenateFields(cloud_a, n_cloud_b, p_n_cloud_c);
//把拼接的点云输出
cout << "Cloud C:(字段拼接)" << endl;
for (size_t i = 0; i < p_n_cloud_c.points.size(); ++i) {
cout << " "<<p_n_cloud_c.points[i].x<<" "<<p_n_cloud_c.points[i].y << " " << p_n_cloud_c.points[i].z << " "
<< p_n_cloud_c.points[i].normal[0] << " " << p_n_cloud_c.points[i].normal[1] << " " << p_n_cloud_c.points[i].normal[2] << " " << endl;
}
}
//如果是点云数据拼接
else {
//先初始化cloud_b点云
//数据拼接,点数可以不一样,但是字段要一致
cloud_b.width = 3;
cloud_b.points.resize(cloud_b.width*cloud_b.height);
for (size_t i = 0; i < cloud_b.points.size(); ++i)
{
cloud_b.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_b.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud_b.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
}
//先把点云b打印出来:
cout << "Cloud B:" << endl;
for (size_t i = 0; i < cloud_b.points.size(); ++i) {
cout << " " << cloud_b.points[i].x << " " << cloud_b.points[i].y << " "<< cloud_b.points[i].z << endl;
}
//数据拼接,直接赋值,做加法
cloud_c = cloud_a;
cloud_c += cloud_b;
//把结果打印出来
cout << "Cloud C:(数据拼接)" << endl;
for (size_t i = 0; i < cloud_c.points.size(); ++i) {
cout << " " << cloud_c.points[i].x << " " << cloud_c.points[i].y << " " << cloud_c.points[i].z << endl;
}
}
return(0);
}
程序调用方式一,在VS中通过输入命令参数,实现控制:
程序调用方式二,在cmd命令行中直接调用生成的exe文件:
字段拼接:
数据拼接: