目的
将文件夹下点云文件在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/ 稀释后点云的输出路径
效果图
原始点云图
切割后