Python 异源mesh裁剪融合实现与优化

Python 异源mesh裁剪融合实现与优化

  • 一、项目需求
  • 二、解决方案
    • 1. 代码
    • 2. 结果
    • 3. 耗时
  • 三、优化探索
    • 0. 分析
    • 1. 在体素边界处进行裁剪
    • 2. 用mesh分块进行裁剪
    • 3. 用缓冲区的思路裁剪

一、项目需求

对mesh进行裁剪,但发现若非mesh是致密的,那么裁剪边会出现锯齿状边缘,究其原因,是因为该裁剪方式没有对三角面片进行处理,而是直接处理的mesh的顶点,导致裁剪边不光滑,那么两个相邻的裁剪后mesh(尤其是异源mesh)放在一起的时候,会出现缝隙。
在这里插入图片描述
在这里插入图片描述

计划找到一种在三角面片层面对mesh进行裁剪的方案,用来解决缝隙问题。

二、解决方案

找到三个python第三方库,分别为pyvista、vedo、trimesh可以实现上述功能,下面对这个三个库进行测试比较。

1. 代码

import time
from datetime import timedeltaimport numpy as npimport pyvista as pvmvs_path = r"T:\ProjectData\SDF_Studio\GT_data\mvs_mesh_aligned.ply"dataset = pv.read(mvs_path)
start_time = time.time()
bounds = [195.957, 211.373, 347.767, 362.355, 270.836, 286.781]
clipped = dataset.clip_box(bounds, invert=False)
end_time = time.time()
elapsed_time = end_time - start_time
formatted_time = str(timedelta(seconds=elapsed_time))
print(f"pyvista took  {formatted_time}")p = pv.Plotter()
p.add_mesh(clipped, label='Clipped')
p.show()import vedomesh = vedo.load(mvs_path)
start_time = time.time()
clipped_mesh = mesh.cut_with_box(bounds)
end_time = time.time()
elapsed_time = end_time - start_time
formatted_time = str(timedelta(seconds=elapsed_time))
print(f"vode took  {formatted_time}")
# 显示裁剪后的mesh
vedo.show(clipped_mesh)import trimeshmesh = trimesh.load_mesh(mvs_path)
start_time = time.time()
min_values = [195.957,347.767,270.836]
max_values = [211.373,362.355,286.781]
# 定义六个平面的法向量和原点
planes = np.array([[1, 0, 0, min_values[0], 0, 0],[-1, 0, 0, max_values[0], 0, 0],[0, 1, 0, 0, min_values[1], 0],[0, -1, 0, 0, max_values[1], 0],[0, 0, 1, 0, 0, min_values[2]],[0, 0, -1, 0, 0, max_values[2]]])mesh = trimesh.intersections.slice_mesh_plane(mesh=mesh,plane_normal=planes[:, :3],plane_origin=planes[:, 3:],cap=False,
)end_time = time.time()
elapsed_time = end_time - start_time
formatted_time = str(timedelta(seconds=elapsed_time))
print(f"trimesh took  {formatted_time}")
mesh.show()

2. 结果

pyvista:
在这里插入图片描述
vedo:
在这里插入图片描述
trimesh:
在这里插入图片描述
以上都可以实现在三角面片层面对mesh进行裁剪,接下来看看其效率和效果。

3. 耗时

pyvista took  0:00:19.446367
vode took  0:00:00.642607
trimesh took  0:00:01.582946

根据测试结果来看,vedo的效率最高,接下来用vedo来做大型的mesh裁剪融合实验。但在实验结果中发现其在边角上处理的并不好,仍有空隙存在。

在这里插入图片描述
在这里插入图片描述

改用trimesh进行测试,其边界就处理得比较好,但相同数据下,trimesh耗时是vedo的两倍。目前还仅是较大的尺寸进行融合,后续当体素设置为更小尺寸时,耗时会指数级别增长,所以还需优化。

在这里插入图片描述
在这里插入图片描述

三、优化探索

在这里记录所想到和已经实验的优化思路。

