3D模型处理的并行化
今天我们将讨论如何使用 Python 多进程来处理大量3D数据。 我将讲述一些可能在手册中找到的一般信息,并分享我发现的一些小技巧,例如将 tqdm
与多处理 imap
结合使用以及并行处理存档。
那么我们为什么要诉诸并行计算呢? 使用数据有时会出现与大数据相关的问题。 每次我们遇到 RAM 不适合的数据时,我们都需要逐段处理它。 幸运的是,现代编程语言允许我们生成在多核处理器上完美工作的多个进程(甚至线程)。注意:这并不意味着单核处理器无法处理多处理,这是有关该主题的 Stack Overflow 讨论。
今天我们将尝试计算网格和点云之间的距离这一常见的 3D 计算机视觉任务。 例如,当你需要在所有可用网格中查找定义与给定点云相同的 3D 对象的网格时,可能会遇到此问题。
我们的数据由存储在 .7z 存档中的 .obj 文件组成,这在存储效率方面非常出色。 但是当我们需要访问它的确切部分时,我们应该付出努力。 在这里,我定义了包装 7-zip 存档并提供底层数据接口的类。
from io import BytesIO
import py7zlibclass MeshesArchive(object):def __init__(self, archive_path):fp = open(archive_path, 'rb')self.archive = py7zlib.Archive7z(fp)self.archive_path = archive_pathself.names_list = self.archive.getnames()def __len__(self):return len(self.names_list)def get(self, name):bytes_io = BytesIO(self.archive.getmember(name).read())return bytes_iodef __getitem__(self, idx):return self.get(self.names[idx])def __iter__(self):for name in self.names_list:yield self.get(name)
这个类几乎不依赖 py7zlib
包,它允许我们在每次调用 get 方法时解压缩数据,并为我们提供存档内的文件数量。 我们还定义了 __iter__
,它将帮助我们像在可迭代对象上一样在该对象上启动多处理映射。
这个定义为我们提供了迭代存档的可能性,但它是否允许我们并行随机访问内容? 这是一个有趣的问题,我在网上没有找到答案,但如果深入研究 py7zlib 的源代码,我们可以回答它。
在这里,我提供了 pylzma 的代码片段:
class Archive7z(Base):def __init__(self, file, password=None):# ...self.files = {}# ...for info in files.files:# create an instance of ArchiveFile that knows location on diskfile = ArchiveFile(info, pos, src_pos, folder, self, maxsize=maxsize)# ...self.files.append(file)# ...self.files_map.update([(x.filename, x) for x in self.files])# method that returns an ArchiveFile from files_map dictionarydef getmember(self, name):if isinstance(name, (int, long)):try:return self.files[name]except IndexError:return Nonereturn self.files_map.get(name, None)class Archive7z(Base):def read(self):# ...for level, coder in enumerate(self._folder.coders):# ...# get the decoder and decode the underlying datadata = getattr(self, decoder)(coder, data, level, num_coders)return data
摘自pylzma源码,省略了很多
我相信从上面的要点可以清楚地看出,只要同时多次读取存档,就没有理由被阻止。
接下来我们快速介绍一下什么是网格和点云。 首先是网格,它们是顶点、边和面的集合。 顶点由空间中的 (x,y,z)
坐标定义,并分配有唯一的编号。 边和面相应地是点对和三元组的组,并使用提到的唯一点 ID 进行定义。 通常,当我们谈论“网格”时,我们指的是“三角形网格”,即由三角形组成的表面。 使用 trimesh 库在 Python 中处理网格要容易得多,例如它提供了在内存中加载 .obj 文件的接口。 要在 Jupyter Notebook 中显示 3D 对象并与之交互,可以使用 k3d
库。
因此,通过以下代码片段,我回答了这个问题:“如何使用 k3d 在 jupyter 中绘制 atrimeshobject?”
import trimesh
import k3dwith open("./data/meshes/stanford-bunny.obj") as f:bunny_mesh = trimesh.load(f, 'obj')plot = k3d.plot()
mesh = k3d.mesh(bunny_mesh.vertices, bunny_mesh.faces)
plot += mesh
plot.display()
k3d 显示的斯坦福兔子网格(不幸的是这里没有响应)
其次,点云,它们是表示空间中物体的 3D 点阵列。 许多 3D 扫描仪生成点云作为扫描对象的表示。 为了演示目的,我们可以读取相同的网格并将其顶点显示为点云。
import trimesh
import k3dwith open("./data/meshes/stanford-bunny.obj") as f:bunny_mesh = trimesh.load(f, 'obj')plot = k3d.plot()
cloud = k3d.points(bunny_mesh.vertices, point_size=0.0001, shader="flat")
plot += cloud
plot.display()
将顶点绘制为点云
k3d绘制的点云
正如上面提到的,3D 扫描仪为我们提供了点云。 假设我们有一个网格数据库,并且希望在数据库中找到与扫描对象(即点云)对齐的网格。 为了解决这个问题,我们可以提出一种简单的方法。 我们将搜索给定点云的点与存档中的每个网格之间的最大距离。 如果对于某些网格来说,1e-4 的距离较小,我们会认为该网格与点云对齐。
最后,我们来到了多处理部分。 请记住,我们的存档有大量文件可能无法同时放入内存中,我们更喜欢并行处理它们。 为了实现这一点,我们将使用多处理池,它使用 map
或 imap/imap_unordered
方法处理用户定义函数的多次调用。 map
和 imap
之间影响我们的区别在于, map
在发送到工作进程之前将可迭代对象转换为列表。 如果存档太大而无法写入 RAM,则不应将其解压到 Python 列表中。 在另一种情况下,它们的执行速度相似。
[Loading meshes: pool.map w/o manager] Pool of 4 processes elapsed time: 37.213207403818764 sec
[Loading meshes: pool.imap_unordered w/o manager] Pool of 4 processes elapsed time: 37.219303369522095 sec
在上面你可以看到从适合内存的网格存档中进行简单读取的结果。
使用 imap
更进一步。 让我们讨论如何实现找到靠近点云的网格的目标。 这是数据,我们有来自斯坦福模型的 5 个不同的网格。 我们将通过向斯坦福兔子网格的顶点添加噪声来模拟 3D 扫描。
import numpy as np
from numpy.random import default_rngdef normalize_pc(points):points = points - points.mean(axis=0)[None, :]dists = np.linalg.norm(points, axis=1)scaled_points = points / dists.max()return scaled_pointsdef load_bunny_pc(bunny_path):STD = 1e-3 with open(bunny_path) as f:bunny_mesh = load_mesh(f)# normalize point cloud scaled_bunny = normalize_pc(bunny_mesh.vertices)# add some noise to point cloudrng = default_rng()noise = rng.normal(0.0, STD, scaled_bunny.shape)distorted_bunny = scaled_bunny + noisereturn distorted_bunny
当然,我们之前对下面的点云和网格顶点进行了标准化,以在 3D 立方体中缩放它们。
为了计算点云和网格之间的距离,我们将使用 igl
。 为了最终确定,我们需要编写一个将在每个进程及其依赖项中调用的函数。 让我们用下面的片段来总结一下。
import itertools
import timeimport numpy as np
from numpy.random import default_rngimport trimesh
import igl
from tqdm import tqdmfrom multiprocessing import Pooldef load_mesh(obj_file):mesh = trimesh.load(obj_file, 'obj')return meshdef get_max_dist(base_mesh, point_cloud):distance_sq, mesh_face_indexes, _ = igl.point_mesh_squared_distance(point_cloud,base_mesh.vertices,base_mesh.faces)return distance_sq.max()def load_mesh_get_distance(args):obj_file, point_cloud = args[0], args[1]mesh = load_mesh(obj_file)mesh.vertices = normalize_pc(mesh.vertices)max_dist = get_max_dist(mesh, point_cloud)return max_distdef read_meshes_get_distances_pool_imap(archive_path, point_cloud, num_proc, num_iterations):# do the meshes processing within a poolelapsed_time = []for _ in range(num_iterations):archive = MeshesArchive(archive_path)pool = Pool(num_proc)start = time.time()result = list(tqdm(pool.imap(load_mesh_get_distance,zip(archive, itertools.repeat(point_cloud)),), total=len(archive)))pool.close()pool.join()end = time.time()elapsed_time.append(end - start)print(f'[Process meshes: pool.imap] Pool of {num_proc} processes elapsed time: {np.array(elapsed_time).mean()} sec')for name, dist in zip(archive.names_list, result):print(f"{name} {dist}")return resultif __name__ == "__main__":bunny_path = "./data/meshes/stanford-bunny.obj"archive_path = "./data/meshes.7z"num_proc = 4num_iterations = 3point_cloud = load_bunny_pc(bunny_path)read_meshes_get_distances_pool_no_manager_imap(archive_path, point_cloud, num_proc, num_iterations)
这里 read_meshes_get_distances_pool_imap
是一个核心函数,其中完成了以下操作:
MeshesArchive
和multiprocessing.Pool
已初始化- 应用
tqdm
来监视池进度,并手动完成整个池的分析 - 执行结果的输出
请注意我们如何将参数传递给 imap
,使用 zip(archive, itertools.repeat(point_cloud))
从 archive
和 point_cloud
创建新的可迭代对象。 这使我们能够将点云数组粘贴到存档的每个条目,从而避免将存档转换为列表。
执行结果如下所示:
100%|####################################################################| 5/5 [00:00<00:00, 5.14it/s]
100%|####################################################################| 5/5 [00:00<00:00, 5.08it/s]
100%|####################################################################| 5/5 [00:00<00:00, 5.18it/s]
[Process meshes: pool.imap w/o manager] Pool of 4 processes elapsed time: 1.0080536206563313 sec
armadillo.obj 0.16176825266293382
beast.obj 0.28608649819198073
cow.obj 0.41653845909820164
spot.obj 0.22739556571296735
stanford-bunny.obj 2.3699851136074263e-05
我们可以发现斯坦福兔子是最接近给定点云的网格。 还可以看出,我们没有使用大量数据,但我们已经证明,即使存档中有大量网格,该解决方案也能发挥作用。
多重处理使数据科学家不仅在 3D 计算机视觉方面而且在机器学习的其他领域都取得了出色的表现。 理解并行执行比循环内执行要快得多,这一点非常重要。 尤其是当算法编写正确时,差异变得非常显着。 大量数据揭示的问题如果没有创造性的方法来利用有限的资源就无法解决。 幸运的是,Python 语言及其丰富的库可以帮助我们数据科学家解决此类问题。
相关文章:

