Python 3D建模指南【numpy-stl | pymesh | pytorch3d | solidpython | pyvista】

news2024/11/23 17:13:17

想象一下,我们需要用 python 编程语言构建某个对象的三维模型,然后将其可视化,或者准备一个文件以便在 3D 打印机上打印。 有几个库可以解决这些问题。 让我们看一下如何在 python 中从点、边和图元构建 3D 模型。 如何执行基本 3D 建模技术:移动、旋转、合并、减去等。
在这里插入图片描述

在线工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 3D场景编辑器

我们将使用以下Python库完成上述任务:

  • numpy-stl
  • pymesh
  • pytorch3d
  • SolidPython

使用每个库,我们构建门格尔海绵分形,将模型保存到 stl 文件,然后渲染图像。 在此过程中,我们简要了解了数据结构和术语。

所有示例均针对 Linux 操作系统提供,代码可以在 GitHub 存储库中找到。

1、环境准备

打开你的 Linux 终端并运行以下 shell 命令:

# Docker for Pymesh library examples:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# PyTorch3d g++ compiler:
sudo apt update
sudo apt install g++
# Repository cloning and library installation:
git clone https://github.com/format37/python3d.git
cd python3d
pip install -r requirements.txt
pip install "git+https://github.com/facebookresearch/pytorch3d.git"
# OpenScad install:
sudo apt-get install openscad

如果遇到安装问题,我建议你使用谷歌搜索。 不幸的是,随着时间的推移,一些依赖项可能会变得过时。 本文的主要思想是尽可能多地收集和概述 Python 3D 建模方法。

2、Numpy-stl概述

多边形网格的结构:
在这里插入图片描述

2.1 Vertices

点列表。 每个点由三个数字描述 - 3 维空间中的坐标。

接下来,我们将使用 Jupyter Notebook。

示例:numpy_stl_example_01.ipynb

import numpy as np
from myplot import plot_verticles
vertices = np.array([
[-3, -3, 0],
[+3, -3, 0],
[+3, +3, 0],
[-3, +3, 0],
[+0, +0, +3]
])
plot_verticles(vertices = vertices, isosurf = False)

在这里插入图片描述

尽管仅描述了顶点,但已经可以想象如果将它们与三角形连接起来,模型会是什么样子:

plot_verticles(vertices = vertices, isosurf = True)

在这里插入图片描述

看起来这些面已经存在了。 但现在我们只有顶点。 要创建 STL 文件,我们需要描述面,这可以手动完成,或者使用scipy 库提供的 spatial.ConvexHull 函数完成操作。

示例:numpy_stl_example_02.ipynb

import numpy as np
from scipy import spatial
from stl import mesh
from myplot import plot_mesh
vertices = np.array(
[
[-3, -3, 0],
[+3, -3, 0],
[+3, +3, 0],
[-3, +3, 0],
[+0, +0, +3]
]
)
hull = spatial.ConvexHull(vertices)
faces = hull.simplices

faces 数组包含以下面描述:

array([
[4, 1, 0],
[4, 2, 1],
[3, 4, 0],
[3, 4, 2],
[3, 2, 1],
[3, 1, 0]
], dtype=int32)

2.2 Faces

面列表。 每个三角形面由三个顶点(点)描述。 换句话说,顶点数组中点的位置。

例如,最后一个面包含数字 3, 1, 0。因此面由顶点数组的第 0、1 和 3 个元素的点组装而成:

在这里插入图片描述

2.3 Mesh

网格是顶点和面的集合,确定多面体对象的形状。

myramid_mesh = mesh.Mesh(
  np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)
)
for i, f in enumerate(faces):
  for j in range(3):
    myramid_mesh.vectors[i][j] = vertices[f[j],:]
    plot_mesh(myramid_mesh)

在这里插入图片描述

从图中可以看出,金字塔的一面是上下颠倒的。 在下面的例子中,在构造分形时,不会使用ConvexHull方法,因为它以任意顺序排列面的点,这会导致某些面的翻转。

myramid_mesh.save('numpy_stl_example_02.stl')

要查看 STL 文件,可以使用Blender,或者直接使用STL在线预览工具:

在这里插入图片描述

space.convexhull方法被设计用于计算凸壳,并且可以很好地应对金字塔和立方体。 但在有空腔的物体中,由于点的数量不一致,在组装STL时会丢失部分点,从而出现错误。

