使用PCL对PCD文件进行简单读、写和拼接(数据拼接和字段拼接)操作

创建一个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文件:

字段拼接:

数据拼接: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SOC罗三炮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值