引用转载
https://www.cnblogs.com/li-yao7758258/p/6659451.html
https://blog.csdn.net/liukunrs/article/details/80319952?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~Rate-1-80319952-blog-125647921.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~Rate-1-80319952-blog-125647921.pc_relevant_vip_default&utm_relevant_index=1
https://blog.csdn.net/qq_30815237/article/details/86509741
https://blog.csdn.net/weixin_42269667/article/details/117130170
内容包括
①关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud
②点云对象的两种定义方式的区别与转换
(1) 关于pcl::PointCloud
pcl::PointXYZ::PointXYZ ( float_x,
float_y,
float_z
)
struct PCLPointCloud2
{
PCLPointCloud2 () : header (), height (0), width (0), fields (),
is_bigendian (false), point_step (0), row_step (0),
data (), is_dense (false)
{
#if defined(BOOST_BIG_ENDIAN)
is_bigendian = true;
#elif defined(BOOST_LITTLE_ENDIAN)
is_bigendian = false;
#else
#error "unable to determine system endianness"
#endif
}
::pcl::PCLHeader header;
pcl::uint32_t height;
pcl::uint32_t width;
std::vector< ::pcl::PCLPointField> fields;
pcl::uint8_t is_bigendian;
pcl::uint32_t point_step;
pcl::uint32_t row_step;
std::vector<pcl::uint8_t> data;
pcl::uint8_t is_dense;
public:
typedef boost::shared_ptr< ::pcl::PCLPointCloud2> Ptr;
typedef boost::shared_ptr< ::pcl::PCLPointCloud2 const> ConstPtr;
}; // struct PCLPointCloud2
要实现它们之间的数据转换
pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);//申明滤波前后的点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_p (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
// 读取PCD文件
pcl::PCDReader reader;
reader.read ("table_scene_lms400.pcd", *cloud_blob);
//统计滤波前的点云个数
std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl;
// 创建体素栅格下采样: 下采样的大小为1cm
pcl::VoxelGrid<pcl::PCLPointCloud2> sor; //体素栅格下采样对象
sor.setInputCloud (cloud_blob); //原始点云
sor.setLeafSize (0.01f, 0.01f, 0.01f); // 设置采样体素大小
sor.filter (*cloud_filtered_blob); //保存
// 转换为模板点云
pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);//我的理解是通过转化使cloud_filtered_blob转变成的形式存储到cloud_filtered
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;
// 保存下采样后的点云
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered);
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;
// 保存下采样后的点云
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
**上述代码通过pcl::fromPCLPointCloud2 (cloud_filtered_blob, cloud_filtered);实现了两者的数据转化
Ⅰ
void pcl::fromPCLPointCloud(const pcl:PCLPointCloud2 & msg pcl::PointCloud<PointT>
& cloud const MsgFieldMap & filed_map )
函数使用field_map实现将一个pcl::pointcloud2二进制数据blob到PCL::PointCloud对象
使用 PCLPointCloud2 (PCLPointCloud2, PointCloud)生成自己的 MsgFieldMap
*上述应该还是说的之前的转换那个意思 *后面再想想
MsgFieldMap field_map;
createMapping<PointT> (msg.fields, field_map);
Ⅱ
void pcl::fromPCLPointCloud2(const pcl::PCLPointCloud
& msg pcl::PointCloud<pointT> &cloud)
把pcl::PCLPointCloud数据格式的点云转化为pcl::PointCloud< pointT >格式
定义点云的数据格式及调试代码遇到的问题
typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
PointCloudT::Ptr cloud_;
对比下 点云的定义
typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT
PointCloudT::Ptr cloud (new PointCloudT);
PointCloudT::Ptr cloud_filtered (new PointCloudT)
对比我们可以看出,这里两种定义的方法的不同。
PointCloudT::Ptr cloud_;
PointCloudY::Ptr cloud_tmp(new PointCloudT)
在构造上的区别:常规变量定义不使用new,定义的对象在定义后就自动可以使用,指针变量定义必须使用new进行对象实例的构造。
使用上的区别:使用new的是一个指针对象,此时对对象成员的访问需要使用指针操作符“->”,而不使用new的是常规对象,使用普通成员操作符“.”。
两者如何去转换
pcl::copyPointCloud (*cloud_tmp, *cloud_);
第一种,是一种vector的赋值方式,将point数据push_back到pcl::PointXYZ类型的模板中。
pcl::PointCloud<pcl::PointXYZ> pointCloud;
pcl::PointXYZ point;
point.x = 2.0f - y;
point.y = y;
point.z = z;
pointCloud.points.push_back(point);
第二种,指针型类模板,采用“->points[i]”方式赋值。
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
for (int i = 0; i < cloud->points.size (); ++i)
{
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::PointCloud::Ptr和pcl::PointCloud可以相互转换
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPtr(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ> cloud;
cloud = *cloudPtr;//由Ptr转变为另一种类型
cloudPtr = cloud.makeShared();//转变为Ptr类型
cloud.makeShared()解释
pcl::PointCloud.makeshared()返回的是一个对当前点云深度复制后的对象的智能指针,
也就是说
pcl::PointCloud cloud;
pcl::PointCloud::Ptr p= cloud.makeshared();
p并不指向cloud的空间,而是先深度拷贝了cloud放在新空间,然后返回指向该空间的指针。
通过p来操作点云,cloud不会改变。
所以用pcl定义点云的时候多用pcl::PointCloud::Ptr p(new pcl::PointCloud)吧,传指针减少开销,还不会因为在传指针的时候因为makeshared被坑。
pcl::PointCloud::Ptr和pcl::PointCloud两种对象,在操作shang是会有所不同
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("E:\\test_PCL\\pipline.pcd",*cloud) == -1)
pcl::PointCloud<pcl::PointXYZ> cloud;
pcl::io::loadPCDFile("E:\\test_PCL\\pipline.pcd",cloud) == -1)
且kdtree和octree类中的setInputCloud()函数只支持Ptr类型,如果点云对象不是Ptr类型,需要进行类型转换。
以下为实例
#include
#include
#include
#include
#include
#include
using namespace std;
void VisualizeCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& filter_cloud) { //定义一个可视化的函数 注意传参数的类型
//-----------------------显示点云-----------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("显示点云"));
int v1(0), v2(0), v3(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("point clouds", 10, 10, "v1_text", v1);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.1, 0.1, 0.1, v2);
viewer->addText("filtered point clouds", 10, 10, "v2_text", v2);
// 按照z字段进行渲染,将z改为x或y即为按照x或y字段渲染
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");
viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud", v1);
viewer->addPointCloud<pcl::PointXYZ>(filter_cloud, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud_out", v3);
//viewer->addCoordinateSystem(1.0);
//viewer->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int main() {
pcl::PCLPointCloud2::Ptr cloud(new pcl::PCLPointCloud2());
pcl::PointCloud<pcl::PointXYZ>::Ptr p(new pcl::PointCloud<pcl::PointXYZ>); //多定义两个p/q便于类型转换
pcl::PointCloud<pcl::PointXYZ>::Ptr q(new pcl::PointCloud<pcl::PointXYZ>);
/*pcl::PointCloud::Ptr cloud(new pcl::PointCloud);*/
pcl::PCDReader reader;
reader.read("C:\\Users\\Administrator\\Desktop\\plot1.pcd", *cloud);
//pcl::io::loadPCDFile("C:\\Users\\Administrator\\Desktop\\data\\shumu.pcd", *cloud);//读取pcd
pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2()); //现创建后续备用
//先进行降采样,减少计算压力;
std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
<< " data points (" << pcl::getFieldsList(*cloud) << ")." << std::endl;//计算点云数量
// Create the filtering object
//设置体素滤波器
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud(cloud); //输入点云
sor.setLeafSize(0.5f, 0.5f, 0.5f); //体素滤波器,单位m
sor.filter(*cloud_filtered); //滤波后的点云
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
<< " data points (" << pcl::getFieldsList(*cloud_filtered) << ")." << std::endl;
pcl::PCDWriter writer;
writer.write("C:\\Users\\Administrator\\Desktop\\plot5.pcd", *cloud_filtered);
pcl::fromPCLPointCloud2(*cloud , *p); //转换类型,将pcl::PCLPointCloud2转变成pcl::PointXYZ,以便适应传参数的需要
pcl::fromPCLPointCloud2(*cloud_filtered, *q);
VisualizeCloud(p, q);
}