admin 管理员组

文章数量: 887021

点云文件常用格式转换(pcd,txt,ply,obj,stl)

目录

    • pcd转txt
    • txt转pcd
    • pcd转ply
    • pcd转ply(三角网格化)
    • ply转pcd
    • obj/ply转pcd(均匀采样)
    • pcd转obj
    • stl转ply
    • ply转stl

pcd转txt

#include <iostream>
#include <fstream>
#include <pcl/io/pcd_io.h>   int main(int argc, char *argv[])
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile("rabbit.pcd", *cloud);std::ofstream outfile;outfile.open("rabbit.txt");for (size_t i = 0; i < cloud->points.size(); ++i){outfile << cloud->points[i].x << "\t" << cloud->points[i].y << "\t" << cloud->points[i].z << "\n";}return 0;
}

txt转pcd

#include <iostream>
#include <fstream>
#include <pcl/io/pcd_io.h>   int main(int argc, char *argv[])
{std::ifstream infile;infile.open("rabbit.txt");float x, y, z;pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);while (infile >> x >> y >> z){cloud->push_back(pcl::PointXYZ(x, y, z));}pcl::io::savePCDFileBinary("rabbit.pcd", *cloud);return 0;
}

pcd转ply

#include <iostream>          
#include <pcl/io/pcd_io.h>  
#include <pcl/point_types.h> 
#include <pcl/io/ply_io.h>  int main(int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile("rabbit.pcd", *cloud);pcl::io::savePLYFileBinary("rabbit.ply", *cloud);return 0;
}

pcd转ply(三角网格化)

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>  
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>using namespace std;int main(int argc, char** argv)
{// Load input filepcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile("rabbit.pcd", *cloud);// Normal estimation*pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);tree->setInputCloud(cloud);n.setInputCloud(cloud);n.setSearchMethod(tree);n.setKSearch(10);n.compute(*normals);//* normals should not contain the point normals + surface curvatures// Concatenate the XYZ and normal fields*pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);//* cloud_with_normals = cloud + normals// Create search tree*pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);tree2->setInputCloud(cloud_with_normals);// Initialize objectspcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;pcl::PolygonMesh triangles;// Set the maximum distance between connected points (maximum edge length)gp3.setSearchRadius(1);// Set typical values for the parametersgp3.setMu(2.5);gp3.setMaximumNearestNeighbors(100);gp3.setMaximumSurfaceAngle(M_PI / 4); // 45 degreesgp3.setMinimumAngle(M_PI / 18); // 10 degreesgp3.setMaximumAngle(2 * M_PI / 3); // 120 degreesgp3.setNormalConsistency(false);// Get resultgp3.setInputCloud(cloud_with_normals);gp3.setSearchMethod(tree2);gp3.reconstruct(triangles);pcl::io::savePLYFile("rabbit.ply", triangles);return 0;
}

ply转pcd

#include <iostream>          
#include <pcl/io/pcd_io.h>  
#include <pcl/point_types.h> 
#include <pcl/io/ply_io.h>  int main(int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPLYFile("rabbit.ply", *cloud);pcl::io::savePCDFileBinary("rabbit.pcd", *cloud);return 0;
}

obj/ply转pcd(均匀采样)

