Python实战点云并行化处理

LAS 及其压缩版本 LAZ 是用于存储点云信息的流行文件格式,通常由 LiDAR 技术生成。 LiDAR(即光探测和测距)是一种遥感技术,用于测量距离并创建物体和景观的高精度 3D 地图。存储的点云信息主要包括X、Y、Z坐标、强度、颜色、特征分类、GPS时间以及扫描仪提供的其他自定义字段。 LAS 文件包含数百万个点,可以准确描述感知的环境或物体,这使得其分析成为一项具有挑战性的任务。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割

处理和分析 3D 数据的基本步骤之一是计算法线。点云中的法线提供有关点云中每个点处的表面方向和方向的信息。这些信息对于可视化、对象识别和形状分析至关重要。

我们不会深入研究如何计算这些法线或使用哪个包的细节。相反,本文的重点是演示如何在对 LAS/LAZ 文件进行分块读取和分块写入时执行并行计算,以及 Python 如何应对并发和并行性的挑战。

要继续学习,你应该对 Python 有一定的了解,并熟悉 numpy 和 laspy。本文对 Python 中的并行性进行了高级概述。

[packages]
numpy = "==1.26.0"
laspy = {extras = ["lazrs"], version = "==2.5.1"}[requires]
python_version = "3.10"

laspy 和 numpy 都是直接与 Python C_API 交互的包,使得它们速度极快。如果不采用直接 C 编程,速度方面没有太大的改进空间。因此,我们需要探索使用代码的新方法,以实现并行性或增强处理管道,以充分利用机器的潜力。

你可能知道也可能不知道,Python 的执行受到全局解释器锁 (GIL) 的限制。 GIL 是 CPython 解释器使用的一种机制,用于确保一次只有一个线程执行 Python 字节码。这简化了实现并使 CPython 的对象模型能够安全地防止并发访问。

虽然 GIL 为多线程程序和单核、单进程性能提供了简单性和优势,但它提出了一些问题:如果多个线程不能同时执行,为什么要使用多线程?是否可以与Python并行执行代码?

多线程是一种使 Python 非阻塞的方法,允许我们创建同时启动多个任务的代码,即使在任何给定时刻只能执行一个任务。当调用外部 API 或数据库(您大部分时间都在等待)时,这种类型的并发非常有用。然而,对于 CPU 密集型任务,这种方法有局限性。

为了并行运行 Python 代码,多处理库使用操作系统 API 调用在不同内核上生成单独的进程。

spawn 是 MacOS 和 Windows 中的默认方法。它创建子进程,继承运行对象的 run() 方法所需的资源。尽管比其他方法(如 fork)慢,但它提供了一致的执行。

fork 是除 MacOS 之外的所有 POSIX 系统中的默认方法。它使用父进程的所有上下文和资源创建子进程。它比 spawn更快,但在多进程和多线程环境中可能会遇到问题。

这种方法允许我们为每个处理器提供一个新的 Python 解释器,从而消除了多个线程争夺解释器可用性的问题。

鉴于点云处理严重依赖 CPU 性能,我们采用多处理来并行执行正在读取的点云的每个块的进程。

为了读取大型 LAS/LAZ 文件, laspy 提供了 chunk_iterator,用于读取数据块中的点云,这些数据块可以发送到不同的进程进行处理。随后,处理后的数据被组装并按块写回到另一个文件中。为了实现这一目标,我们需要两个上下文管理器:一个用于读取输入文件,另一个用于写入输出文件。

你通常会这样做:

import laspy
import numpy as np# reading the file
with laspy.open(input_file_name, mode="r") as f:# creating a filewith laspy.open(output_file_name, mode="w", header=header) as o_f:# iteration over the chunk iteratorfor chunk in f.chunk_iterator(chunk_size):# Normals calculation over each chunkpoint_record = calculate_normals(chunk)# writting or appending the data into the point cloudo_f.append_points(point_record)

为了并行化这个过程,我们创建了一个 ProcessPoolExecutor,它允许我们将函数的每次执行(计算法线的地方)发送到一个单独的进程。过程完成后,我们收集结果并将其写入新的 LAS/LAZ 文件。

