Python三维网格体素化实例

 更新时间:2024年06月24日 14:29:07   作者:BTWBB  
这篇文章主要介绍了Python三维网格体素化实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

Python三维网格体素化

本文主要是实现将一个网格模型体素化,实现不同分辨率的体素化效果,并且可视化输出为obj文件!

首先利用trimesh对mesh进行采样,然后根据采样点得到各个体素点的占有值。

效果

通过调整分辨率以及采样率(当分辨率变高时建议适量提高采样率)得到以下的效果!

代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author: Matthieu Zins
"""

import trimesh
import numpy as np
import os
import argparse

"""
    ======   Voxelize the surface of a mesh   ======
"""



def create_if_needed(folder):
    if not os.path.isdir(folder):
        os.mkdir(folder)



parser = argparse.ArgumentParser(description='Pass object name')
parser.add_argument('input_mesh', type=str)
parser.add_argument('--output_folder', type=str, default="")
parser.add_argument('--resolution', type=int, nargs=3, default=[50, 50, 50], 
                    help="resolution_X resolution_Y resolution_Z")
parser.add_argument('--sampling', type=int, default="100000",
                    help="number of points sampled on the mesh")
args = parser.parse_args()


input_mesh_filename = args.input_mesh
object_name = os.path.splitext(os.path.basename(input_mesh_filename))[0]
output_folder = args.output_folder
if len(output_folder) == 0: output_folder = object_name
RES_X, RES_Y, RES_Z = args.resolution
sample_points_count = args.sampling

create_if_needed(output_folder)


mesh = trimesh.exchange.load.load(input_mesh_filename)


# Uniform Points Sampling
pts, _ = trimesh.sample.sample_surface_even(mesh, sample_points_count )

# Save sample points
sampled_points_mesh = trimesh.Trimesh(vertices=pts)
sampled_points_mesh.export(os.path.join(output_folder, object_name + "_resampled_points.ply"))


# Adjust the grid origin and voxels size
origin = pts.min(axis=0)
dimensions = pts.max(axis=0) - pts.min(axis=0)
scales = np.divide(dimensions, np.array([RES_X-1, RES_Y-1, RES_Z-1]))
scale = np.max(scales)


# Voxelize

pts -= origin
pts /= scale
pts_int = np.round(pts).astype(int)

grid = np.zeros((RES_X, RES_Y, RES_Z), dtype=int)
gooRES_X = np.where(np.logical_and(pts_int[:, 0] >= 0, pts_int[:, 0] < RES_X))[0]
gooRES_Y = np.where(np.logical_and(pts_int[:, 1] >= 0, pts_int[:, 1] < RES_Y))[0]
gooRES_Z = np.where(np.logical_and(pts_int[:, 2] >= 0, pts_int[:, 2] < RES_Z))[0]
goods = np.intersect1d(np.intersect1d(gooRES_X, gooRES_Y), gooRES_Z)
pts_int = pts_int[goods, :]
grid[pts_int[:, 0], pts_int[:, 1], pts_int[:, 2]] = 1




# Save voxels
voxel_pts = np.array([[-0.5, 0.5, -0.5],
                      [0.5, 0.5, -0.5],
                      [0.5, 0.5, 0.5],
                      [-0.5, 0.5, 0.5],
                      [-0.5, -0.5, -0.5],
                      [0.5, -0.5, -0.5],
                      [0.5, -0.5, 0.5],
                      [-0.5, -0.5, 0.5]])
voxel_faces = np.array([[0, 1, 2, 3],
                        [1, 5, 6, 2],
                        [5, 4, 7, 6],
                        [4, 0, 3, 7],
                        [0, 4, 5, 1],
                        [7, 3, 2, 6]])

def get_voxel(i, j, k):
    global voxel_pts, voxel_faces
    v = np.array([i, j, k], dtype=float) * scale
    v += origin
    points = voxel_pts * scale + v
    return points, voxel_faces.copy()

points = []
faces = []
fi = 0
for i in range(RES_X):
    for j in range(RES_Y):
        for k in range(RES_Z):
            if grid[i, j, k]:
                p, f = get_voxel(i, j, k)
                points.append(p)
                f += fi
                faces.append(f)
                fi += 8

points = np.vstack(points)
faces = np.vstack(faces)
# Write obj mesh with quad faces
with open(os.path.join(output_folder, object_name + "_voxels.obj"), "w") as fout:
    for p in points:fout.write("v " + " ".join(map(str, p)) + "\n")
    for f in faces+1:fout.write("f " + " ".join(map(str, f)) + "\n")


print(object_name, "done.")

运行: 

Dependencies

  • numpy
  • trimesh
## Usage

python voxelize_surface.py example/chair.obj --output_folder output --resolution 30 30 30 --sampling 10000

The optional parameters are:

  • output_folder (string): folder where the result is saved
  • resolution (list): the resolution of the grid [res_x, res_y, res_z]
  • sampling (int): number of points sampled on the mesh surface before voxelization
  • :输入的类型可以时obj也可以是off以及ply格式!

注意

若出现如下情况,可将采样点数(sampling)提高!

出现此种情况的原因是采样间隔太大,而体素尺寸太小(分辨太高),所以导致在有些体素的占有值进行判断的时候出现错误。

所以也可以通过降低分辨率来改善此种情况!

Reference:

声明:本文的代码并非原创,来自GitHub中zinsmatt的Surface_Voxels一作!若有侵权请联系撤文!

https://github.com/zinsmatt/Surface_Voxels

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python re模块的使用全过程

    Python re模块的使用全过程

    这篇文章主要介绍了Python re模块的使用全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Django如何配置mysql数据库

    Django如何配置mysql数据库

    这篇文章主要为大家详细介绍了Django配置mysql数据库的详细步骤,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • 举例讲解Python的lambda语句声明匿名函数的用法

    举例讲解Python的lambda语句声明匿名函数的用法

    匿名函数现在已经成了各大编程语言争相标配的热门特性,无需用函数名来定义函数的方式在很多场合下书写起来十分炫酷,这里我们就来举例讲解Python的lambda语句声明匿名函数的用法
    2016-07-07
  • Python pip指定安装源的方法详解

    Python pip指定安装源的方法详解

    pip是Python包管理工具,该工具提供了对Python包的查找、下载、安装、卸载的功能,这篇文章主要给大家介绍了关于Python pip指定安装源的相关资料,需要的朋友可以参考下
    2023-12-12
  • Django serializer优化类视图的实现示例

    Django serializer优化类视图的实现示例

    这篇文章主要介绍了Django serializer优化类视图的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • Python 列表和字典常踩坑即解决方案

    Python 列表和字典常踩坑即解决方案

    这篇文章介绍了 Python 列表和字典常踩坑即解决方案,主要针对python列表和字典得一些问题,提出了多种解决方案。需要的小伙伴可以参考一下
    2022-05-05
  • Python中requests.session()的用法小结

    Python中requests.session()的用法小结

    这篇文章主要介绍了Python中requests.session()的用法小结,可能大家对 session 已经比较熟悉了,也大概了解了session的机制和原理,但是我们在做爬虫时如何会运用到session呢,接下来要讲到会话保持,需要的朋友可以参考下
    2022-11-11
  • python 爬虫如何实现百度翻译

    python 爬虫如何实现百度翻译

    这篇文章主要介绍了python 爬虫 简单实现百度翻译的示例,帮助大家更好的理解和使用python 爬虫,感兴趣的朋友可以了解下
    2020-11-11
  • 超好玩的"隔空操物"通过Python MediaPipe库实现

    超好玩的"隔空操物"通过Python MediaPipe库实现

    这篇文章主要介绍了python+mediapipe+opencv实现手部关键点检测功能(手势识别),本文仅仅简单介绍了mediapipe的使用,而mediapipe提供了大量关于图像识别等的方法,需要的朋友可以参考下
    2022-01-01
  • Python 查看文件的读写权限方法

    Python 查看文件的读写权限方法

    下面小编就为大家分享一篇Python 查看文件的读写权限方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01

最新评论