这在二维示例中清晰可见:numpy_stl_example_03.ipynb

import matplotlib.pyplot as plt
from scipy import spatial
import numpy as np
points = np.array([
[0,0],
[-2,0],
[-2,2],
[0,1.5],
[2,2],
[2,0]
])
hull = spatial.ConvexHull(points)

hull.simplices 包含面描述:

array([
[2, 1],
[2, 4],
[5, 1],
[5, 4]
], dtype=int32)

让我们绘制顶点和面:

plt.plot(points[:,0], points[:,1], 'o')
for simplex in hull.simplices:
  plt.plot(points[simplex, 0], points[simplex, 1], 'k-')

在这里插入图片描述

对于这种情况,可以找到凸包的替代方案,或者手动描述边:

faces = np.array([
[0, 1],
[1, 2],
[2, 3],
[3, 4],
[4, 5],
[5, 0]
])
plt.plot(points[:,0], points[:,1], 'o')
for simplex in faces:
  plt.plot(points[simplex, 0], points[simplex, 1], 'k-')

在这里插入图片描述

3、Numpy-stl构建分形

是时候构建一个分形了。 Numpy-stl 中没有布尔减法函数。 为了构建门格尔海绵分形,我们采取了相反的做法。 有两种方法:

  • 构建基本立方体网格。 我们称之为体素。
  • 将多个体素组合成一个网格。

我们将从立方体构建分形,就像从构造函数一样。

构造分形的逻辑描述:

假设分形面长度为1。分形深度是唯一孔尺寸的数量。 体素长度取决于分形的深度,每个新的深度级别都会除以 3。
我们将找到深度为 1 和 2 的体素边。让我们简化任务,将分形从 3 维变为 1 维情况:

在这里插入图片描述

如果分形级别为 2,则立方体边长将为 1 / (3 ** 2),相当于 1/9。 让我们制作一组立方体,以便它们按其位置填充生成的体素立方体。 我们来计算一下孔面积。 排除孔中的体素。 总之,将剩余的体素合并到一个对象中并保存。
示例:numpy_stl_example_04.ipynb

在这里插入图片描述

4、Numpy-stl渲染

为了渲染图像,我们将从 STL 文件加载的网格发送到plot_mesh 函数。

示例:numpy_stl_example_05.ipynb

在这里插入图片描述

5、PyMesh概述

不幸的是,Pymesh 库无法通过 PIP 包管理器安装,尽管文档中描述了这种方法,也无法通过 Anaconda 安装。 有两种安装方法。

按照说明,从源代码进行编译。
使用docker容器。 我选择这个选项是因为更有趣。 容器使用参数启动。 使用启动参数,将脚本文件夹装载到容器中。 让我们为脚本提供必要的参数。 脚本执行完成后,容器将被删除。
如果Docker已经按照文章开头的说明安装,则无需再安装。如果 Docker 不适合你,请按照文档中的说明编译 Pymesh。 这个选项也经过我的测试。

示例:pymesh_example_01.py

import pymesh
box_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)

从项目根目录启动容器:

sh pymesh_example_01.sh

执行上述命令后:

  • Pymesh 容器启动。 初次启动镜像下载需要一些时间。
  • Pymesh_examples 文件夹安装在容器内。
  • Python 脚本在容器内启动: /pymesh_examples/pymesh_example_01.py
  • Pymesh 库已导入。
  • generate_box_mesh 函数根据点 [0,0,0] 和 [1,1,1] 处的两个相对顶点生成立方体。
  • Save_Mesh 函数将对象保存在 STL 文件中。

执行后, pymesh_examples文件夹中出现 pymesh_example_01.stl文件。
在这里插入图片描述

让我们使用布尔减法来制作一个方孔。 我们要构建一个平行六面体并将其从主立方体中减去。

示例:pymesh_example_02.py

import pymesh
box_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)

运行程序:

sh pymesh_example_02.sh

在这里插入图片描述

布尔函数很简单。 第一个参数是我们从中减去的对象。 其次是我们做减法。 我们还发送操作和引擎。

布尔值不仅适用于减法。 总共有 4 种操作可用:

  • 交:A∩B
  • 并:A∪B
  • 差:A∖B(最后两个例子)
  • 异或:A XOR B(图像未显示)

在这里插入图片描述