由于我们在主进程中收集 future 的结果,然后将它们写入文件,因此我们避免了多个进程同时访问同一文件的问题。如果你的实现不允许这种方法,可能需要使用锁来确保数据完整性。

import laspy
import numpy as np
import concurrent.futures# reading the file
with laspy.open(input_file_name, mode="r") as f:# creating an output filewith laspy.open(output_file_name, mode="w", header=f.header) as o_f:# this is where we are going to collect our future objectsfutures = []with concurrent.futures.ProcessPoolExecutor() as executor:# iteration over the chunk iteratorfor chunk in f.chunk_iterator(chunk_size):# disecting the chunk into the points that conform itpoints: np.ndarray = np.array(((chunk.x + f.header.offsets[0])/f.header.scales[0],(chunk.y + f.header.offsets[1])/f.header.scales[1],(chunk.z + f.header.offsets[2])/f.header.scales[2],)).T# calculate the normals  in a multi processing poolfuture = executor.submit(process_points,   # function where we calculate the normalspoints=points,)futures.append(future)# awaiting all the future to complete in case we neededfor future in concurrent.futures.as_completed(futures):# unpacking the result from the futureresult = future.result()# creating a point record to store the resultspoint_record = laspy.PackedPointRecord.empty(point_format=f.header.point_format)# appending information to that point recordpoint_record.array = np.append(point_record.array,result)# appending the point record into the point cloudo_f.append_points(point_record)

这段代码中有很多东西需要展开解释,比如为什么我们不使用块对象本身?为什么我们要创建一个空的 PackedPointRecord

我们将从块对象开始。如果不触及原因,对象本身就无法发送到进程池中进行处理。因此,我们必须从中提取我们认为重要的信息。因为我们正在计算法线,所以我们需要的是块的 X、Y 和 Z 坐标,同时考虑到 LAS/LAZ 文件头中指定的偏移和比例。

鉴于计算返回一个值数组,该数组将表示 X、Y 和 Z 坐标、RGB 值、强度和分类,我们不能将其直接写入 LAS/LAZ 文件,我们需要创建一个 PackedPointRecord使用标头中指定的格式,我们将在其中存储返回的数组,然后将它们附加到 LAS/LAZ 文件中。

LAS/LAZ 文件有一个标头对象,我们在其中存储点云的比例、偏移和格式。这很重要,因为为了我们能够将信息发送到该文件,我们的值的格式必须与标头中指定的格式匹配。在我们的例子中,两个文件具有相同的标头格式。但是,如果你需要写入不同版本的文件,则数组格式必须与你要写入的版本匹配。

要确定能够将结果附加到 PackedPointRecord 中所需的格式,你可以运行以下命令:

>>> f.header.point_format.dtype()

在此示例中,我们使用 Point Format版本 3,其结构如下:

np.dtype([('X', np.int32),('Y', np.int32),('Z', np.int32),('intensity', np.int16),('bit_fields', np.uint8),('raw_classification', np.uint8),('scan_angle_rank', np.uint8),('user_data', np.uint8),('point_source_id', np.int16),('gps_time', np.float64),('red', np.int16),('green', np.int16),('blue', np.int16),
])

因为我们无法使用此命令来将解压后的 future 的 dtype 与 header 的 dtype 进行匹配。

>>> result = result.astype(header.point_format.dtype())

我们必须按以下方式进行转换:

