点云切割代码实现

目的

将文件夹下点云文件在x,y维度按照自定义的步长(step)切割成点云块并重新保存新的点云文件并稀释。

环境配置

c++ pcl库

代码实现

切割部分

#include<iostream>
#include<pcl/io/pcd_io.h>
#include<pcl/point_types.h>
#include<cmath>
#include<unordered_map>
#include<vector>
#include<dirent.h>

using namespace std;

unordered_map<string , pcl::PointCloud<pcl::PointXYZ>>umap;
//切割点云
void division(string filename , int batch){
    
    
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    string pwdfilename = "../input/" + filename;
    if(pcl::io::loadPCDFile<pcl::PointXYZ>(pwdfilename,*cloud) == -1){
    
    
        PCL_ERROR("can't open pcd file");
        return;
    }
    int a ,b;
    for (size_t i = 0; i < cloud->size(); ++i) {
    
    
        a = floor(cloud->points[i].x / batch);
        b = floor(cloud->points[i].y / batch);
        string cloudname = "x"+to_string(a)+"_y"+to_string(b);
        umap[cloudname].push_back({
    
    cloud->points[i].x , cloud->points[i].y , cloud->points[i].z});
    }
}
int main(int argc, char *argv[])
{
    
    
    int batch  = stoi(argv[1]);	//输入batch每个点云块的大小
    cout << "batch size = " << batch << endl;
	string PATH = argv[2];		//输入原点云文件夹的路径
	
	//读取文件夹下所有文件
    struct dirent *ptr;
    DIR *dir;
    dir = opendir(PATH.c_str());
    vector<string>files;
    while ((ptr=readdir(dir)) != NULL){
    
    
        if(ptr->d_name[0] == '.') continue;
        files.push_back(ptr->d_name);
    }
    closedir(dir);
    for (int i = 0; i < files.size(); ++i)
    {
    
    
        cout << files[i] << endl;
        division(files[i] , batch);
    }
    //切割后的点云保存到输出路路径
    for(auto it : umap){
    
    
        pcl::io::savePCDFileASCII("/home/houyiliang/pointclouds_cut/output/"+it.first + ".pcd" , it.second);
    }
    return 0;
}

稀释部分

在这里插入代码片#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
using namespace std;

void filter(string filename , float leafsize){
    
    
  pcl::PCLPointCloud2::Ptr cloud (new pcl::PCLPointCloud2 ());
  pcl::PCLPointCloud2::Ptr cloud_filtered (new pcl::PCLPointCloud2 ());
  // 填入点云数据
  pcl::PCDReader reader;
  // 把路径改为自己存放文件的路径
  string pwdfilename = "../output/" + filename;
  reader.read (pwdfilename, *cloud); // 记住要事先下载这个数据集!
  std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height 
       << " data points (" << pcl::getFieldsList (*cloud) << ").";
  // 创建滤波器对象
  pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
  sor.setInputCloud (cloud);
  sor.setLeafSize (leafsize, leafsize, leafsize);// 单位:m
  sor.filter (*cloud_filtered);
  std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height 
       << " data points (" << pcl::getFieldsList (*cloud_filtered) << ")." << endl;
  pcl::PCDWriter writer;
  string outputfilename = "../output_filter/" + filename + "_filter.pcd";
  writer.write (outputfilename, *cloud_filtered, 
         Eigen::Vector4f::Zero (), Eigen::Quaternionf::Identity (), false);

}
main (int argc, char** argv)
{
    
    
    float leafsize  = atof(argv[1]);	//稀释块大小
    struct dirent *ptr;
    DIR *dir;
    string PATH = argv[2];		//输出路径
    dir = opendir(PATH.c_str());
    vector<string>files;
    while ((ptr=readdir(dir)) != NULL){
    
    
        if(ptr->d_name[0] == '.') continue;//linux下跳过.开头的文件
        files.push_back(ptr->d_name);
    }
    cout <<  "total " << files.size() << endl;
    for (int i = 0; i < files.size(); ++i)
    {
    
    
        cout << files[i] << endl;
        filter(files[i] , leafsize);
    }

    closedir(dir);
  return (0);
}

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(cut)

find_package(PCL REQUIRED)
include_directories(${
    
    PCL_INCLUDE_DIRS})
link_directories(${
    
    PCL_LIBRARY_DIRS})

add_definitions(${
    
    PCL_DEFINITIONS})

add_executable(pointclouds_cut pointclouds_cut.cpp)
target_link_libraries (pointclouds_cut ${
    
    PCL_LIBRARIES})

add_executable(filter_pointclouds filter_pointclouds.cpp)
target_link_libraries (filter_pointclouds ${
    
    PCL_LIBRARIES})

执行

切割

 ./pointclouds_cut 50 ../input/ ../outpt/

参数释义:
argv[1]:50 表示x,y以50(m)切割
argv[2]: …/input 原始点云的输入路径
argv[3]: …/output 切割后输出点云的路径

稀释

 ./pointclouds_cut 0.2 ../output_filter/ ../output/

参数释义:
argv[1]:0.2 稀释块大小
argv[2]: …/output/ 要被稀释点云的路径(这里要稀释的是切割后段云的路径,所以是切割部分的输出路径)
argv[3]: …/output_filter/ 稀释后点云的输出路径

效果图

原始点云图
在这里插入图片描述
切割后
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43200940/article/details/127803572
今日推荐