为了更好地理解如何移动和旋转对象,出于调试目的,可以方便地暂时用 Union 代替 Difference 操作。

让我们制作第二个孔,移动并旋转它。

示例:pymesh_example_03.py

运行:

sh pymesh_example_03.sh

我们的脚本包含了移动和旋转函数。 通过移动,会根据原始对象修改后的顶点和面创建一个新的网格对象。四元数类描述旋转,然后根据原始对象的顶点和面以及旋转的描述创建一个新的旋转对象。

脚本执行的结果是一个带有两个相交孔的立方体:

在这里插入图片描述

这些工具足以构建分形。

6、PyMesh构建分形

示例:pymesh_example_04.py

在此脚本中,我们添加了一个输入参数来设置分形深度。 对于每个深度级别,创建一个框,复制两次,然后旋转和偏移。 结果只有 3 个平行六面体,这是从主立方体中减去的。 每条边各一个。 此操作重复 x 和 y 次以填充所有行和列边缘。 未执行从空白空间中减去的检查。

这次我们必须明确指定分形的深度:

sh pymesh_example_04.sh 3

需要 5 至 15 分钟才能完成。 启动后,新的STL文件将出现在 pymesh_examples文件夹中:
在这里插入图片描述

请求 4 级分形,组装大约需要 4 小时,文件大小为 73 mb:
在这里插入图片描述

3D打印后就是这样:
在这里插入图片描述

7、PyMesh渲染

上次我们旋转了网格。 这次让我们旋转相机。

示例:pymesh_example_05.py

运行程序:

sh pymesh_example_05.sh

在这里插入图片描述

8、PyTorch3d概述

金字塔示例:pytorch3d_example_01.py

方法与 numpy-stl 中使用的方法非常相似。 但由于它应该在 GPU 上工作,因此我们将主机和设备的概念分开。

  • 主机就是我们的电脑。
  • 设备是显卡。如果你没有显卡,仍然可以使用库,那么CPU将充当GPU。

主机和设备都有自己的内存。 要将项目从主机传输到设备并传回,我们需要执行一个小仪式。

在下面的例子中,我们立即描述设备上的顶点,将它们从设备复制到主机。 基于顶点计算的边。 然后保存该对象。 生成的 OBJ 文件可以导入到Blender中:
在这里插入图片描述

注意命令 verts.cpu().numpy()

顶点从设备复制到主机。 如果使用 GPU,每个副本都会减慢算法速度。 在规划程序架构时,最好将主机和设备之间的复制操作次数尽可能减少。 例如,如果你最初在主机上有一个顶点列表,则可以计算面,而无需将顶点从设备复制到主机,如下一个示例中所示。

示例:pytorch3d_example_02.py

在这里插入图片描述

9、PyTorch3d构建分形

GPU 提供了一些性能提升。

示例:pytorch3d_example_03.py

我们声明了指定深度级别的最小体素的顶点。 使用与前面的示例相似的算法,我们计算二维的孔坐标。 然后用不会落入孔中的体素填充主立方体。
在这里插入图片描述

计算速度提高了一个数量级,这使得在大约 5 小时内构建 5 级分形成为可能:
在这里插入图片描述

此 STL 文件的大小为 1.9 GB。 在构建第 5 层分形时,由于显卡内存溢出,程序停止。 我必须分批收集该物体。 创建了 10 层“2D”分形,然后将它们附加到主要对象上,直到构建完整的分形。

10、PyTorch3d渲染

除了绘图可视化之外,pytorch3d 还特别关注渲染。 而且这种方法非常彻底,有纹理和着色器。

示例:pytorch3d_example_04.py
在这里插入图片描述

11、SolidPython概述

SolidPython 是目前最丰富的建模库。 3D场景,描述格式,与openscad非常相似。 Python 生成写入 scad 文件的 openscad 代码。 然后可以在openscad中编辑或立即保存为STL。

示例:solidpython_example_01.ipynb

from solid import *
d = difference()(
  cube(size = 10, center = True),
  sphere(r = 6.5, segments=300)
)
path = scad_render_to_file(d, 'solidpython_example_01.scad')

为了指定球体的分辨率,我们使用 word segment,而不是通常的 $fn openscad 参数。
在这里插入图片描述

Solidpython 方便调试。

  • 在屏幕的一侧,我们打开了 scad 文件。
  • 在另一边,我们打开了 Jupyter Notebook。