def process_points(points: np.ndarray,
) -> np.ndarray:# normals calculationnormals, curvature, density = calculate_normals(points=points)# RGBred, green, blue = 255 * (np.abs(normals)).Tdtype = np.dtype([('X', np.int32),('Y', np.int32),('Z', np.int32),('intensity', np.int16),('bit_fields', np.uint8),('raw_classification', np.uint8),('scan_angle_rank', np.uint8),('user_data', np.uint8),('point_source_id', np.int16),('gps_time', np.float64),('red', np.int16),('green', np.int16),('blue', np.int16),])array = np.zeros(len(points), dtype=dtype)array['X'] = points[:, 0]array['Y'] = points[:, 1]array['Z'] = points[:, 2]array['intensity'] = densityarray['bit_fields'] = np.zeros(len(points), dtype=np.uint8)array['raw_classification'] = curvaturearray['scan_angle_rank'] = np.zeros(len(points), dtype=np.uint8)array['user_data'] = np.zeros(len(points), dtype=np.uint8)array['point_source_id'] = np.zeros(len(points), dtype=np.int16)array['gps_time'] = np.zeros(len(points), dtype=np.float64)array['red'] = redarray['green'] = greenarray['blue'] = bluereturn np.ascontiguousarray(array)

将所有这些放在一起,我们就能够使用计算机的所有资源并行处理大型点云。

尽管需要非常熟悉上述软件包才能理解和应用上面的代码,但我们的想法是解决我们在处理点云时遇到的常见问题之一,并分享我们找到的解决方案对于我们的问题。


原文链接:用Python并行化处理点云 - BimAnt

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

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

相关文章

博睿数据将出席ClickHouse Hangzhou User Group第1届 Meetup

2024年5月18日,博睿数据数智能力中心负责人李骅宸将受邀参加ClickHouse Hangzhou User Group第1届 Meetup活动,分享《ClickHouse在可观测性的应用实践和优化》的主题演讲。 在当前数字化浪潮下,数据的规模和复杂性不断攀升,如何高…

人大金仓报The connection attempt failed.Reason:Connection reset解决办法

在连接人大京仓数据库 的时候报下面的错误 解决办法: 更换这里的IP地址就行,不要用127.0.0.1,然后就可以了

XSS、CSRF、SSRF漏洞原理以及防御方式_xss csrf ssrf

这里写目录标题 XSS XSS攻击原理:XSS的防范措施主要有三个:编码、过滤、校正 CSRF CSRF攻击攻击原理及过程如下:CSRF攻击的防范措施: SSRF SSRF漏洞攻击原理以及方式SSRF漏洞攻击的防范措施 XMLXSS、CSRF、SSRF的区别 XSS、CSRF的…

成都百洲文化传媒有限公司电商服务的新领军者

在数字化浪潮席卷全球的今天,电商行业以其独特的魅力和无限的可能性,成为了推动经济发展的重要引擎。在这个竞争激烈的市场中,成都百洲文化传媒有限公司凭借其专业的电商服务和前瞻性的战略布局,正迅速崛起为行业的新领军者。 一…

图算法必备指南:《图算法:行业应用与实践》全面解读,解锁主流图算法奥秘!

《图算法:行业应用与实践》于近日正式与读者见面了! 该书详解6大类20余种经典的图算法的原理、复杂度、参数及应用,旨在帮助读者在分析和处理各种复杂的数据关系时能更好地得其法、善其事、尽其能。 全书共分为10章: 第1~3章主要…

PGP加密技术:保护信息安全的利器

随着数字化时代的到来,个人和企业对信息安全的需求日益增长。PGP(Pretty Good Privacy)加密技术作为一项强大的加密工具,为保护敏感数据提供了一种有效的方法。本文将探讨PGP加密技术的基本原理、应用场景以及其在现代信息安全中的…

Linux入门攻坚——22、通信安全基础知识及openssl、CA证书

Linux系统常用的加解密工具:OpenSSL,gpg(是pgp的实现) 加密算法和协议: 对称加密:加解密使用同一个秘钥; DES:Data Encryption Standard,数据加密标准&…

无人机运营合格证:民用无人机驾驶航空器运营合格证书

无人机运营合格证是指经国家相关部门审核通过并颁发给相应无人驾驶航空器运营机构的一种资质证明。获得该证书的机构具备相关的技术和管理能力,能够安全、合规地运营无人驾驶航空器。 无人机运营合格证的申请流程一般包括报名、培训学习、考试准备、考试报名、考试…

无人机+垂直起降:微型共轴双旋翼无人机技术详解