#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/common/transforms.h>
#include <vtkVersion.h>
#include <vtkPLYReader.h>
#include <vtkOBJReader.h>
#include <vtkTriangle.h>
#include <vtkTriangleFilter.h>
#include <vtkPolyDataMapper.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <vtkAutoInit.h>
#include <vtkRenderWindow.h>VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)inline double uniform_deviate(int seed)
{double ran = seed * (1.0 / (RAND_MAX + 1.0));return ran;
}inline void randomPointTriangle(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3, Eigen::Vector4f& p)
{float r1 = static_cast<float> (uniform_deviate(rand()));float r2 = static_cast<float> (uniform_deviate(rand()));float r1sqr = std::sqrt(r1);float OneMinR1Sqr = (1 - r1sqr);float OneMinR2 = (1 - r2);a1 *= OneMinR1Sqr;a2 *= OneMinR1Sqr;a3 *= OneMinR1Sqr;b1 *= OneMinR2;b2 *= OneMinR2;b3 *= OneMinR2;c1 = r1sqr * (r2 * c1 + b1) + a1;c2 = r1sqr * (r2 * c2 + b2) + a2;c3 = r1sqr * (r2 * c3 + b3) + a3;p[0] = c1;p[1] = c2;p[2] = c3;p[3] = 0;
}inline void randPSurface(vtkPolyData * polydata, std::vector<double> * cumulativeAreas, double totalArea, Eigen::Vector4f& p, bool calcNormal, Eigen::Vector3f& n)
{float r = static_cast<float> (uniform_deviate(rand()) * totalArea);std::vector<double>::iterator low = std::lower_bound(cumulativeAreas->begin(), cumulativeAreas->end(), r);vtkIdType el = vtkIdType(low - cumulativeAreas->begin());double A[3], B[3], C[3];vtkIdType npts = 0;vtkIdType *ptIds = NULL;polydata->GetCellPoints(el, npts, ptIds);polydata->GetPoint(ptIds[0], A);polydata->GetPoint(ptIds[1], B);polydata->GetPoint(ptIds[2], C);if (calcNormal){// OBJ: Vertices are stored in a counter-clockwise order by defaultEigen::Vector3f v1 = Eigen::Vector3f(A[0], A[1], A[2]) - Eigen::Vector3f(C[0], C[1], C[2]);Eigen::Vector3f v2 = Eigen::Vector3f(B[0], B[1], B[2]) - Eigen::Vector3f(C[0], C[1], C[2]);n = v1.cross(v2);n.normalize();}randomPointTriangle(float(A[0]), float(A[1]), float(A[2]),float(B[0]), float(B[1]), float(B[2]),float(C[0]), float(C[1]), float(C[2]), p);
}void uniform_sampling(vtkSmartPointer<vtkPolyData> polydata, size_t n_samples, bool calc_normal, pcl::PointCloud<pcl::PointNormal> & cloud_out)
{polydata->BuildCells();vtkSmartPointer<vtkCellArray> cells = polydata->GetPolys();double p1[3], p2[3], p3[3], totalArea = 0;std::vector<double> cumulativeAreas(cells->GetNumberOfCells(), 0);size_t i = 0;vtkIdType npts = 0, *ptIds = NULL;for (cells->InitTraversal(); cells->GetNextCell(npts, ptIds); i++){polydata->GetPoint(ptIds[0], p1);polydata->GetPoint(ptIds[1], p2);polydata->GetPoint(ptIds[2], p3);totalArea += vtkTriangle::TriangleArea(p1, p2, p3);cumulativeAreas[i] = totalArea;}cloud_out.points.resize(n_samples);cloud_out.width = static_cast<pcl::uint32_t> (n_samples);cloud_out.height = 1;for (i = 0; i < n_samples; i++){Eigen::Vector4f p;Eigen::Vector3f n;randPSurface(polydata, &cumulativeAreas, totalArea, p, calc_normal, n);cloud_out.points[i].x = p[0];cloud_out.points[i].y = p[1];cloud_out.points[i].z = p[2];if (calc_normal){cloud_out.points[i].normal_x = n[0];cloud_out.points[i].normal_y = n[1];cloud_out.points[i].normal_z = n[2];}}
}using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;const int default_number_samples = 1000000;
const float default_leaf_size = 1.0f;void printHelp(int, char **argv)
{print_error("Syntax is: %s input.{ply,obj} output.pcd <options>\n", argv[0]);print_info("  where options are:\n");print_info("                     -n_samples X      = number of samples (default: ");print_value("%d", default_number_samples);print_info(")\n");print_info("                     -leaf_size X  = the XYZ leaf size for the VoxelGrid -- for data reduction (default: ");print_value("%f", default_leaf_size);print_info(" m)\n");print_info("                     -write_normals = flag to write normals to the output pcd\n");print_info("                     -no_vis_result = flag to stop visualizing the generated pcd\n");
}/* ---[ */
int main(int argc, char **argv)
{print_info("Convert a CAD model to a point cloud using uniform sampling. For more information, use: %s -h\n", argv[0]);if (argc < 3){printHelp(argc, argv);return (-1);}// Parse command line argumentsint SAMPLE_POINTS_ = default_number_samples;parse_argument(argc, argv, "-n_samples", SAMPLE_POINTS_);float leaf_size = default_leaf_size;parse_argument(argc, argv, "-leaf_size", leaf_size);bool vis_result = !find_switch(argc, argv, "-no_vis_result");const bool write_normals = find_switch(argc, argv, "-write_normals");// Parse the command line arguments for .ply and PCD filesstd::vector<int> pcd_file_indices = parse_file_extension_argument(argc, argv, ".pcd");if (pcd_file_indices.size() != 1){print_error("Need a single output PCD file to continue.\n");return (-1);}std::vector<int> ply_file_indices = parse_file_extension_argument(argc, argv, ".ply");std::vector<int> obj_file_indices = parse_file_extension_argument(argc, argv, ".obj");if (ply_file_indices.size() != 1 && obj_file_indices.size() != 1){print_error("Need a single input PLY/OBJ file to continue.\n");return (-1);}vtkSmartPointer<vtkPolyData> polydata1 = vtkSmartPointer<vtkPolyData>::New();if (ply_file_indices.size() == 1){pcl::PolygonMesh mesh;pcl::io::loadPolygonFilePLY(argv[ply_file_indices[0]], mesh);pcl::io::mesh2vtk(mesh, polydata1);}else if (obj_file_indices.size() == 1){vtkSmartPointer<vtkOBJReader> readerQuery = vtkSmartPointer<vtkOBJReader>::New();readerQuery->SetFileName(argv[obj_file_indices[0]]);readerQuery->Update();polydata1 = readerQuery->GetOutput();}//make sure that the polygons are triangles!vtkSmartPointer<vtkTriangleFilter> triangleFilter = vtkSmartPointer<vtkTriangleFilter>::New();
#if VTK_MAJOR_VERSION < 6triangleFilter->SetInput(polydata1);
#elsetriangleFilter->SetInputData(polydata1);
#endiftriangleFilter->Update();vtkSmartPointer<vtkPolyDataMapper> triangleMapper = vtkSmartPointer<vtkPolyDataMapper>::New();triangleMapper->SetInputConnection(triangleFilter->GetOutputPort());triangleMapper->Update();polydata1 = triangleMapper->GetInput();bool INTER_VIS = false;if (INTER_VIS){visualization::PCLVisualizer vis;vis.addModelFromPolyData(polydata1, "mesh1", 0);vis.setRepresentationToSurfaceForAllActors();vis.spin();}pcl::PointCloud<pcl::PointNormal>::Ptr cloud_1(new pcl::PointCloud<pcl::PointNormal>);uniform_sampling(polydata1, SAMPLE_POINTS_, write_normals, *cloud_1);if (INTER_VIS){visualization::PCLVisualizer vis_sampled;vis_sampled.addPointCloud<pcl::PointNormal>(cloud_1);if (write_normals)vis_sampled.addPointCloudNormals<pcl::PointNormal>(cloud_1, 1, 0.02f, "cloud_normals");vis_sampled.spin();}// VoxelgridVoxelGrid<PointNormal> grid_;grid_.setInputCloud(cloud_1);grid_.setLeafSize(leaf_size, leaf_size, leaf_size);pcl::PointCloud<pcl::PointNormal>::Ptr voxel_cloud(new pcl::PointCloud<pcl::PointNormal>);grid_.filter(*voxel_cloud);if (!write_normals){pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_xyz(new pcl::PointCloud<pcl::PointXYZ>);// Strip uninitialized normals from cloud:pcl::copyPointCloud(*voxel_cloud, *cloud_xyz);savePCDFileBinary(argv[pcd_file_indices[0]], *cloud_xyz);}else{savePCDFileBinary(argv[pcd_file_indices[0]], *voxel_cloud);}
}

pcd转obj

#include <iostream>
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/obj_io.h>
#include <pcl/PolygonMesh.h>int main(int argc, char** argv)
{pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);pcl::io::loadPCDFile("rabbit.pcd", *cloud);pcl::PolygonMesh mesh;pcl::toPCLPointCloud2(*cloud, mesh.cloud);pcl::io::saveOBJFile("rabbit.obj", mesh);return 0;
}

