[求助]怎么将三角网格形式再转回点云啊
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[求助]怎么将三角网格形式再转回点云啊相关的知识,希望对你有一定的参考价值。
[求助]怎么将三角网格形式再转回点云啊 ..谢谢啊
简单,因为三角网格本身就是点云连接成的啊。譬如STL格式的Mesh,它是由许多三角形Facets组成的,而每个Facet由三个顶点及其法线矢量组成(点坐标与法线矢量都是X,Y,Z三个值)。所以,要读出STL格式文件,只需写个小程序,遍历网格上每个Facet,即可得到所有顶点坐标。请注意,STL格式描述每个点,都重复四遍。换句话说,STL网格有好多冗余重复的点云数据,所以在遍历程序里,要记得逐点与前面已遍历的点进行比较,消除冗余描述的点。最后把读出的点云投影到XY平面上,即可按矩阵形式排列各点了05x05x。这就是点云排列的有序化。 参考技术A 如果用Imageware的话,就很简单了哇:打开STL 文件后,然后另存为“Save as”,选文件格式为ASCII(文件名可以相同,后缀不同)。 无需选Label格式的ASCII文件。这就是点云文件了,里面是一个个点的三维坐标。64K以内的文件可以用记事本打开看,更大的可以用WORDPAD看,或导入EXCEL。如何使用 pcl 将 3D 点云离散化为 xy 平面上的 2D 网格,而不是使用体素网格?
【中文标题】如何使用 pcl 将 3D 点云离散化为 xy 平面上的 2D 网格,而不是使用体素网格?【英文标题】:hwo to use pcl to achieve that discretizing the 3D point cloud into a 2D grid over the xy plane, not use the voxelgrid? 【发布时间】:2019-01-10 15:38:45 【问题描述】:我想将3D点云在xy平面上投影成2D网格,每个网格单元大小为20cm*20cm,如何有效实现?
不使用 VoxelGrid 方法,因为我想保留每个点并在下一步处理它们(每列高斯核并使用 EM 处理每个网格)
【问题讨论】:
欢迎来到 Stack Overflow!请查看writing the perfect question 以帮助您提出一个好问题,从而获得一个好的答案。 请看:***.com/a/49749230/6812182 【参考方案1】:正如 cmets 中所讨论的,您可以使用 OctreePointCloudPointVector
类实现您想要的。
这是一个如何使用该类的示例:
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/octree/octree_pointcloud_pointvector.h>
using Cloud = pcl::PointCloud<pcl::PointXYZ>;
using CloudPtr = Cloud::Ptr;
using OctreeT = pcl::octree::OctreePointCloudPointVector<pcl::PointXYZ>;
int main(int argc, char** argv)
if(argc < 2)
return 1;
// load cloud
CloudPtr cloud(new Cloud);
pcl::io::loadPCDFile(argv[1], *cloud);
CloudPtr cloud_projected(new Cloud(*cloud));
// project to XY plane
for(auto& pt : *cloud_projected)
pt.z = 0.0f;
// create octree, set resolution to 20cm
OctreeT octree(0.2);
octree.setInputCloud(cloud_projected);
octree.addPointsFromInputCloud();
// we gonna store the indices of the octree leafs here
std::vector<std::vector<int>> indices_vec;
indices_vec.reserve(octree.getLeafCount());
// traverse the octree leafs and store the indices
const auto it_end = octree.leaf_depth_end();
for(auto it = octree.leaf_depth_begin(); it != it_end; ++it)
auto leaf = it.getLeafContainer();
std::vector<int> indices;
leaf.getPointIndices(indices);
indices_vec.push_back(indices);
// save leafs to file
int cnt = 0;
for(const auto indices : indices_vec)
Cloud leaf(*cloud, indices);
pcl::io::savePCDFileBinary("leaf_" + std::to_string(cnt++) + ".pcd", leaf);
调用pcl_viewer
可以看到输出:
pcl_viewer 叶_*.pcd
查看示例输出
【讨论】:
嗨,塞尔坎。我运行了代码,但是我很困惑,当我使用 Visual Studio 时,我找不到最终结果文件(leaf_number 的名称)。 文件将被写入VS运行程序的路径。您可以随时将路径更改为pcl::io::savePCDFileBinary()
中的绝对路径。【参考方案2】:
您可以使用https://github.com/daavoo/pyntcloud 和以下代码实现此目的:
from pyntcloud import PyntCloud
cloud = PyntCloud.from_file("some_cloud.ply")
# 0.2 asumming your point cloud units are meters
voxelgrid_id = cloud.add_structure("voxelgrid", size_x=0.2, size_y=0.2)
voxelgrid = cloud.structures[voxelgrid_id]
您可以在此处了解有关 VoxelGrid 的更多信息:
https://github.com/daavoo/pyntcloud/blob/master/examples/%5Bstructures%5D%20VoxelGrid.ipynb
【讨论】:
【参考方案3】:xy 平面上的二维网格是什么意思?还是要z值是原来的值,还是先把点云投影到XY平面上?
保持Z值
如果您想保留 Z 值,只需将 VoxelGrid
的 Z 的 叶子大小 设置为无限(或非常大的数字)。
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud (cloud);
sor.setLeafSize (0.01f, 0.01f, 100000.0f);
sor.filter (*cloud_filtered);
先将 Cloud 投影到 XY 平面
将云投影到XY平面只不过是将每个点的Z值设置为0。
for(auto& pt : cloud)
pt.z = 0.0f;
现在你可以在投影点云上做普通的VoxelGrid
。
【讨论】:
据我了解,VoxelGrid 是一种实现下采样的方法,即从输入网格中的每个输出点。我想把原来的点云投影到xy平面并光栅化,每个网格大小为20cm*20cm,并且保留点云中的每一个点,而不是下采样 好的,我明白了。在这种情况下,我建议使用OctreePointCloudPointVector。首先将您的输入点云投影到 XY 平面,使用该投影点云作为八叉树的输入。之后,您将获得每个体素中输入点云的点的索引。 是的,我实际上实现了到 xy 平面的投影,但我对光栅化感到困惑。我的投影方法是 pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());系数->values.resize(4);系数->值[0] = 0;系数->值[1] = 0;系数->值[2] = 1;系数->值[3] = 0; 谢谢你的回复,我其实是搜索八叉树方法的,我被一些东西弄糊涂了。首先是八叉树的体素内部是否为空,而只是像二维平面上的像素一样表示。第二个问题是,如果我想知道网格内部的分布,我该怎么办? @WanEthan 我将在单独的答案中向您展示如何实现您想要的。以上是关于[求助]怎么将三角网格形式再转回点云啊的主要内容,如果未能解决你的问题,请参考以下文章