Python软件设计基础 第九节-Open3D模型处理

目录

一、Open3D介绍

二、Open3D安装

三、Open3D操作

(一)几何学-点云

1、可视化点云

2、KD近邻搜索

3、半径领域搜索

4、混合搜索

5、法向量估计/顶点正态估计

(二)几何学-表面重建

1、用无结构的点云数据生成

2、用三角片面生成

四、总结


一、Open3D介绍

Open3D是一个开源库,支持快速开发处理3D数据的软件。Open3D 前端在 C++ 和 Python 中公开了一组精心挑选的数据结构和算法。后端经过高度优化,并设置为并行化。

Open3D的核心功能包括: 3D 数据结构 3D 数据处理算法、场景重建、表面对齐、3D可视化、基于物理的渲染(PBR)等。

更多相关内容可访问:Open3D: A Modern Library for 3D Data Processing — Open3D 0.14.1 documentation

二、Open3D安装

pip安装步骤如下:

1、找到Python安装路径下的Scripts文件夹,并打开

2、在Scripts文件夹下打开命令提示符

3、在cmd窗口中输入:pip install open3d

4、检验是否安装完成,在cmd窗口输入python -c "import open3d as o3d"。若没有报错,则安装成功

需要注意的是,Open3D目前最高支持Python3.8版本,Python3.9及以上版本将无法安装。因此,在找上述Python安装目录时,需要查找Python3.8及以下版本的安装目录,否则将无法使用。

三、Open3D操作

(一)几何学-点云

1、可视化点云

代码如下:

import open3d as o3d
import numpy as np
#引入第三方库

print("Open3D read Point Cloud")
#输出提示文字
pcd=o3d.io.read_point_cloud(r"thu_statue.ply")
#读取模型
print(pcd)

o3d.visualization.draw_geometries([pcd],width=800,height=600)
#绘制生成点云

结果如下:

 

其中,按【ctrl】+【-】可以减少点云的体素尺寸,按【ctrl】+【+】可以放大点云的体素尺寸。具体示例如下(左图为增加点云体素尺寸的效果、右图为减少点云体素尺寸的效果):

2、KD近邻搜索

Kd-树是K- dimension tree的缩写,是对数据点在k维空间(如二维(x,y), 三维(x,y, z), k维(x, y, z...) )中划分的一种数据结构,主要应用于多维空间关键数据的搜索。

Search_knn_vector_3d,返回查询点的K个最近邻索引列表,并将这些相邻的点存储在一个数组中。

代码实现:

import open3d as o3d
import numpy as np
#引入第三方库

print("Open3D read Point Cloud")
#输出提示语句
pcd = o3d.io.read_point_cloud(r"bunny10k.ply")
pcd.paint_uniform_color([0.5, 0.5, 0.5])
#读取模型文件

pcd_tree = o3d.geometry.KDTreeFlann(pcd)
pcd.colors[100] = [1, 0, 0]

[k, idx, _] = pcd_tree.search_knn_vector_3d(pcd.points[100],100)
#确定中心
np.asarray(pcd.colors)[idx[1:], :] = [0, 1, 0]

o3d.visualization.draw_geometries([pcd],width=1200,height=1000)
#绘制点云模型

结果如下:

3、半径领域搜索

Search_radius_vector_3d,查询所有和查询点距离小于给定半径的点。

代码实现:

import open3d as o3d
import numpy as np
#引入第三方库

print("Open3D read Point Cloud")
#输出提示语句
pcd = o3d.io.read_point_cloud(r"bunny10k.ply")
pcd.paint_uniform_color([0.5, 0.5, 0.5])
#读取模型文件

pcd_tree = o3d.geometry.KDTreeFlann(pcd)
pcd.colors[100] = [1, 0, 0]

[k,idx,_] = pcd_tree.search_radius_vector_3d(pcd.points[3000],0.1) 
#设置索引半径小于0.02
np.asarray(pcd.colors)[idx[1:], :] = [0, 0, 1]

o3d.visualization.draw_geometries([pcd],width=1200,height=1000)
#绘制点云模型

结果如下:

4、混合搜索

混合搜索结合了KD近邻搜索和半径邻域搜索两种搜索方式。

Search_hybrid_vector_3d,最多返回k个和被查询点距离小于给定半径的最近邻点。

代码实现:

import open3d as o3d
import numpy as np
#导入第三方库

print("Open3D read Point Cloud")
#输出提示语句

