找回密码
 会员注册
查看: 24|回复: 0

Python3D建模指南numpy-stlpymeshpytorch3dsolidpythonpyvista

[复制链接]

4

主题

0

回帖

13

积分

新手上路

积分
13
发表于 2024-9-4 18:09:09 | 显示全部楼层 |阅读模式
想象一下,我们需要用python编程语言构建某个对象的三维模型,然后将其可视化,或者准备一个文件以便在3D打印机上打印。有几个库可以解决这些问题。让我们看一下如何在python中从点、边和图元构建3D模型。如何执行基本3D建模技术:移动、旋转、合并、减去等。在线工具推荐:Three.jsAI纹理开发包-YOLO合成数据生成器-GLTF/GLB在线编辑-3D模型格式在线转换-3D场景编辑器我们将使用以下Python库完成上述任务:numpy-stlpymeshpytorch3dSolidPython使用每个库,我们构建门格尔海绵分形,将模型保存到stl文件,然后渲染图像。在此过程中,我们简要了解了数据结构和术语。所有示例均针对Linux操作系统提供,代码可以在GitHub存储库中找到。1、环境准备打开你的Linux终端并运行以下shell命令:#DockerforPymeshlibraryexamples:curl-fsSLhttps://get.docker.com-oget-docker.shsudoshget-docker.sh#PyTorch3dg++compiler:sudoaptupdatesudoaptinstallg++#Repositorycloningandlibraryinstallation:gitclonehttps://github.com/format37/python3d.gitcdpython3dpipinstall-rrequirements.txtpipinstall"git+https://github.com/facebookresearch/pytorch3d.git"#OpenScadinstall:sudoapt-getinstallopenscad12345678910111213如果遇到安装问题,我建议你使用谷歌搜索。不幸的是,随着时间的推移,一些依赖项可能会变得过时。本文的主要思想是尽可能多地收集和概述Python3D建模方法。2、Numpy-stl概述多边形网格的结构:2.1Vertices点列表。每个点由三个数字描述-3维空间中的坐标。接下来,我们将使用JupyterNotebook。示例:numpy_stl_example_01.ipynbimportnumpyasnpfrommyplotimportplot_verticlesvertices=np.array([[-3,-3,0],[+3,-3,0],[+3,+3,0],[-3,+3,0],[+0,+0,+3]])plot_verticles(vertices=vertices,isosurf=False)12345678910尽管仅描述了顶点,但已经可以想象如果将它们与三角形连接起来,模型会是什么样子:plot_verticles(vertices=vertices,isosurf=True)1看起来这些面已经存在了。但现在我们只有顶点。要创建STL文件,我们需要描述面,这可以手动完成,或者使用scipy库提供的spatial.ConvexHull函数完成操作。示例:numpy_stl_example_02.ipynbimportnumpyasnpfromscipyimportspatialfromstlimportmeshfrommyplotimportplot_meshvertices=np.array([[-3,-3,0],[+3,-3,0],[+3,+3,0],[-3,+3,0],[+0,+0,+3]])hull=spatial.ConvexHull(vertices)faces=hull.simplices123456789101112131415faces数组包含以下面描述:array([[4,1,0],[4,2,1],[3,4,0],[3,4,2],[3,2,1],[3,1,0]],dtype=int32)123456782.2Faces面列表。每个三角形面由三个顶点(点)描述。换句话说,顶点数组中点的位置。例如,最后一个面包含数字3,1,0。因此面由顶点数组的第0、1和3个元素的点组装而成:2.3Mesh网格是顶点和面的集合,确定多面体对象的形状。myramid_mesh=mesh.Mesh(np.zeros(faces.shape[0],dtype=mesh.Mesh.dtype))fori,finenumerate(faces):forjinrange(3):myramid_mesh.vectors[i][j]=vertices[f[j],:]plot_mesh(myramid_mesh)1234567从图中可以看出,金字塔的一面是上下颠倒的。在下面的例子中,在构造分形时,不会使用ConvexHull方法,因为它以任意顺序排列面的点,这会导致某些面的翻转。myramid_mesh.save('numpy_stl_example_02.stl')1要查看STL文件,可以使用Blender,或者直接使用STL在线预览工具:space.convexhull方法被设计用于计算凸壳,并且可以很好地应对金字塔和立方体。但在有空腔的物体中,由于点的数量不一致,在组装STL时会丢失部分点,从而出现错误。这在二维示例中清晰可见:numpy_stl_example_03.ipynbimportmatplotlib.pyplotaspltfromscipyimportspatialimportnumpyasnppoints=np.array([[0,0],[-2,0],[-2,2],[0,1.5],[2,2],[2,0]])hull=spatial.ConvexHull(points)123456789101112hull.simplices包含面描述:array([[2,1],[2,4],[5,1],[5,4]],dtype=int32)123456让我们绘制顶点和面:plt.plot(points[:,0],points[:,1],'o')forsimplexinhull.simplices:plt.plot(points[simplex,0],points[simplex,1],'k-')123对于这种情况,可以找到凸包的替代方案,或者手动描述边:faces=np.array([[0,1],[1,2],[2,3],[3,4],[4,5],[5,0]])plt.plot(points[:,0],points[:,1],'o')forsimplexinfaces:plt.plot(points[simplex,0],points[simplex,1],'k-')12345678910113、Numpy-stl构建分形是时候构建一个分形了。Numpy-stl中没有布尔减法函数。为了构建门格尔海绵分形,我们采取了相反的做法。有两种方法:构建基本立方体网格。我们称之为体素。将多个体素组合成一个网格。我们将从立方体构建分形,就像从构造函数一样。构造分形的逻辑描述:假设分形面长度为1。分形深度是唯一孔尺寸的数量。体素长度取决于分形的深度,每个新的深度级别都会除以3。我们将找到深度为1和2的体素边。让我们简化任务,将分形从3维变为1维情况:如果分形级别为2,则立方体边长将为1/(3**2),相当于1/9。让我们制作一组立方体,以便它们按其位置填充生成的体素立方体。我们来计算一下孔面积。排除孔中的体素。总之,将剩余的体素合并到一个对象中并保存。示例:numpy_stl_example_04.ipynb4、Numpy-stl渲染为了渲染图像,我们将从STL文件加载的网格发送到plot_mesh函数。示例:numpy_stl_example_05.ipynb5、PyMesh概述不幸的是,Pymesh库无法通过PIP包管理器安装,尽管文档中描述了这种方法,也无法通过Anaconda安装。有两种安装方法。按照说明,从源代码进行编译。使用docker容器。我选择这个选项是因为更有趣。容器使用参数启动。使用启动参数,将脚本文件夹装载到容器中。让我们为脚本提供必要的参数。脚本执行完成后,容器将被删除。如果Docker已经按照文章开头的说明安装,则无需再安装。如果Docker不适合你,请按照文档中的说明编译Pymesh。这个选项也经过我的测试。示例:pymesh_example_01.pyimportpymeshbox_a=pymesh.generate_box_mesh([0,0,0],[1,1,1])filename="/pymesh_examples/pymesh_example_01.stl"pymesh.save_mesh(filename,box_a,ascii=False)1234从项目根目录启动容器:shpymesh_example_01.sh1执行上述命令后:Pymesh容器启动。初次启动镜像下载需要一些时间。Pymesh_examples文件夹安装在容器内。Python脚本在容器内启动:/pymesh_examples/pymesh_example_01.pyPymesh库已导入。generate_box_mesh函数根据点[0,0,0]和[1,1,1]处的两个相对顶点生成立方体。Save_Mesh函数将对象保存在STL文件中。执行后,pymesh_examples文件夹中出现pymesh_example_01.stl文件。让我们使用布尔减法来制作一个方孔。我们要构建一个平行六面体并将其从主立方体中减去。示例:pymesh_example_02.pyimportpymeshbox_a=pymesh.generate_box_mesh([0,0,0],[1,1,1])box_b=pymesh.generate_box_mesh([0.4,0.4,0],[0.6,0.6,1])box_c=pymesh.boolean(box_a,box_b,operation='difference',engine="igl")filename="/pymesh_examples/pymesh_example_02.stl"pymesh.save_mesh(filename,box_c,ascii=False)1234567891011运行程序:shpymesh_example_02.sh1布尔函数很简单。第一个参数是我们从中减去的对象。其次是我们做减法。我们还发送操作和引擎。布尔值不仅适用于减法。总共有4种操作可用:交:A∩B并:A∪B差:A∖B(最后两个例子)异或:AXORB(图像未显示)为了更好地理解如何移动和旋转对象,出于调试目的,可以方便地暂时用Union代替Difference操作。让我们制作第二个孔,移动并旋转它。示例:pymesh_example_03.py运行:shpymesh_example_03.sh1我们的脚本包含了移动和旋转函数。通过移动,会根据原始对象修改后的顶点和面创建一个新的网格对象。四元数类描述旋转,然后根据原始对象的顶点和面以及旋转的描述创建一个新的旋转对象。脚本执行的结果是一个带有两个相交孔的立方体:这些工具足以构建分形。6、PyMesh构建分形示例:pymesh_example_04.py在此脚本中,我们添加了一个输入参数来设置分形深度。对于每个深度级别,创建一个框,复制两次,然后旋转和偏移。结果只有3个平行六面体,这是从主立方体中减去的。每条边各一个。此操作重复x和y次以填充所有行和列边缘。未执行从空白空间中减去的检查。这次我们必须明确指定分形的深度:shpymesh_example_04.sh31需要5至15分钟才能完成。启动后,新的STL文件将出现在pymesh_examples文件夹中:请求4级分形,组装大约需要4小时,文件大小为73mb:3D打印后就是这样:7、PyMesh渲染上次我们旋转了网格。这次让我们旋转相机。示例:pymesh_example_05.py运行程序:shpymesh_example_05.sh18、PyTorch3d概述金字塔示例:pytorch3d_example_01.py方法与numpy-stl中使用的方法非常相似。但由于它应该在GPU上工作,因此我们将主机和设备的概念分开。主机就是我们的电脑。设备是显卡。如果你没有显卡,仍然可以使用库,那么CPU将充当GPU。主机和设备都有自己的内存。要将项目从主机传输到设备并传回,我们需要执行一个小仪式。在下面的例子中,我们立即描述设备上的顶点,将它们从设备复制到主机。基于顶点计算的边。然后保存该对象。生成的OBJ文件可以导入到Blender中:注意命令verts.cpu().numpy()顶点从设备复制到主机。如果使用GPU,每个副本都会减慢算法速度。在规划程序架构时,最好将主机和设备之间的复制操作次数尽可能减少。例如,如果你最初在主机上有一个顶点列表,则可以计算面,而无需将顶点从设备复制到主机,如下一个示例中所示。示例:pytorch3d_example_02.py9、PyTorch3d构建分形GPU提供了一些性能提升。示例:pytorch3d_example_03.py我们声明了指定深度级别的最小体素的顶点。使用与前面的示例相似的算法,我们计算二维的孔坐标。然后用不会落入孔中的体素填充主立方体。计算速度提高了一个数量级,这使得在大约5小时内构建5级分形成为可能:此STL文件的大小为1.9GB。在构建第5层分形时,由于显卡内存溢出,程序停止。我必须分批收集该物体。创建了10层“2D”分形,然后将它们附加到主要对象上,直到构建完整的分形。10、PyTorch3d渲染除了绘图可视化之外,pytorch3d还特别关注渲染。而且这种方法非常彻底,有纹理和着色器。示例:pytorch3d_example_04.py11、SolidPython概述SolidPython是目前最丰富的建模库。3D场景,描述格式,与openscad非常相似。Python生成写入scad文件的openscad代码。然后可以在openscad中编辑或立即保存为STL。示例:solidpython_example_01.ipynbfromsolidimport*d=difference()(cube(size=10,center=True),sphere(r=6.5,segments=300))path=scad_render_to_file(d,'solidpython_example_01.scad')123456为了指定球体的分辨率,我们使用wordsegment,而不是通常的$fnopenscad参数。Solidpython方便调试。在屏幕的一侧,我们打开了scad文件。在另一边,我们打开了JupyterNotebook。在JupyterNotebook中执行scad_render_to_file后,openscad中的图片会自动更新。Openscad可以使用控制台命令将模型渲染为stl文件。Jupyter笔记本中有调用示例:!openscadsolidpython_example_01.scad-osolidpython_example_01.stl1任何openscad函数都会返回一个对象。要对对象执行操作,请在操作调用字符串末尾的圆括号中传递对象或对象列表。示例:solidpython_example_02.ipynbfromsolidimport*c=circle(r=1)t=translate([2,0,0])(c)e=linear_extrude(height=10,center=True,convexity=10,twist=-500,slices=500)(t)col=color('lightgreen')(e)path=scad_render_to_file(col,'solidpython_example_02.scad')123456789101112分辨率由切片参数决定。12、SolidPython构建分形示例:solidpython_example_03.ipynb13、SolidPython渲染让我们通过相机在每个图像上旋转来渲染最后一个场景的一系列图像。示例:solidpython_example_04.ipynb此外,solidpython还提供使用openscad的动画生成功能。文档中有一小节带有示例。最后,让我们看一下本文中用于构建场景的代码。示例:solidpython_example_05.ipynb14、PyVista我还想提一下另一个有趣的PyVista库。通过可视化工具包(VTK)的简化界面进行3D绘图和网格分析他通过从STL文件读取网格来帮助我可视化深度图。但除此之外,它还有一些其他有趣的功能。15、库比较目前的性能比较并不完全客观,因为算法存在显着差异。Pymesh和SolidPython使用减法,而Numpy-stl和Pytorch3d使用网格并集。我的机器配置如下:Ubuntu20.04.2LTSPython3.7.3英特尔®酷睿™i3-7350KCPU@4.20GHz内存35.2GbGPUGeForceGTX1080Ti11175MB原文链接:Python3D建模入门—BimAnt
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-31 03:46 , Processed in 0.588445 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表