读取并显示.pcd/.ply/.txt/.bin/.stl格式的点云

1. 读取显示.pcd/.ply格式的点云

  • 通过loadPCDFile/loadPLYFile或者loadPLYFile/PLYReader来载入点云数据
  • pcd格式
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
//1.直接载入 实际上loadPCDFile调用PCDReader实现
pcl::PointCloud<PointXYZ >::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("tree.pcd", *cloud);
//2.创建点云对象读取
pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2 ());
pcl::PCDReader reader;
reader.read ("cat.pcd", *cloud); 
  • ply格式
#include <iostream>
#include <pcl/io/ply_io.h> 
#include <pcl/point_types.h>
//1.直接载入
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPLYFile <pcl::PointXYZ>("tree.pcd", *cloud);
//2.创建点云对象读取
pcl::PCLPointCloud2::Ptr cloud_blob(new pcl::PCLPointCloud2);
pcl::PLYReader reader;
reader.read("cat.pcd", *cloud);

  • 以下均读取为点类型为PointXYZ的点云中,即在调用这些函数前cloud_为pcl::PointCloud<PointXYZ >::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

2. 读取显示.txt格式的点云

  • 将txt文件每一行的数据读入到点point中,再将点push_back到点云中
  • 注意此处适用于每行中点的数据以空格分割的数据,以逗号分割的稍有不同(有空补充)
  • cloudPath为txt文件路径
void readTxtCloud(std::string cloudPath)
{
    
    
	std::string line;
	pcl::PointXYZ point;
	std::ifstream txtfile(cloudPath.c_str());
	if(!txtfile)
	{
    
    
	    std::cout<<"open txt file fail"<<std::endl;
	}
	while(getline(txtfile, line))
	{
    
    
	    std::stringstream ss(line);
	    //以空格分割遇到逗号结束
	    ss >> point.x;
	    ss >> point.y;
	    ss >> point.z;
	    cloud->push_back(point);
	}
	txtfile.close();
}

3. 读取显示.bin格式的点云

  • 此处读取过程中直接舍弃了intensity强度信息(将其存到a里),保存点x,y,z坐标到点类型为PointXYZ的点云中
void readBinCloud(std::string cloudPath)
{
    
    
   pcl::PointXYZ point;
   float a=0;
   std::ifstream binfile(cloudPath.c_str(),ios::in|ios::binary);
   if(!binfile.good())
   {
    
    
       std::cout<<"open bin file fail"<<std::endl;
   }
   for(int i=0;binfile.good()&&!binfile.eof();i++)
   {
    
    
       binfile.read((char *)&point.x,3*sizeof (float));
       binfile.read((char *)&a,sizeof (float));
       cloud->push_back(point);
   }
   binfile.close(); 
}

4. 读取显示.stl格式的点云

  • 首先通过vtkSTLReader读取.stl点云,将其转换为Poly格式再转换为pcl::PointCloud
void readStlCloud(std::string cloudPath)
{
    
    
	vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
	reader->SetFileName(cloudPath.c_str());
	reader->Update();
	vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
	polydata = reader->GetOutput();
	polydata->GetNumberOfPoints();
	pcl::io::vtkPolyDataToPointCloud(polydata,*cloud);
}

5. 读取.pcd/.ply/.txt/.bin/.stl任一格式的点云

  • 传入需要读取的点云数据的路径cloudPath,判断字符串的后缀名,分别对不同的后缀进行不同的读取方式
  • 由于读取.txt/.bin文件时是将点push_back到点云中的,所以加上了cloud->clear();清空点云,否则多次调用函数读取.txt/.bin会导致出现多片点云。
  • find_last_of表示从字符串右边开始寻找指定字符,返回该字符在最右处的索引值
  • substr,str.substr(size_t pos = 0, size_t len = npos)表示拷贝字符串str从pos开始的len个字符,pos不指定则从0开始拷贝,len不指定的话则默认从pos开始拷贝到字符串末尾
void readPointCloud(std::string cloudPath)
{
    
    
    cloud_->clear();
    //判断文件的后缀,以确定打开的方式
    if (cloudPath.substr(cloudPath.find_last_of('.')) == ".pcd")
    {
    
    
        try
        {
    
    
            pcl::io::loadPCDFile(cloudPath, *cloud);
        }
        catch(...)
        {
    
    
            std::cout << "load pcd file error" << std::endl;
        }
    }
    else if (cloudPath.substr(cloudPath.find_last_of('.')) == ".ply")
    {
    
    
        try
        {
    
    
            pcl::io::loadPLYFile(cloudPath,*cloud);
        }
        catch (...)
        {
    
    
            std::cout<<"load ply file error"<<std::endl;
        }
    }
    else if (cloudPath.substr(cloudPath.find_last_of('.')) == ".txt")
    {
    
    
        try
        {
    
    
            std::string line;
            pcl::PointXYZ point;
            std::ifstream txtfile(cloudPath.c_str());
            if(!txtfile)
            {
    
    
                std::cout<<"open txt file fail"<<std::endl;
            }
            while(getline(txtfile, line))
            {
    
    
                std::stringstream ss(line);
                //以空格分割遇到逗号结束
                ss >> point.x;
                ss >> point.y;
                ss >> point.z;
                cloud->push_back(point);
                std::cout<<point<<std::endl;
            }
            txtfile.close();
        }
        catch(...)
        {
    
    
           std::cout<<"load ply file error"<<std::endl;
        }
    }
    else if (cloudPath.substr(cloudPath.find_last_of('.')) == ".bin")
    {
    
    
        try
        {
    
    
            pcl::PointXYZ point;
            float a=0;
            std::ifstream binfile(cloudPath.c_str(),ios::in|ios::binary);
            if(!binfile.good())
            {
    
    
                std::cout<<"open bin file fail"<<std::endl;
            }
            for(int i=0;binfile.good()&&!binfile.eof();i++)
            {
    
    
                binfile.read((char *)&point.x,3*sizeof (float));
                binfile.read((char *)&a,sizeof (float));
                cloud->push_back(point);
            }
            binfile.close();
        }
        catch(...)
        {
    
    
            std::cout<<"load bin file error"<<std::endl;
        }
    }
    else if (cloudPath.substr(cloudPath.find_last_of('.')) == ".stl")
    {
    
    
        try
        {
    
    
            vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
            reader->SetFileName(cloudPath.c_str());
            reader->Update();
            vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
            polydata = reader->GetOutput();
            polydata->GetNumberOfPoints();
            pcl::io::vtkPolyDataToPointCloud(polydata,*cloud);
        }
        catch(...)
        {
    
    
            std::cout<<"load stl file error"<<std::endl;
        }
    }
    //对读取到的点云保存为pcd格式
    pcl::io::savePCDFile<pcl::PointXYZ>("wind.pcd", *cloud);
}

6. 显示上述格式的点云数据

  • 调用显示函数showPointCloud前,先调用readPointCloud函数读入点云
void showPointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    
    
    //显示点云前设置背景颜色,清空上次显示所有形状以及点云
    viewer->setBackgroundColor(0,0,0);
    viewer>removeAllShapes();
    viewer->removeAllPointClouds();
    viewer->removeAllCoordinateSystems();
    pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud,"z");
    viewer>addPointCloud<pcl::PointXYZ>(cloud,fildColor);
    //重设相机视角
    viewer->resetCamera();
}

猜你喜欢

转载自blog.csdn.net/m0_68312479/article/details/127660101