**
PCL代码学习
网上找的原文地址
**
1. 写入PCD文件
主要:
<pcl/io/pcd_io.h>
<pcl/point_types.h>
pcl::PointCloudpcl::PointXYZcloud;
pcl::io::savePCDFileASCII(“test_pcd.pcd”, cloud);
#include<iostream>
#include<pcl/io/pcd_io.h>
//pcd 读写类相关头文件
#include<pcl/point_types.h>
//pcl中支持的点类型头文件
int main()//看书打代码的时候忘了写main函数,有错误
{
pcl::PointCloud<pcl::PointXYZ>cloud;
//描述将要实例化的模板类PointCloud,每一个点的类型都被设置成pcl::PointXYZ,作为模板类实例化的参数
cloud.width = 5;
cloud.height = 1;
cloud.is_dense = false;
cloud.points.resize(cloud.width * cloud.height);
for (size_t i = 0; i < cloud.points.size(); ++i)//书上是size_ti=0,typedef undesigned long long size_t
{
cloud.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
}
pcl::io::savePCDFileASCII("test_pcd.pcd", cloud);//保存地址,与源文件一个文件夹
std::cout << "Saved " << cloud.points.size() << " data points to test_pcd.pcd." << std::endl;
for (size_t i = 0; i < cloud.points.size(); ++i)//输出点云xyz值
{
std::cerr << " " << cloud.points[i].x << " " << cloud.points[i].y << " " << cloud.points[i].z << std::endl;
}
return(0);
}
2.读取PCD文件
pcl::PointCloudpcl::PointXYZ::Ptr cloud(new pcl::PointCloud pcl::PointXYZ);
pcl::io::loadPCDFilepcl::PointXYZ(“test_pcd.pcd”, *cloud)
#include<iostream>
#include<pcl/io/pcd_io.h>
//pcl读写类相关头文件
#include<pcl/point_types.h>
//pcl支持的点类型头文件
int main()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
//创建了一个PointCloud<pcl::PointXYZ> boost共享指针并进行实例化
if (pcl::io::loadPCDFile<pcl::PointXYZ>("test_pcd.pcd", *cloud)== -1)//if判断时候就已经执行了
{
PCL_ERROR("不能载入文件test_pcd.pcd\n");
return(-1);
//现在如果有文件已经读入了,cloud存储其地址
//点类型为默认二进制块读取转换为模块化的PointCLoud格式里pcl::PointXYZ
}
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);
}
3. 合并两个点云形成点云
原本是用字符串数组argv[1]决定用哪个连接,但是运行的时候出错:istream的_Str读取字符串时出错0xcccccccccccccccc
网上说是数组越界,这个问题没搞明白,换成数字就好了。
#include<iostream>
#include<pcl/io/pcd_io.h>
#include<pcl/point_types.h>
//两种合并:点与点,点与向量
int main()
{
int argv;//数组,用于判断使用哪种合并方式
std::cout << "输入选择,‘1’为点与点,‘2’为点与向量连接" << std::endl;
std::cin >> argv;
pcl::PointCloud<pcl::PointXYZ>cloud_a, cloud_b, cloud_c;//声明三个pcl::PointXYZ点云类型
pcl::PointCloud<pcl::Normal>n_cloud_b;//存储进行连接时需要的normal点云
pcl::PointCloud<pcl::PointNormal>p_n_cloud_c;//存储连接XYZ与Normal后的点云
//接下来创建点云数据
cloud_a.width = 3;//cloud_a点个数为3
cloud_a.height = cloud_b.height = n_cloud_b.height = 1;//都为无序点云
cloud_a.points.resize (cloud_a.width * cloud_a.height);
//填充两种点云类型
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;
}
if (argv == 1)
{
cloud_b.width = 2;
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;
}
cloud_c = cloud_a;
cloud_c += cloud_b;
for (size_t i = 0; i < cloud_c.points.size(); ++i)
{
std::cout << "cloud_c" << cloud_c.points[i].x <<" "<< cloud_c.points[i].y <<" "<< cloud_c.points[i].z << std::endl;
}
}
else
{
n_cloud_b.width = 3;
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;
}
pcl::concatenateFields(cloud_a, n_cloud_b, p_n_cloud_c);
for (size_t i = 0; i < p_n_cloud_c.points.size(); ++i)
{
std::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] << std::endl;
}
}
}
4. 在点云中加入高斯噪声
没明白高斯噪声怎么生成,之后看。。
在13行处,如果没有括号,就会提示:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误(活动) E0300 指向绑定函数的指针只能用于调用函数 PCL_Debug C:\Users\one\Desktop\PCL_Debug\PCL_Debug\源.cpp 13
在size后面加上()成功运行
这是因为调用的是函数,要加上括号。
#include<pcl/point_types.h>
#include<pcl/point_cloud.h>
#include<iostream>
#include <pcl/console/time.h>
#include <boost/random.hpp>
int main()
{
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
//创建了一个PointCloud<pcl::PointXYZ> boost共享指针并进行实例化
cloud->width = 100;
cloud->height = 1;
cloud->points.resize(cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size(); ++i)
{
cloud->points[i].x = 1000.0f * rand() / (RAND_MAX + 1.0f);
cloud->points[i].y = 1000.0f * rand() / (RAND_MAX + 1.0f);
cloud->points[i].z = 1000.0f * rand() / (RAND_MAX + 1.0f);
}
//添加高斯噪声,范围(0-0.01)
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudfiltered(new pcl::PointCloud<pcl::PointXYZ>());
cloudfiltered->points.resize(cloud->points.size());
cloudfiltered->header = cloud->header;
cloudfiltered->width = cloud->width;
cloudfiltered->height = cloud->height;
boost::mt19937 rng;
rng.seed(static_cast<unsigned int> (time(0)));
boost::normal_distribution<> nd(0, 0.01);
boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > var_nor(rng, nd);
for (size_t point_i = 0; point_i < cloud->points.size(); ++point_i)
{
cloudfiltered->points[point_i].x = cloud->points[point_i].x + static_cast<float> (var_nor());
cloudfiltered->points[point_i].y = cloud->points[point_i].y + static_cast<float> (var_nor());
cloudfiltered->points[point_i].z = cloud->points[point_i].z + static_cast<float> (var_nor());
}
return 0;
}
5. 使用kdtree(k近邻搜索和半径搜索)
#include <pcl/point_cloud.h>//点类型定义头文件
#include <pcl/kdtree/kdtree_flann.h>//kdtree类定义头文件
#include<iostream>
#include<vector>
#include<ctime>
int main(int argc, char** argv)
{
srand(time(NULL));//用系统时间初始化随机种子
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
//创建一个PointCloud<pcl::PointXYZ>..
//pcl 是一个命名空间,跟std类似,
//PointCloud是类模板,
//<pcl::PointXYZ>是模板类实例化的类型
//PointCloud<pcl::PointXYZ>就是一个实例化了的模板类
//ptr是智能指针,相当于之前普通指针声明的*,
//cloud是指针变量,就是一个指向PointCloud<pcl::PointXYZ>类对象的指针
//new pcl::PointCloud<pcl::PointXYZ>就是给了一个地址初始化指针
//随机点云生成
cloud->width = 1000;//点云数量
cloud->height = 1;//无序点云
cloud->points.resize(cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size(); ++i)//循环填充点云数据
{
cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f);
cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);
cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);
}
//创建kdtreeFLANN对象,并把创建的点云设置为输入,创建一个searchPoint变量作为查询点
pcl::KdTreeFLANN<pcl::PointXYZ> kdtree;//创建kd-tree对象
kdtree.setInputCloud(cloud);//设置搜索空间
pcl::PointXYZ searchPoint;//设置查询点并附随机值
searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f);
searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f);
searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);
//k近邻搜索
//创建一个整数(设置为10)和两个向量来存储搜索到的k近邻,两个向量中,一个存储搜索到查询点近邻的索引,另一个存储对应近邻的距离平方
int K = 10;
std::vector<int> pointIdxNKNSearch(K);//存储查询点近邻索引,定义向量pointTdxNKNSearch
std::vector<float> pointNKNSquaredDistance(K);//存储近邻点对应距离平方,定义向量pointNKNSquareDistance
std::cout << "K nearest neighbor search at(" << searchPoint.x
<< "," << searchPoint.y
<< "," << searchPoint.z
<< ") with K=" << K << std::endl;//打印查询点的信息
//假设kd-tree对象返回了多余0个近邻,搜索结果已经存储在之前创建的两个向量pointTdxNKNSearch和pointNKNSquareDistance中,并把所有10个紧邻的位置打印出来
if(kdtree.nearestKSearch(searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance)>0);//执行k近邻搜索
{
for (size_t i = 0; i < pointIdxNKNSearch.size(); ++i)
std::cout << cloud->points[pointIdxNKNSearch[i]].x
<< "," << cloud->points[pointIdxNKNSearch[i]].y
<< "," << cloud->points[pointIdxNKNSearch[i]].z
<< "square distance:" << pointNKNSquaredDistance[i] << ")" << std::endl;
}
//下面代码展示查找到给定searchPoint的某一半径(随机产生)内的所有近邻,重新定义两个向量
//pointIdxRadiusSearch和pointSquareRadiusDistance来存储关于近邻的信息
std::vector<int>pointIdxRadiusSearch;//存储近邻索引
std::vector<float>pointSquareRadiusDistance;//存储近邻对应的距离平方
float radius = 256.0f * rand() / (RAND_MAX + 1.0f);
std::cout << "distance<radius=" << radius << std::endl;
//像之前一样,如果kd-tree对象在指定半径内返回返回多余0个近邻,他将打印输出向量中存储的点的坐标与距离
if (kdtree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointSquareRadiusDistance) > 0)
{
for (size_t i = 0; i < pointIdxRadiusSearch.size(); ++i)
{
std::cout << cloud->points[pointIdxRadiusSearch[i]].x << "," << cloud->points[pointIdxRadiusSearch[i]].y << "," << cloud->points[pointIdxRadiusSearch[i]].z<< "(squared distance:" << pointSquareRadiusDistance[i] << ")" << std::endl;
}
}
}