0. 分析

首先简单说一下trimesh的裁剪逻辑,它没有直接利用体素bound或者box进行裁剪方式,只有一个用平面切分mesh的方法,而且只返回法线正侧的mesh,见此处。所以想要裁剪出一个体素内的mesh,只能用6个平面循环切分得到,如上述代码。
那么很容易想到,用多个体素裁剪时会有重复计算。

1. 在体素边界处进行裁剪

先在所有体素边界处进行裁剪,然后得到边界处分割后的mesh,与原始mesh合并,在正常进行裁剪融合,但实验发现融合结果始终有缝隙存在,可能跟边界的顶点不好判别在哪一个体素有关系。
这个边框的mesh还比较有意思。
在这里插入图片描述

2. 用mesh分块进行裁剪

先找到一个大于体素的mesh分块,然后用这个mesh分块进行裁剪,实验发现用mesh分块裁剪确实很快,但在加上mesh分块的过程,与之前用整个mesh进行裁剪的耗时相当了。

def small_mesh(vertices,faces,min_v ,max_v ):'''在大型mesh中找到小的mesh分块'''# 找出满足条件的顶点的索引inside_indices = np.where((vertices[:, 0] > min_v[0]) & (vertices[:, 0] < max_v[0]) &(vertices[:, 1] > min_v[1]) & (vertices[:, 1] < max_v[1]) &(vertices[:, 2] > min_v[2]) & (vertices[:, 2] < max_v[2]))[0]# 根据这些索引找到相关的三角面片inside_faces = np.any(np.isin(faces, inside_indices), axis=1)# 创建新的 meshnew_vertices = vertices[inside_indices]new_faces=faces[inside_faces]index_map1 = {old: new for new, old in enumerate(inside_indices.flatten())}new_faces = [[index_map1[idx] for idx in face] for face in new_faces if all(idx in index_map1 for idx in face)]new_mesh = trimesh.Trimesh(vertices=new_vertices, faces=new_faces)return new_mesh

在这里插入图片描述

3. 用缓冲区的思路裁剪

之所以有缝隙存在,是因为使用顶点判别时没有顾及到三角面片,如果设定一个缓冲区,那么三角面片就可以覆盖边界从而消除缝隙。
那怎么实现这个缓冲区的思路呢,其实也简单,在遍历顶点的时候,对每个顶点在6个方向上平移一个设定值,判断其是否会落入到其他体素内就可以了。若没有落入其他体素,记得不要重复统计该顶点。

# 核心代码
voxel_dict1 = defaultdict(list)buffer = 0.2  # 设置缓冲区大小directions=[np.array([1, 0, 0]), np.array([-1, 0, 0]), np.array([0, 1, 0]), np.array([0, -1, 0]), np.array([0, 0, 1]), np.array([0, 0, -1])]for i, v in tqdm(enumerate(vertices1)):k = ((v - global_min) / voxel_size).astype(np.int32)voxel_dict1[tuple(k)].append(i)# 将顶点向六个方向移动一个缓冲值,然后检查移动后的顶点是否会落入其他体素中for direction in directions:new_v = v + direction * buffernew_k = tuple(((new_v - global_min) / voxel_size).astype(np.int32))if not np.array_equal(new_k, k):   # 检查顶点是否移动到了其他体素中voxel_dict1[tuple(new_k)].append(i)

以下分别是无缓冲区、缓冲值为0.1,、缓冲值为0.2的结果。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
耗时8分钟左右,且跟体素尺寸无关,不会随着体素减小耗时指数倍增长。
在这里插入图片描述
实验表明,这种方法简单高效,可以有效去除异源mesh融合时的缝隙。在这里,最朴素的思想反而是最实用的。


打完收工

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

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

相关文章

JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、运行时数据区 二、Java虚拟机栈 1.栈帧的组成 2.局部变量表 3.操作数栈 4.帧数据 总结 前言 JVM作为Java程序的运行环境&#xff0c;其负责解释和执行字节码&#xff0c;管理…

