3、点云数据生成(一):使用Open3D生成基本几何体点云(立方体、球体、圆柱体),理解点云坐标与颜色
各位好,欢迎来到《点云生成与滤波处理实战手册》的第三讲。
今天咱们聊聊一个基础但特别重要的话题——怎么用Open3D生成基本几何体的点云。说白了,就是让计算机“凭空”变出立方体、球体、圆柱体的点云数据。
你可能会问:“为什么要自己生成?直接扫描不就行了?”嗯,我在项目里遇到过这种情况:算法调试阶段,你手头没有激光雷达,或者扫描数据太脏、有遮挡。这时候,自己生成干净的点云数据,就是最好的调试工具。它能帮你快速验证算法逻辑,排除数据噪声的干扰。
核心要点:Open3D 提供了 create_mesh_box、create_mesh_sphere、create_mesh_cylinder 等函数,但注意——它们生成的是三角网格,不是点云。我们需要从网格中采样点,才能得到点云。
3.1 从网格到点云:一个关键转换
我个人习惯把Open3D的几何体生成流程拆成三步:
- 创建网格对象(Mesh)
- 从网格采样点(Sample Points)
- 赋予颜色(Assign Colors)
为什么不能直接生成点云?因为Open3D的设计哲学是:网格是“连续”的几何表示,点云是“离散”的采样结果。你想想看,一个球体表面有无穷多个点,我们只能取有限个。所以必须通过采样。
来看一个最简单的例子——生成一个立方体点云:
import open3d as o3d
import numpy as np
# 1. 创建立方体网格(边长2,中心在原点)
mesh_box = o3d.geometry.TriangleMesh.create_box(width=2.0, height=2.0, depth=2.0)
mesh_box.translate([-1, -1, -1]) # 将中心移到原点
# 2. 采样点云(均匀采样500个点)
pcd = mesh_box.sample_points_uniformly(number_of_points=500)
# 3. 赋予颜色(这里用蓝色)
pcd.paint_uniform_color([0.1, 0.2, 0.8])
# 可视化
o3d.visualization.draw_geometries([pcd], window_name="立方体点云")
这里有个坑,我曾经踩过:create_box 默认的立方体是从 [0,0,0] 到 [2,2,2],中心在 [1,1,1]。如果你不平移,后面做旋转或对称操作时,坐标会乱套。所以我习惯先平移,让几何体中心对齐原点。
3.2 球体与圆柱体:参数控制与采样密度
球体和圆柱体稍微复杂一点,因为它们有半径和分辨率的概念。
先看球体:
# 生成球体网格(半径1.0,分辨率20)
mesh_sphere = o3d.geometry.TriangleMesh.create_sphere(radius=1.0, resolution=20)
pcd_sphere = mesh_sphere.sample_points_uniformly(number_of_points=1000)
pcd_sphere.paint_uniform_color([0.8, 0.2, 0.1]) # 红色
resolution 参数控制网格的细分程度。数值越大,网格越精细,采样出的点云越接近理想球体。但注意,resolution=20 已经会产生约 400 个三角面,采样 1000 个点绰绰有余。
圆柱体呢?它需要半径和高度:
# 生成圆柱体网格(半径0.5,高度2.0)
mesh_cylinder = o3d.geometry.TriangleMesh.create_cylinder(radius=0.5, height=2.0, resolution=20)
pcd_cylinder = mesh_cylinder.sample_points_uniformly(number_of_points=800)
pcd_cylinder.paint_uniform_color([0.2, 0.8, 0.2]) # 绿色
小技巧:采样点数不是越多越好。我一般遵循“每平方厘米 50-100 个点”的经验法则。比如一个半径1的球体,表面积约12.56,取 600-1200 个点就够用了。点太多,可视化会卡;点太少,形状特征不明显。
3.3 理解点云坐标与颜色
生成点云后,我们得理解它内部的数据结构。说白了,点云就是一个 N×3 的坐标矩阵,加上一个 N×3 的颜色矩阵。
来看一下如何获取这些数据:
# 获取点坐标(N行3列)
points = np.asarray(pcd.points)
print("点云坐标形状:", points.shape) # 例如 (500, 3)
print("前5个点坐标:\n", points[:5])
# 获取颜色(N行3列,值范围0-1)
colors = np.asarray(pcd.colors)
print("颜色形状:", colors.shape) # 例如 (500, 3)
print("前5个点颜色:\n", colors[:5])
坐标的单位是什么?Open3D 默认使用米。所以一个边长2的立方体,就是2米见方。颜色值在 [0, 1] 之间,不是 [0, 255]。这一点和很多图像处理库不同,要注意。
注意:如果你从其他软件(如CloudCompare)导入点云,颜色值可能是0-255。记得除以255归一化。我曾经因为这个坑,调试了整整一个下午才发现颜色显示不对。
3.4 综合示例:生成三种几何体并对比
下面我把三种几何体放在一起,生成并显示,方便对比:
import open3d as o3d
import numpy as np
# 创建立方体
mesh_box = o3d.geometry.TriangleMesh.create_box(2, 2, 2)
mesh_box.translate([-1, -1, -1])
pcd_box = mesh_box.sample_points_uniformly(500)
pcd_box.paint_uniform_color([0.1, 0.2, 0.8])
# 创建球体
mesh_sphere = o3d.geometry.TriangleMesh.create_sphere(1.0, resolution=20)
pcd_sphere = mesh_sphere.sample_points_uniformly(1000)
pcd_sphere.paint_uniform_color([0.8, 0.2, 0.1])
# 创建圆柱体
mesh_cylinder = o3d.geometry.TriangleMesh.create_cylinder(0.5, 2.0, resolution=20)
pcd_cylinder = mesh_cylinder.sample_points_uniformly(800)
pcd_cylinder.paint_uniform_color([0.2, 0.8, 0.2])
# 平移位置,避免重叠
pcd_box.translate([-3, 0, 0])
pcd_cylinder.translate([3, 0, 0])
# 可视化
o3d.visualization.draw_geometries(
[pcd_box, pcd_sphere, pcd_cylinder],
window_name="三种基本几何体点云",
width=1200, height=600
)
运行这段代码,你会看到三个不同颜色、不同形状的点云并排显示。蓝色立方体、红色球体、绿色圆柱体。嗯,这里要注意:圆柱体的高度是2米,半径0.5米,看起来会比较“瘦高”。如果你想要更粗的圆柱,调大半径就行。
3.5 知识体系:本章核心逻辑
为了让你更直观地理解本章的知识结构,我画了一张流程图:
这张图清晰地展示了从网格到点云的完整链路。你跟着这个流程走,基本不会出错。
3.6 避坑指南与个人经验
最后,分享几个我实际项目中遇到的坑:
- 采样不均匀:
sample_points_uniformly是均匀采样,但网格面片大小不同时,大面片上点会更多。如果你需要严格均匀分布,可以用sample_points_poisson_disk做泊松盘采样。 - 颜色丢失:如果你保存点云为
.ply文件,记得用write_point_cloud并指定write_ascii=True,否则颜色信息可能丢失。 - 坐标偏移:多个几何体组合时,一定要先平移再合并。我习惯用
pcd.translate([dx, dy, dz])分别调整位置。
好了,这一讲的内容就到这里。你学会了用Open3D生成三种基本几何体的点云,也理解了坐标和颜色的存储方式。下一讲我们会继续深入,看看如何生成更复杂的点云数据。
公众号:蓝海资料掘金营,微信deep3321