//常用
typedef pcl::PointXYZRGBA PointT;
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
//两个一起定义:pcl::PointCloud::Ptr cloud(new pcl::PointCloud), cloud_f(new pcl::PointCloud);
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);//带法线的点云
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);//法线
这两种方法不知道有什么区别,先记下来吧
法一:
#include
#include
typedef pcl::PointXYZRGBA PointT;
pcl::PCDReader reader;
pcl::PLYReader reader1;
reader.read("tree3.pcd", *cloud);
reader1.read("cow_final1_RORFed.ply", *cloud);
pcl::PCDWriter writer;
pcl::PLYWriter writer1;
writer.write<PointT> ("tree3.pcd", *every_cluster, false);
writer1.write<PointT> ("tree3.pcd", *every_cluster, false);
法二:
#include
#include
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); // 创建点云(指针)
if (pcl::io::loadPLYFile<pcl::PointXYZ>("2020- 6- 9-10-0passthrough.ply", *cloud) <0) //* 读入PLY格式的文件,如果文件不存在,返回-1
{
PCL_ERROR("Couldn't read file test_pcd.pcd \n"); //文件不存在时,返回错误,终止程序。
getchar();
return (-1);
}
pcl::io::savePLYFile("test.ply", *cloud, true);
string和stringstream区别:string和stringstream用法总结
//简单版批量存储
//(在for循环里面)
std::stringstream ss, ss1;
ss << "tree3_cluster_" << j << ".pcd";
ss1<< "tree3_cluster_" << j << ".ply";
writer.write<PointT> (ss.str (), *every_cluster, false);
writer1.write<PointT> (ss1.str(), *every_cluster, false);
j++;
结合结构体以及字符串对点云进行批量存取:
//复杂版批量读取点云和存储点云
#include
#include
#include
#include
string num2str(int i)
{
stringstream ss;
ss << i;
return ss.str();
}
//定义结构体,用于处理点云
struct PLY
{
std::string f_name; //文件名
pcl::PointCloud<pcl::PointNormal>::Ptr cloudWithNormal;//存储估计的法线的指针
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;//存储点云
//构造函数
PLY() : cloud(new pcl::PointCloud<pcl::PointXYZ>),cloudWithNormal(new pcl::PointCloud<pcl::PointNormal>){}; //初始化
};
int main()
{
const int numberOfViews = 6;//文件数量
std::vector<PLY, Eigen::aligned_allocator<PCD> > data; //点云数据
std::vector<PLY, Eigen::aligned_allocator<PCD> > data1; //点云数据
std::string prefix("cow1");
std::string extension("_withNormal_boundary.ply"); //声明并初始化string类型变量extension,表示文件后缀名
// 通过遍历文件名,读取ply文件
for (int i = 0; i < numberOfViews; i++) //遍历所有的文件名
{
std::string fname = prefix + num2str(i) + extension;
// 读取点云,并保存到models
PLY m;
m.f_name = fname;
if (pcl::io::loadPLYFile(fname, *m.cloud) == -1) //* 读入PCD格式的文件,如果文件不存在,返回-1
{
cout << "Couldn't read file " + fname + "." << endl; //文件不存在时,返回错误,终止程序。
return (-1);
}
data.push_back(m);
}
//这样之后data[i].cloud就代表一个点云,共六个
//批量存储点云
for (int i = 0; i < numberOfViews; ++i)
{
std::string fname = prefix + num2str(i) + "_rotate" + extension;
pcl::io::savePLYFile(fname, *data[i].cloudWithNormal, true);
}
return 0;
}
还可以批量进行其他操作,比如离群点滤波
//-----------------------去除离群点------------------------
std::vector<PCD, Eigen::aligned_allocator<PCD> > data1; //这里新定义了一个算是数组?好像滤波之后的点云不能重复赋值到这个数组里
pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
outrem.setRadiusSearch(0.01);
outrem.setMinNeighborsInRadius(5);
for (int i = 0; i < numberOfViews; ++i)
{
PLY a;//这里新定义了一个结构体
outrem.setInputCloud(data[i].cloud);
outrem.filter(*a.cloud);
data1.push_back(a);
}
*cloud是已知的点云
*newcloud是新点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr newcloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 创建点云(指针)
newcloud->height = cloud->height;//或者直接这个newcloud->height = 1;一般好像点云这个都是1
newcloud->width = cloud->width;//*cloud是已知的点云
newcloud->is_dense = false;
也可以直接复制点云
pcl::PointCloud<pcl::PointXYZRGB>::Ptr newcloud(new pcl::PointCloud<pcl::PointXYZRGB>); // 创建点云(指针)
pcl::copyPointCloud(*cloud, *newcloud);//把cloud复制给newcloud(然后就可以直接用newcloud了,里面就有相应点的坐标了,相当于把指针赋值了吧)
//一顿操作之后newcloud里面一些点被修改,需要保存起来,如下:
newcloud->height = 1;
newcloud->width = newcloud->points.size();
newcloud->is_dense = false;
//去除NAN点
std::vector<int> mapping;
pcl::removeNaNFromPointCloud(*pcloud, *pcloud, mapping);
std::cout << "原始点云去除NaN点后数量: " << pcloud->points.size() << std::endl;