在 Jupyter Notebook 中执行 scad_render_to_file 后,openscad 中的图片会自动更新。

Openscad 可以使用控制台命令将模型渲染为 stl 文件。 Jupyter 笔记本中有调用示例:

!openscad solidpython_example_01.scad -o solidpython_example_01.stl

在这里插入图片描述

任何 openscad 函数都会返回一个对象。

要对对象执行操作,请在操作调用字符串末尾的圆括号中传递对象或对象列表。

示例:solidpython_example_02.ipynb

from solid import *
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')

分辨率由切片参数决定。
在这里插入图片描述

12、SolidPython构建分形

示例:solidpython_example_03.ipynb
在这里插入图片描述

13、SolidPython渲染

让我们通过相机在每个图像上旋转来渲染最后一个场景的一系列图像。

示例:solidpython_example_04.ipynb

在这里插入图片描述

此外,solidpython 还提供使用 openscad 的动画生成功能。 文档中有一小节带有示例。

最后,让我们看一下本文标题中用于构建场景的代码。

示例:solidpython_example_05.ipynb

14、PyVista

我还想提一下另一个有趣的 PyVista 库。

通过可视化工具包 (VTK) 的简化界面进行 3D 绘图和网格分析

他通过从 STL 文件读取网格来帮助我可视化深度图。 但除此之外,它还有一些其他有趣的功能。

在这里插入图片描述

15、库比较

目前的性能比较并不完全客观,因为算法存在显着差异。 Pymesh 和 SolidPython 使用减法,而 Numpy-stl 和 Pytorch3d 使用网格并集。

在这里插入图片描述

我的机器配置如下:

  • Ubuntu 20.04.2 LTS
  • Python 3.7.3
  • 英特尔® 酷睿™ i3-7350K CPU @ 4.20GHz
  • 内存 35.2Gb
  • GPU GeForce GTX 1080 Ti 11175 MB

原文链接:Python 3D建模入门 — BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1191767.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

overflow: auto滚动条跳到指定位置

