你有没有搜索过如何将 Cad 模型转换为 python 就绪的 numpy 数组,但没有得到任何明确的答案? 我也是。 经过长时间的研究并尝试了很多软件和 python 库,我终于能够将 3D STEP 文件转换为 3 维 numpy 数组。 如果你想做同样的事情或只是想知道它是如何完成的,请继续阅读 😃
推荐:用 NSDT设计器 快速搭建可编程3D场景。
1、简介
与二维图像数据相比,对 3 维模型的机器学习研究并不多。 大多数机器学习和深度学习模型都使用 numpy 数组作为数据类型。
虽然点云数据可以作为 numpy 数组导入,但是当 3D 模型转换为点云时,空间信息会丢失。 点云只是空间中的一组数据点,其中每个点都有其一组 X、Y 和 Z 坐标。 当点云被转换为 3 维 numpy 数组时,空间信息被恢复。 一个 3 维 numpy 数组就像一堆 2D 图像,其中每个图像都是整个 3D 的横截面视图,无论你如何切片阵列。
我最近正在从事一个这样的项目,但没有找到任何资源来帮助我将 cad 模型转换为 numpy 数组。
2、需要的软件和 Python 库
要加载“.stp”文件,我们将使用 FreeCAD 软件。 FreeCAD 是一款免费的开源参数化 3D 建模器。 你可以从此处下载该软件。 我们将使用 FreeCAD 加载“.stp”文件并将其转换为点云。
对于 Python,我将使用 Jupyter Notebook,但代码应该可以在任何其他 IDE 上正常运行。 我们将需要以下 Python 库来可视化点云并将其转换为 numpy 数组。
import pptk #not essential, but its good for visualizing
import numpy as np
import pandas as pd
from pyntcloud import PyntCloud
3、将 .stp 文件转换为点云
FreeCAD 的用户界面非常直观且易于理解。 当你在 FreeCAD 中打开一个“.stp”文件时,它看起来像这样:
我正在使用的 cad 模型是我几年前为 GrabCad 网站上的竞赛创建的。 您可以通过单击此处查看我的其他 Cad 模型并在 GrabCad 上进行渲染。
我们在 FreeCAD 中要做的第一件事是激活点工作台。 转到 View>Workbench>Points,如下图所示:
要将 3D 模型转换为点云,请选择左侧面板上的零件(part)。 选择零件实体后,工具栏中的“转换为点”选项将可用。 选择转换为点选项并输入最大距离。 最大距离是两点之间的距离。 创建点云所花费的时间与最大距离成反比。 因此,请根据所需的详细程度和你的计算机配置来选择它。
当单击“确定”时,点云即会生成,并且可以在左侧面板上将其视为一个单独的零件体。 可以在下图中看到:
要导出点云,请在左侧面板上选择点云零件主体,然后单击“导出点云”选项。 确保在保存点云时文件的扩展名应该是“.asc”。
4、点云到 3D Numpy 数组
要将“.asc”点云文件加载到 python 中,我们将使用 numpy 库。 使用下面显示的代码行将点云导入 python。 点云将是一个形状为 (N, 3) 的 numpy 数组。 其中 N 是数据点的数量,3 是每个数据点的 X、Y 和 Z 坐标。 有关单个数据点的示例,请参见下面代码中的最后两行。
import numpy as np
point_cloud = np.loadtxt("path/bracketpointcloud.asc")
point_cloud.shape
#output: (1840605, 3)
point_cloud[1]
#output: array([94.5374 , -2.27163, -3.81])
我们可以使用 pptk 库或 PyntCloud 库来查看点云。 我将解释两者,但 pptk 更好且易于可视化。 要使用 pptk 可视化点云,只需使用以下代码。 这将打开一个新窗口,你可以在其中缩放和旋转点云。 pptk 库提供了许多其他参数,可以在文档中看到。
v = pptk.viewer(point_cloud)
要使用 PyntCloud 可视化点云,我们必须将 numpy 数组转换为 pandas 数据框。 其中每行代表一个数据点,列代表相应数据点的 X、Y 和 Z 坐标。 然后这个数据框被用来创建一个 PyntCloud 对象,如下面的代码所示。 要绘制点云,请使用以下代码的最后一行。 PyntCloud 将在 jupyter 中显示输出。 我们可以在显示点云之前设置点大小和不透明度。
from pyntcloud import PyntCloud
df = pd.DataFrame(data=point_cloud, columns=['x','y','z'])
cloud = PyntCloud(new_df)
cloud
#output: PyntCloud
1840603 points with 0 scalar fields
0 faces in mesh
0 kdtrees
0 voxelgrids
Centroid: 57.98352803, 18.506313633, -6.561006902397e-05
Other attributes:
cloud.plot(point_size=0.1, opacity=0.6)
现在我们将点云数据帧转换为体素网格,也称为点云体素化(Voxelization)。 为此,我们将使用下面的前两行代码。 我们还可以设置表示 3D 模型的体素空间的大小。 这在深度学习和机器学习中特别方便,因为所有输入都应该具有相同的大小。 可以使用下面显示的最后一行代码查看体素网格。
voxelgrid_id = cloud.add_structure(“voxelgrid”, n_x=512, n_y=512, n_z=512)
voxelgrid = cloud.structures[voxelgrid_id]
voxelgrid.plot(d=3, mode="density", cmap="hsv")
最后我们只需要将体素网格转换为二进制 numpy 数组。 使用下面的代码行。
Binary_voxel_array = voxelgrid.get_feature_vector(mode=”binary”)
Binary_voxel_array.shape
#output: (512, 512, 512)
好了,现在我们有了一个 Numpy 数组表示的 3D cad 模型。
5、让我们看看结果
我们创建的 numpy 数组与 3D 模型非常相似。 当我们在 2 维中对数组进行切片时,我们将立即获得剖面图。 通过这种方式,机器可以保留 3D 模型的空间信息,机器可以使用各种深度学习或机器学习技术来学习这些信息。 下面是我们在 (512, 512, 512) 数组的不同索引处对数组进行切片时得到的几个示例。
plt.imshow(Binary_voxel_array[ 200, : , : ], cmap=’gray’)
plt.imshow(Binary_voxel_array[ :, 300, : ], cmap=’gray’)
plt.imshow(Binary_voxel_array[ :, :, 250 ], cmap=’gray’)
原文链接:3D CAD模型体素化 — BimAnt