stl转ply

#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <time.h>using namespace std;struct Coordinate {float x, y, z;bool operator<(const Coordinate& rhs) {return x<rhs.x || (x == rhs.x&&y<rhs.y) || (x == rhs.x&&y == rhs.y&&z<rhs.z);}bool operator==(const Coordinate& rhs) {return x == rhs.x&&y == rhs.y && z == rhs.z;}
};
vector<Coordinate> vecSorted, vecOrigin;
vector<Coordinate>::iterator iter, iterBegin;int numberOfFacets;
int numberOfPoints;
int index;char c1[] = "ply\nformat binary_little_endian 1.0\ncomment By ET \nelement vertex ";
char c2[] = "\nproperty float x\nproperty float y\nproperty float z\nelement face ";
char c3[] = "\nproperty list uchar int vertex_indices\nend_header\n";int main(int argc, char **argv)
{cout << ".exe .STL .ply" << endl;clock_t start, finish;double totaltime;start = clock();int length;int position = 80;fstream fileIn(argv[1], ios::in | ios::binary);fileIn.seekg(0, ios::end);length = (int)fileIn.tellg();fileIn.seekg(0, ios::beg);char* buffer = new char[length];fileIn.read(buffer, length);fileIn.close();numberOfFacets = *(int*)&(buffer[position]);position += 4;cout << "Number of Facets: " << numberOfFacets << endl;for (int i = 0; i < numberOfFacets; i++){Coordinate tmpC;position += 12;for (int j = 0; j < 3; j++){tmpC.x = *(float*)&(buffer[position]);position += 4;tmpC.y = *(float*)&(buffer[position]);position += 4;tmpC.z = *(float*)&(buffer[position]);position += 4;vecOrigin.push_back(tmpC);}position += 2;}free(buffer);vecSorted = vecOrigin;sort(vecSorted.begin(), vecSorted.end());iter = unique(vecSorted.begin(), vecSorted.end());vecSorted.erase(iter, vecSorted.end());numberOfPoints = vecSorted.size();ofstream fileOut(argv[2], ios::binary | ios::out | ios::trunc);fileOut.write(c1, sizeof(c1) - 1);fileOut << numberOfPoints;fileOut.write(c2, sizeof(c2) - 1);fileOut << numberOfFacets;fileOut.write(c3, sizeof(c3) - 1);buffer = new char[numberOfPoints * 3 * 4];position = 0;for (int i = 0; i < numberOfPoints; i++){buffer[position++] = *(char*)(&vecSorted[i].x);buffer[position++] = *((char*)(&vecSorted[i].x) + 1);buffer[position++] = *((char*)(&vecSorted[i].x) + 2);buffer[position++] = *((char*)(&vecSorted[i].x) + 3);buffer[position++] = *(char*)(&vecSorted[i].y);buffer[position++] = *((char*)(&vecSorted[i].y) + 1);buffer[position++] = *((char*)(&vecSorted[i].y) + 2);buffer[position++] = *((char*)(&vecSorted[i].y) + 3);buffer[position++] = *(char*)(&vecSorted[i].z);buffer[position++] = *((char*)(&vecSorted[i].z) + 1);buffer[position++] = *((char*)(&vecSorted[i].z) + 2);buffer[position++] = *((char*)(&vecSorted[i].z) + 3);}fileOut.write(buffer, numberOfPoints * 3 * 4);free(buffer);buffer = new char[numberOfFacets * 13];for (int i = 0; i < numberOfFacets; i++){buffer[13 * i] = (unsigned char)3;}iterBegin = vecSorted.begin();position = 0;for (int i = 0; i < numberOfFacets; i++){position++;for (int j = 0; j < 3; j++){iter = lower_bound(vecSorted.begin(), vecSorted.end(), vecOrigin[3 * i + j]);index = iter - iterBegin;buffer[position++] = *(char*)(&index);buffer[position++] = *((char*)(&index) + 1);buffer[position++] = *((char*)(&index) + 2);buffer[position++] = *((char*)(&index) + 3);}}fileOut.write(buffer, numberOfFacets * 13);free(buffer);fileOut.close();finish = clock();totaltime = (double)(finish - start) / CLOCKS_PER_SEC * 1000;cout << "All Time: " << totaltime << "ms\n";return 0;
}

ply转stl

#include <pcl/io/vtk_lib_io.h>
#include <vtkPLYReader.h>
#include <vtkSTLWriter.h>int main(int argc, char** argv)
{vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();reader->SetFileName("rabbit.ply");reader->Update();vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();polyData = reader->GetOutput();polyData->GetNumberOfPoints();vtkSmartPointer<vtkSTLWriter> writer = vtkSmartPointer<vtkSTLWriter>::New();writer->SetInputData(polyData);writer->SetFileName("rabbit.stl");writer->Write();return 0;
}

本文标签: 点云文件常用格式转换(pcd txt ply obj stl)