点击对应模块跳转页面,滚动到对应模块,露出到可视范围 代码: scrollToCurrentCard() {// treeWrapper是包裹多个el-tree组件的父级元素,也是设置overflow:auto的元素let treeWrapper document.getElementsByClassName(treeWrapp…

Kafka JNDI 注入分析(CVE-2023-25194)

Apache Kafka Clients Jndi Injection 漏洞描述 Apache Kafka 是一个分布式数据流处理平台,可以实时发布、订阅、存储和处理数据流。Kafka Connect 是一种用于在 kafka 和其他系统之间可扩展、可靠的流式传输数据的工具。攻击者可以利用基于 SASL JAAS 配置和 SAS…

赞不绝口!飞凌嵌入式全新子品牌ElfBoard好评如潮

飞凌嵌入式凭借十多年的企业级板卡开发与服务经验,深挖嵌入式学习市场的需求和痛点推出全新子品牌ElfBoard,旨在为嵌入式学习爱好者创造更具价值的学习体验。 ElfBoard旗下ELF 1及ELF 1S两款新品已经上市1个月了,两款开发板产品凭借高性价比…

假如我们进入了时间循环,那么如何在时间循环里做最优决策?

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

温湿度监测更方便,食品物流很多都这样做!

在当今高度技术化的社会,温度监控不仅仅是一项科技应用,更是各行各业中确保稳定运作和产品质量的重要环节。 温度监控系统的应用不仅有助于维护生产条件,提高效率,还对确保产品质量和符合行业标准起着至关重要的作用。 客户案例 …

直播实时数仓基于DataLeap开放平台在发布管控场景的业务实践

更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 背景 业务背景 随着字节业务的高速增长,业务场景越来越丰富,业务基于数据做的决策也越来越多,对数据的时效性要求也越来越高。…

CSDN中调整图片和文本样式

1.调整图片比例 插入图片后,觉得图片比例不协调,想改小点。只需要在文件后缀加个参数即可:?pic_center 60x。 NOTE:等号左边一定要加个空格,否则格式不生效 2.修改字体颜色 如上 NOTE:等号左边一定要…

搭建完全分布式Hadoop

文章目录 一、Hadoop集群规划二、在主节点上配置Hadoop(一)登录虚拟机(二)设置主机名(三)主机名与IP地址映射(四)关闭与禁用防火墙(五)配置免密登录&#xff…

Linux Centos配置邮件发送

Linux Centos配置邮件发送 这里使用的是外部发送邮件方式,也就是使用自己的账号发送 第一步 首先要开启STMP授权码,以QQ邮箱为例 配置文件 vim /etc/mail.rc找到之后在最下面添加如下 #邮箱set from3324855376qq.com #默认smtp发送,stmp…

简单聊聊java中各种常量池

一 引子 小试身手 首先我们来看一道题 Integer i1 127; Integer i2 127;System.out.println(i1 i2); //这种调用底层实际是执行的Integer.valueOf(127),里面用到了IntegerCache对象池//值大于127时,不会从对象池中取对象 Integer i3 128; Integ…

4S店汽车行业万能通用小程序源码系统 在线预约试驾+购车计算器 源码完全开源可二次开发

随着互联网技术的发展和普及,越来越多的消费者开始依赖于互联网进行消费。传统的汽车销售模式也正在经历着数字化转型,以适应消费者需求的变化。这款小程序源码系统就是为帮助汽车4S店等销售商实现数字化转型而开发的。 以下是部分核心功能的代码模块&a…

合成数据在医疗保健行业的案例研究

从机器人辅助手术到医学成像技术,人工智能在医疗保健领域的应用正在迅速改变医疗保健行业,并改善服务成本和服务质量。例如,埃森哲表示,到 150 年,人工智能临床健康应用每年可以为美国医疗保健行业节省 2026 亿美元。 …

C++中的函数重载:多功能而强大的特性

引言 函数重载是C编程语言中的一项强大特性,它允许在同一个作用域内定义多个同名函数,但这些函数在参数类型、个数或顺序上有所不同。本文将深入探讨函数重载的用法,以及它的优势和应用场景。 正文 在C中,函数重载是一项非常有…

Spring Security使用总结八,Security的第二个功能授权,不同的角色访问不同的资源

前面五章基本都是给认证做铺垫的,这一章是security的另一个硬菜:授权,你在我这里注册,成为唯爱痞,我给你个令牌,你可以访问我资源,但是不能所有资源都给你,于是就有了授权,你只能访问我让你访问的资源,我不让你访问的资源,你一点都别想看。这里就出现了角色,不同的…

一个不用充钱也能让你变强的 VSCode 插件!!!

今天给大家推荐一款不用充钱也能让你变强的 vscode 插件 通义灵码(TONGYI Lingma),可以称之为 copilot 的替代甜品 💪 前言 之前一直使用的 GitHub Copilot,虽然功能强大,但是收费相对来说有点贵&#xf…

C 语言 while 和 do...while 循环

在本教程中,您将在示例的帮助下学习在C语言编程中创建while和do ... while循环。 在编程中,循环用于重复代码块,直到满足指定条件为止。 C语言编程具有三种类型的循环。 for循环 while循环 do... while循环 在上一教程中,我…

解决:AttributeError: ‘WebDriver‘ object has no attribute ‘find_element_by_xpath‘

解决:AttributeError: ‘WebDriver’ object has no attribute ‘find_element_by_xpath’ 背景 在使用之前的代码通过selenium定位元素时,报错:selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to l…

vioovi的ECRS工时分析软件:食品加工行业的生产效率提升利器

在食品加工行业,提高生产效率、降低成本、优化资源配置是至关重要的。随着科技的不断发展,越来越多的企业开始借助先进的软件工具来助力生产管理。本文将介绍一款备受食品加工企业青睐的工业工程软件——vioovi的ECRS工时分析软件,并探讨其如…

dapp技术开发

随着区块链技术的普及和应用,DApp(去中心化应用)逐渐成为了区块链领域中备受关注的核心部分。DApp是一种运行在去中心化网络上的应用程序,其开发、部署和运行都不依赖于任何中心化的实体或中介机构。这种应用程序的兴起和发展&…

基于springboot 手工艺品在线展示系统-计算机毕设 附源码 42553

springboot 手工艺品在线展示系统 目 录 摘要 1 绪论 1.1本课题研究意义 1.2系统开发目的 2 1.3系统开发技术的特色 3 1.4 springboot框架介绍 3 1.5论文结构与章节安排 4 2 手工艺品在线展示系统系统分析 5 2.1 可行性分析 5 2.2 系统流程分析 5 2.2.1数据增加流程 5 2.2.…