3D模型处理的并行化
今天我们将讨论如何使用 Python 多进程来处理大量3D数据。 我将讲述一些可能在手册中找到的一般信息,并分享我发现的一些小技巧,例如将 tqdm 与多处理 imap 结合使用以及并行处理存档。 那么我们为什么要诉诸并行计算呢? 使用数据有时会出现…...

盲人安全导航技巧:科技赋能让出行更自如
作为一名资深记者,长期关注并报道无障碍领域的发展动态。今日,我将聚焦盲人安全导航技巧,探讨这一主题下科技如何赋能视障人士实现更为安全、独立的出行。一款融合了实时避障、拍照识别物体及场景功能的盲人出行辅助应用叫做蝙蝠避障…...
问,由于java存在性能上,以及部分功能上的缺点,请问如何正确使用C,C++,Go,这三个语言,提升Java Web项目的性能?
拓展阅读:版本任你发,我用java8 我明白Java虽然在许多方面表现出色,但在某些特定场景下可能会遇到性能瓶颈或功能限制。为了提升Java Web项目的性能,可以考虑将C、C和Go这三种语言用于特定的组件或服务。以下是如何正确使用这些语…...
【信号与系统 - 9】傅里叶变换的性质习题
1 习题 已知 f ( t ) f(t) f(t) 的傅里叶变换为 F ( j w ) F(jw) F(jw) ,求如下信号的傅里叶变换 (1) t ⋅ f ( 3 t ) t\cdot f(3t) t⋅f(3t) 解: f ( 3 t ) ↔ 1 3 F ( j w 3 ) f(3t)\leftrightarrow \frac{1}{3}F(j\frac{w}…...
C#探索之路基础夯实篇(5):语法糖概念解析
C#探索之路基础夯实篇(5):语法糖概念解析 文章目录 C#探索之路基础夯实篇(5):语法糖概念解析1、概念定义2、Lua中的语法糖3、C#中的语法糖4、C中的语法糖5、优缺点辨析6、适用范围7、总结 从之前一开始接触lua的时候开始,开始第一次接触到语法…...

SeaTunnel 与 DataX 、Sqoop、Flume、Flink CDC 对比
产品概述 Apache SeaTunnel 是一个非常易用的超高性能分布式数据集成产品,支持海量数据的离线及实时同步。每天可稳定高效同步万亿级数据,已应用于数百家企业生产,也是首个由国人主导贡献到 Apache 基金会的数据集成顶级项目。 SeaTunnel 主要解决数据集成领域的常见问题:…...
深入理解汇编:平栈、CALL和RET指令详解
视频学习下载地址:https://pan.quark.cn/s/04e6946a803a 汇编语言以其接近硬件的特性和高效的执行速度,在系统编程、性能优化和逆向工程中占有不可或缺的地位。本文将深入探讨汇编语言中的平栈操作以及CALL和RET指令&#…...

DP4 最小花费爬楼梯
原题链接:最小花费爬楼梯_牛客题霸_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 dp。 开一个dp数组和a数组。dp[i]表示在当前这一格所需要的费用,a数组其实就是题目中的cost数组。 因为最后要求到顶楼的最低费用&a…...
OpenXR API概览与核心组件解析
在虚拟现实(VR)和增强现实(AR)领域,OpenXR API提供了一个重要的开放标准,使得开发者能够跨多种硬件和软件平台创建兼容的应用。本文将详细解释OpenXR中的核心组件和数据结构,并探讨它们如何共同…...

安装指定版本的ant-design-vue和指定版本的@ant-design/icons-vue 图标组件包
前言: 最近在完成公司的项目时,为了兼容其他的版本,需要安装指定版本的ant-design-vue和ant-design/icons-vue 图标组件包,安装成功之后,分享如下: 安装命令: ant-design-vue: 不…...
Zynq7000系列中的休眠模式
休眠模式是在系统层面定义的,它包括将APU置于待机模式,并将多个控制器保持在无时钟的复位状态。 进入休眠模式可以大大降低功耗。在休眠模式下,大多数功能时钟组都会被关闭或断电。唯一需要保持活动的设备是一个CPU、窥探控制单元(…...
在redhat7/8平台上部署ELK7.17.18的技术方案
部署环境说明 为节省资源直接使用1台测试机模拟3节点elasticsearch服务集群做部署,在该主机上同时部署了3个elasticsearch实例、1个logstash实例、1个kibana实例、1个filebeat实例。对于生产环境,以上实例服务应该做分布式部署。 ELK-TEST1 192.168.10…...
(Chat For Al,创新Al,汇语Al助手,AiTab新标签,万能助手,LLaVA)分享6个好用的ChatGPT
目录 1、Chat For AI 2、创想AI 3、汇语AL助手...
MySQL-锁篇
文章目录 表级锁和行级锁了解吗?有什么区别?行级锁使用有什么注意事项?InnoDB有哪几类行锁?共享锁和排他锁是什么?意向锁有什么用? 锁是一种常见的并发事务的控制方式 表级锁和行级锁了解吗?有什…...

滤波器笔记(杂乱)
线性相位是时间平移,相位不失真 零、基础知识 1、用相量表示正弦量 https://zhuanlan.zhihu.com/p/345546880 https://www.zhihu.com/question/347763932/answer/1103938667 A s i n ( ω t θ ) ⇔ A e j θ ⇔ A ∠ θ Asin(\omega t\theta) {\Leftrightarrow…...

【ARFoundation自学01】搭建AR框架,检测平面点击位置克隆物体
Unity开发ARFoundation相关应用首先安装ARFoundation包 然后设置XR 1.基础AR场景框架搭建 2.一个基本的点击克隆物体到识别的平面脚本 挂在XROrigin上 脚本AppController 脚本说明书 ## 业务逻辑 AppController 脚本旨在实现一个基本的 AR 应用程序功能:用户通过…...
.Net ajax 接收参数
后端部分代码 一般处理程序 public void ProcessRequest(HttpContext context){context.Response.ContentType "text/plain";string str_index context.Request.Form.AllKeys.Contains("index") ? context.Request.Form["index"].ToString(…...

智能零售:引领购物新时代
智能零售通过整合人工智能、物联网、大数据和机器学习等技术,正在彻底改变传统的购物模式,为消费者和零售商提供前所未有的效率和个性化体验。 智能零售利用消费者数据分析来提供个性化的购物推荐。无论是在线平台或是实体店内,智能系统都能…...

【AIGC】AIGC在虚拟数字人中的应用:塑造未来互动体验的革新力量
🚀 🚀 🚀随着科技的快速发展,AIGC已经成为引领未来的重要力量。其中,AIGC在虚拟数字人领域的应用更是引起了广泛关注。虚拟数字人作为一种先进的数字化表达形式,结合了3D建模、动画技术、人工智能等多种先进…...

电机控制器电路板布局布线参考指导(五)
电机控制器电路板布局布线参考指导(五)大容量电容和旁路电容的放置 1.大容量电容的放置2.电荷泵电容器3.旁路电容/去耦电容的放置3.1 靠近电源3.2 靠近功率器件3.3 靠近开关电流源3.4 靠近电流感测放大器3.5 靠近稳压器 tips:资料主要来自网络…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...