微型共轴双旋翼无人机技术是一种独特的无人机设计,它结合了垂直起降(VTOL)能力和微型无人机的灵活性。这种设计允许无人机在无需跑道的情况下垂直起降,并具备在空中悬停和执行各种飞行动作的能力。 适用于集群控制,荷载…

华为OD机试【全量和已占用字符集】(java)(100分)

1、题目描述 给定两个字符集合,一个是全量字符集,一个是已占用字符集,已占用字符集中的字符不能再使用。 2、输入描述 输入一个字符串 一定包含,前为全量字符集 后的为已占用字符集;已占用字符集中的字符一定是全量…

1756jsp农产品销售管理系统Myeclipse开发mysql数据库C2C模式java编程计算机网页项目沙箱支付

一、源码特点 java 农产品销售管理系统 是一套完善的web设计系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统采用web模式,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0…

压缩损失来源-量化噪声

压缩损失会以多种方式表现出来并会导致视觉损失。这里讨论最常见的压缩损失——量化噪声。量化是将大量输入值映射到较小集合的过程,如将输入值四舍五入为某个精度单位的值。 执行量化的设备或算法称为量化器。量化过程引入的舍入误差即量化误差或量化噪声。量化误差…

12个最强悍的数字孪生软件

数字孪生软件是一种尖端技术,可创建物理资产、系统或流程的虚拟表示。工程师、城市规划者、制造商和无数其他专业人士使用它来模拟、监控和分析数字环境中的真实场景。通过这样做,他们可以预测潜在问题、测试解决方案并简化操作,确保现实世界…

Linux网络编程(三)IO复用一 select系统调用

I/O复用使得程序能同时监听多个文件描述符。在以下场景中需要使用到IO复用技术: 客户端程序要同时处理多个socket,非阻塞connect技术客户端程序要同时处理用户输入和网络连接,聊天室程序TCP服务器要同时处理监听socket和连接socket服务器要同…

算法学习:数组 vs 链表

🔥 个人主页:空白诗 文章目录 🎯 引言🛠️ 内存基础什么是内存❓内存的工作原理 🎯 📦 数组(Array)📖 什么是数组🌀 数组的存储📝 示例代码&#…

运放的同相与反相放大

反相放大器 同相端接地,电压为 0,反相端和同相端虚短,因此也是 0 V 的电压,同时由于虚断,几乎没有电流注入,所以R 1 和R 2 相当于串联,电阻上的电流相等 因此可以求出输入输出关系式为 V o u t…

excel如何将多列数据转换为一列?

这个数据整理借用数据透视表也可以做到: 1.先将数据源的表头补齐,“姓名” 2.点击插入选项卡,数据透视表,在弹出对话框中,数据透视位置选择 现有工作表,(实际使用时新建也没有问题)…

免费分享一套微信小程序在线订餐(点餐)配送系统(SpringBoot+Vue),帅呆了~~

大家好,我是java1234_小锋老师,看到一个不错的微信小程序在线订餐(点餐)配送系统(SpringBootVue),分享下哈。 项目视频演示 【免费】微信小程序在线订餐(点餐)配送系统(SpringBootVue) Java毕业设计_哔哩哔哩_bilibili【免费】微信小程序在…

每日OJ题_贪心算法三⑥_力扣738. 单调递增的数字

目录 力扣738. 单调递增的数字 解析代码 力扣738. 单调递增的数字 738. 单调递增的数字 难度 中等 当且仅当每个相邻位数上的数字 x 和 y 满足 x < y 时&#xff0c;我们称这个整数是单调递增的。 给定一个整数 n &#xff0c;返回 小于或等于 n 的最大数字&#xff0…

集成学习案例-幸福感预测

集成学习案例一 &#xff08;幸福感预测&#xff09; 背景介绍 此案例是一个数据挖掘类型的比赛——幸福感预测的baseline。比赛的数据使用的是官方的《中国综合社会调查&#xff08;CGSS&#xff09;》文件中的调查结果中的数据&#xff0c;其共包含有139个维度的特征&#xf…