pcd = o3d.io.read_point_cloud(r"bunny10k.ply")
#读取3d文件
pcd.paint_uniform_color([0.5, 0.5, 0.5])
#定义特定颜色

pcd_tree = o3d.geometry.KDTreeFlann(pcd)

#标记点1
pcd.colors[100] = [1, 0, 0]
#定义标记颜色
[k, idx, _] = pcd_tree.search_hybrid_vector_3d(pcd.points[100],0.05,200)
np.asarray(pcd.colors)[idx[1:], :] = [0, 1, 0]
#o3d.visualization.draw_geometries([pcd],width=1200,height=1000)
#绘制

#标记点2
pcd.colors[2000]=[1, 0, 0]
#定义标记颜色
[k2, idx2, _]=pcd_tree.search_hybrid_vector_3d(pcd.points[2000],0.05,200)
np.asarray(pcd.colors)[idx2[1:], :] = [0, 1, 0.8]
o3d.visualization.draw_geometries([pcd],width=1200,height=1000)
#绘制点云模型

 结果如下:

5、法向量估计/顶点正态估计

estimate_normals计算每个点的法线,该函数使用协方差分析查找相邻点并计算相邻点的主轴。

协方差分析算法生成两个与正态候选方向相反的方向。在不知道几何图形的全局结构的情况下,两者都可能是正确的,这称为正常方向问题。Open3D 尝试定向法线以使其与原始法线(如果存在)对齐。否则,Open3D会进行随机猜测。

代码如下:

import open3d as o3d
import numpy as np
#引入第三方库

print("Open3D read Point Cloud")
pcd = o3d.io.read_point_cloud(r"bunny10k.ply")
#读取模型文件
print(pcd)
dumppcd = pcd.voxel_down_sample(voxel_size=0.01)  
#下采样(降采样)

dumppcd.estimate_normals(search_param=o3d.geometry.KDTreeSearchParamHybrid(radius=0.01,max_nn=30))
#进行协方差计算

print(dumppcd.normals[0])
print(np.asarray(dumppcd.normals)[:10,:])

o3d.visualization.draw_geometries(  [dumppcd],point_show_normal=True,
                                    window_name="法线估计", 
                                    width=1200,height=1000,
                                    esh_show_back_face=False)
#绘制点云模型

 结果如下:

其中,按【ctrl】+【-】可以缩减点法线的长度,按【ctrl】+【+】可以增加点法线的长度。具体示例如下(左图为增加点法线长度的效果、右图为减少点法线长度的效果):

(二)几何学-表面重建

在许多情况下,我们希望生成密集的3D几何体,即三角形网格。然而,从多视点立体方法或深度传感器中,我们只能获得非结构化的点云。要从此非结构化输入中获取三角形网格,我们需要执行表面重建。

1、用无结构的点云数据生成

代码实现:

import open3d as o3d
import numpy as np
#引入第三方库

print("Open3D read Point Cloud")
#输出提示语句
pcd = o3d.io.read_point_cloud(r"bunny10k.ply")
#读取模型文件 
print(pcd)
o3d.visualization.draw_geometries([pcd])
#绘制点云模型

trimesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pcd,0.03)
print(trimesh)
o3d.visualization.draw_geometries([trimesh])
#绘制初始结构化模型

trimesh.compute_vertex_normals()
o3d.visualization.draw_geometries([trimesh],mesh_show_back_face=True)
#绘制结构化模型

 结果如下:

2、用三角片面生成

 代码如下:

import open3d as o3d
import numpy as np
#引入第三方库

print("Open3D read Point Cloud")
#输出提示语句
pcd = o3d.io.read_triangle_mesh(r"bunny10k.ply")
#读取模型文件
#print(pcd)
pcd.compute_vertex_normals()
pcdmesh = pcd.sample_points_poisson_disk(3000)
o3d.visualization.draw_geometries([pcdmesh],point_show_normal=True)


radii=[0.005, 0.01, 0.02, 0.04]

ballmesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcdmesh,o3d.utility.DoubleVector(radii))
#print(ballmesh)
o3d.visualization.draw_geometries([ballmesh])

o3d.visualization.draw_geometries([pcd, ballmesh])

结果如下:

四、总结

Open3D是一款非常便于使用的3D处理软件,能够实现较多的操作。在写帖子的过程中,再次对课上学的内容进行了巩固,也通过查看Open3D的网站学到了很多新的东西,例如体素化、点云异常值移除等等。


版权声明:本文为weixin_48138515原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。