点云处理基础操作

21 篇文章 0 订阅
8 篇文章 3 订阅

点云定义(还是点云指针定义?一直搞不懂)

//常用
typedef pcl::PointXYZRGBA PointT;
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
//两个一起定义:pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>), cloud_f(new pcl::PointCloud<PointT>);

pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);//带法线的点云
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);//法线

1. 读取和保存点云

这两种方法不知道有什么区别,先记下来吧
法一:

#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
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 <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>

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 <string>
#include <iostream>
#include <pcl/io/pcd_io.h> 
#include <pcl/io/ply_io.h>

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);
	}

注意!

批量处理点云时会出现定义新点云以及赋值的问题,这里一定要注意在赋值时先给他一个空间,否则如果只是一个指针的话很容易报错,什么指针溢出啥的,最后处理完成一定要设置好点云的长宽来保存点云
在这里插入图片描述

2. 定义一个新的点云

*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;

创建新点云并且给它赋值:

pcl::PointCloud<pcl::PointXYZ>::Ptr centorid_points(new pcl::PointCloud<pcl::PointXYZ>);

	for (int i = 0; i < numberOfViews; i++)
	{
		pcl::PointXYZ point; 
		Eigen::Vector4f centroid;					// 质心
		pcl::compute3DCentroid(*data1[i].cloud, centroid);	// 齐次坐标,(c0,c1,c2,1)
		point.x = centroid(0); //这里直接给点云赋值(centorid_points->points[i].x=centroid(0);)是不行的,要先给点赋值,然后再把点push_back到点云中
		point.y = centroid(1);
		point.z = centroid(2);
		//cout << centroid(0)<<endl;
		centorid_points->points.push_back(point);
	}
	centorid_points->height = 1;
	centorid_points->width = numberOfViews;
	centorid_points->is_dense = false;

有序点云的保存

	pcl::PointCloud<pcl::PointXYZ> newcloud;
	newcloud.width = 424;
	newcloud.height = 512;
	newcloud.points.resize(newcloud.width*newcloud.height);//要加这个,否则会报错
	newcloud.is_dense = false;//点云中有NAN值,若没有则true,或者说数值是有限则是true
	for (int i = 0; i < cloud->size(); i++)
	{
		newcloud.points[i].x = cloud->points[i].x;
		newcloud.points[i].y = cloud->points[i].y;
		newcloud.points[i].z = cloud->points[i].z;
		/*std::cout << i << endl;*/
	}
	pcl::io::savePLYFile("newcloud.ply", newcloud);

3. 去除NAN点

#include <pcl/filters/extract_indices.h>  
#include <pcl/filters/filter.h>  //这两个任意一个头文件好像就可以
//去除NAN点
	std::vector<int> mapping;
	pcl::removeNaNFromPointCloud(*pcloud, *pcloud, mapping);
	std::cout << "原始点云去除NaN点后数量: " << pcloud->points.size() << std::endl;

注意这里如果是复制的指针,去除之前一定要先保存点云,否则没啥效果

	pcl::copyPointCloud(*source_key_Neigh, *source_key_Neighbors);
	for (int n = 0; n < source_key_Neigh->size(); n++)
	{
		for (int m = 0; m < source_key_Neigh->size(); m++)
		{
			if ((source_key_Neigh->points[n].x == source_key_Neighbors->points[m].x) && (source_key_Neigh->points[n].y == source_key_Neighbors->points[m].y) && (source_key_Neigh->points[n].z == source_key_Neighbors->points[m].z) && (m != n))
			{
				source_key_Neighbors->points[m].x = NAN;
				source_key_Neighbors->points[m].y = NAN;
				source_key_Neighbors->points[m].z = NAN;
			}
		}
	}
	// 设置并保存点云***********保存这里很重要
	source_key_Neighbors->height = 1;
	source_key_Neighbors->width = source_key_Neighbors->points.size();
	source_key_Neighbors->is_dense = false;
	//去除NAN点
	std::vector<int> mapping;
	pcl::removeNaNFromPointCloud(*source_key_Neighbors, *source_key_Neighbors, mapping);

4. 遍历点云

C++里,是编号是从0开始

for (int n = 0; n < source_key_Neigh->size(); n++)
	{
		for (int m = 0; m < source_key_Neigh->size(); m++)
		{
			if ((source_key_Neigh->points[n].x == source_key_Neighbors->points[m].x) && (source_key_Neigh->points[n].y == source_key_Neighbors->points[m].y) && (source_key_Neigh->points[n].z == source_key_Neighbors->points[m].z) && (m != n))
			{
				source_key_Neighbors->points[m].x = NAN;
				source_key_Neighbors->points[m].y = NAN;
				source_key_Neighbors->points[m].z = NAN;
			}
		}
	}

matlab里编号是从1 开始

ptCloud = pcread('source_key_Neigh.ply');
location=ptCloud.Location;
x = location(:,1);
y = location(:,2);
z = location(:,3);
location1=location;
x1=x;
y1=y;
z1=z;
for i=1:size(x)
    for j=1:size(x)
        if((x1(j)==x(i))&&(y1(j)==y(i))&&(z1(j)==z(i))&&(i~=j))
            location1(j,1)=nan;
            location1(j,2)=nan;
            location1(j,3)=nan;
        end
    end
end
location1(all(isnan(location1), 2),:) = [];

5. 查看点云点数

#include <pcl/ModelCoefficients.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>


using namespace std;
typedef pcl::PointXYZRGBA PointT;

int main()
{
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZRGB>);
	std::string prefix("2020-10-14-15-19-55_ConditionAnd_RadiusOutlierRemoval");
	std::string extension(".ply");
	std::string fname = prefix + extension;
	if (pcl::io::loadPLYFile<pcl::PointXYZRGB>(fname, *cloud) == -1) //* load the file 
	{
		PCL_ERROR("Couldn't read file. \n");
		system("PAUSE");
		return (-1);
	}
	std::cout << cloud->size() << endl;

	std::system("pause");
	return 0;
}
  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值