图片太模糊我们怎么提高清晰度呢

在数字时代&#xff0c;图片是我们日常生活中不可或缺的一部分。然而&#xff0c;有时候由于各种原因&#xff0c;我们得到的图片清晰度可能并不理想。这篇文章将介绍三款软件&#xff0c;帮助你提高图片的清晰度&#xff0c;让你的图片更加生动、清晰。 一、水印云 水印云是…

小型机故障案例

小型机故障案例 小型机往往应用于金融、电力、电信等行业&#xff0c;Unix操作系统和专用服务器RAS特性、纵向扩展性和高并发访问下的出色处理能力**&#xff0c;如HP RX6600**本文章记录在机房直连服务器进行故障原因排查及解决过程 故障现象 HP RX6600小型机关机后&#xff…

uniapp 微信小程序 内嵌H5网页办法

uniapp 微信小程序 内嵌H5网页办法 如图所示 1.新建webView页面 <template><web-view v-ifhttpUrl :srchttpUrl></web-view> </template><script>export default {data() {return {httpUrl: "",};},onLoad(options) {options.http…

脏牛漏洞(CVE-2016-5195)复现过程(详细完整版)

1、实验环境 KaLi 攻击机 Linux靶机 靶场 实验目的&#xff1a; 掌握漏洞利用的方法 掌握脏牛漏洞的原理 提高对内核安全性的认识 2、靶场搭建 VMware导入靶场 靶场地址&#xff1a;链接&#xff1a;百度网盘 请输入提取码百度网盘为您提供文件的网络备份、同步和分享服务。…

Pypputeer自动化

Pyppeteer简介 pyppeteer 是 Python 语言的一个库&#xff0c;它是对 Puppeteer 的一个非官方端口&#xff0c;Puppeteer 是一个 Node 库&#xff0c;Puppeteer是Google基于Node.js开发的一个工具&#xff0c;它提供了一种高层次的 API 来通过 DevTools 协议控制 Chrome 或 Ch…

分类预测 | Matlab实现ISSA-SVM基于多策略混合改进的麻雀搜索算法优化支持向量机的数据分类预测

分类预测 | Matlab实现ISSA-SVM基于多策略混合改进的麻雀搜索算法优化支持向量机的数据分类预测 目录 分类预测 | Matlab实现ISSA-SVM基于多策略混合改进的麻雀搜索算法优化支持向量机的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 基于多策略混合改进的麻…

docker报错 missing signature key 无法拉去镜像,yum install docker-ce没有可用软件包 解决办法

错误场景描述 今天项目需要用到minio&#xff0c;我打算在虚拟机中使用docker装一个&#xff0c;可是发现当我docker pull minio/minio的时候&#xff0c;报错了missing signature key 这个报错提示的让人很蒙&#xff0c;翻译过来的意思是 “缺少签名密钥” &#xff1f;&am…

用 Python 制作可视化 GUI 界面,一键实现自动分类管理文件!

经常杂乱无章的文件夹会让我们找不到所想要的文件&#xff0c;因此小编特意制作了一个可视化GUI界面&#xff0c;通过输入路径一键点击实现文件分门别类的归档。 不同的文件后缀归类为不同的类别 我们先罗列一下大致有几类文件&#xff0c;根据文件的后缀来设定&#xff0c;大…

GaussDB与openGauss有什么相同和不同?

众所周知&#xff0c;GaussDB是华为自主创新研发的分布式关系型数据库&#xff0c;为企业提供功能全面、稳定可靠、扩展性强、性能优越的企业级数据库服务&#xff0c;openGauss是开源数据库&#xff0c;两者之间又是什么样的关系&#xff0c;有什么相同和不同&#xff0c;让我…

如何使用Portainer部署web站点并实现无公网ip远程访问

文章目录 前言1. 安装Portainer1.1 访问Portainer Web界面 2. 使用Portainer创建Nginx容器3. 将Web静态站点实现公网访问4. 配置Web站点公网访问地址4.1公网访问Web站点 5. 固定Web静态站点公网地址6. 固定公网地址访问Web静态站点 前言 Portainer是一个开源的Docker轻量级可视…

k8s的PV,PVC自动创建

此部署使用传统的pv&#xff0c;pvc方式做持久化数据存储&#xff0c;而是使用storageclass调用provisioner&#xff0c;自动给pod创建的pvc分配pv并绑定&#xff0c;从而达到持久化存储的效果。可根据自己需求创建相关的pv&#xff0c;pvc。 安装NFS服务 NFS Server IP&…

【spark】SparkSQL

目录 SparkSQL01.快速入门什么是SparkSQL为什么学习SparkSQLSparkSQL的特点SparkSQL发展历史-前身Shark框架SparkSQL发展历史 02.SparkSQL概述SparkSQL和Hive的异同SparkSQL的数据抽象DataFrame概述SparkSession对象 03.DataFrame入门和操作DataFrame的组成DataFrame的代码构建…

NativePHP:开发跨平台原生应用的强大工具

NativePHP 是一种创新性的技术&#xff0c;可以帮助开发者使用 PHP 语言构建原生应用程序。本文将介绍 NativePHP 的概念和优势&#xff0c;探讨其在跨平台应用开发中的应用&#xff0c;并提供一些使用 NativePHP 开发原生应用的最佳实践。 什么是 NativePHP&#xff1f; Nati…

js实现iframe内容加载失败自动重新加载功能

最近一个项目上的程序经常出现掉线的情况&#xff0c;经排查是该单位的网络不稳定&#xff0c;存在网络丢包现象。导致有时候程序运行加载页面失败&#xff0c;开机自启动应用时出现请求失败的概率非常大&#xff0c;为了解决这个问题我在网上东找西找也没有找到有效的解决办法…

丰果管道——2024中国家装管道十大品牌

丰果管道——2024中国家装管道十大品牌 丰果&#xff08;中国&#xff09;有限公司 丰果管道品牌创立于1999年&#xff0c;是国内最早从事PPR家装管道生产的品牌之一&#xff0c;在业内有着良好的口碑和市场美誉度&#xff0c;在全国的头部装企更是有相当高的市场占有率。2023年…

猫咪发腮长肉吃什么?5款适合猫咪发腮长肉的猫罐头推荐

随着冬季的来临&#xff0c;北方的小猫咪们因为有暖气&#xff0c;日子还算好过。然而南方的猫咪们只能依靠自己的抵抗力来度过这个寒冷的季节。为了确保这些怕冷的小家伙能温暖地度过冬天&#xff0c;铲屎官们是不是该考虑为它们囤积一些肉肉呢&#xff1f; 有些猫咪&#xf…

无货源跨境电商到底应该怎么做,新手必看

如今&#xff0c;跨境电商无疑已经成为了一个热门的创业领域&#xff0c;但对于一些新手来说&#xff0c;面临的一个主要挑战是如何处理产品的货源问题。下面我就和大家分享一下无货源跨境电商的基本概念以及一些新手可以采取的策略和步骤&#xff0c;帮助大家在这个领域取得成…

C#MQTT编程08--MQTT服务器和客户端(cmd版)

1、前言 前面完成了winform版&#xff0c;wpf版&#xff0c;为什么要搞个cmd版&#xff0c;因为前面介绍了mqtt的报文结构&#xff0c;重点分析了【连接报文】&#xff0c;【订阅报文】&#xff0c;【发布报文】&#xff0c;这节就要就看看实际报文是怎么组装的&#xff0c;这…

Flink编程——风险欺诈检测

Flink 风险欺诈检测 文章目录 Flink 风险欺诈检测背景准备条件FraudDetectionJob.javaFraudDetector.java 代码分析执行环境创建数据源对事件分区 & 欺诈检测输出结果运行作业欺诈检测器 欺诈检测器 v1&#xff1a;状态欺诈检测器 v2&#xff1a;状态 时间完整的程序期望的…