Open3d 曲面滤波

文章目录

    • 均值滤波
    • 拉普拉斯滤波
    • Taubin滤波
    • 锐化

先打开一个曲面

import open3d as o3d
mesh = o3d.io.read_triangle_mesh('knot.ply')
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])

效果如下

Open3d 曲面滤波_第1张图片

knot.ply显然是点云文件,如果用io.read_point_cloud读取,那么draw出来的就是一片点云。将每三个点组成一个三角形,那么点云也就变成了三角面。

Open3D提供了4种滤波方法,分别是均值滤波、拉普拉斯滤波、taubin滤波以及锐化滤波。

均值滤波

所谓均值滤波,就是取最邻近的点做个均值,例如,顶点 v i v_i vi的值变化为

v i = ∑ n ∈ N v n ∣ N ∣ v_i=\frac{\sum_{n\in N} v_n}{|N|} vi=NnNvn

N N N为距离 v i v_i vi最近的点集(包括 v i v_i vi), ∣ N ∣ |N| N为点的个数

import numpy as np
vertices = np.asarray(mesh.vertices)
noise = 5
# 添加噪声
vertices += np.random.uniform(0, noise, size=vertices.shape)
mesh.vertices = o3d.utility.Vector3dVector(vertices)
mesh.compute_vertex_normals()

# 平滑去噪 迭代次数设为1
mesh_simple1 = mesh.filter_smooth_simple(1)
mesh_simple1.compute_vertex_normals()

mesh_simple5 = mesh.filter_smooth_simple(5)
mesh_simple5.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh,
    mesh_simple1.translate([200,0,0]),
    mesh_simple5.translate([400,0,0]),])

对比如下

Open3d 曲面滤波_第2张图片

拉普拉斯滤波

Laplace滤波相当于是对临近点做加权平均,其权重取决于到目标点的距离,其表达式如下

v i = v i ⋅ λ ∑ n ∈ N w n v n − v i v_i=v_i\cdot\lambda\sum_{n\in N}w_nv_n-v_i vi=viλnNwnvnvi

其中,lambda默认为0.5。

laplaces = []
for i,s in [[1,0.5],[10,0.5],[10,1],[50,0.5]]:
    laplaces.append(mesh.filter_smooth_laplacian(i,s))
    laplaces[-1].compute_vertex_normals()
    laplaces[-1].translate([200*len(laplaces),0,0])

o3d.visualization.draw_geometries(laplaces+[mesh])

效果为

Open3d 曲面滤波_第3张图片

随着迭代次数和lambda取值的不断增大,可以发现这个图形变得越来越细,为了解决这个问题,需要用到Taubin滤波。

Taubin滤波

Taubin滤波在Laplace滤波的基础上又加了一个负的 μ \mu μ参数,且要求 0 < λ < − μ 0<\lambda<-\mu 0<λ<μ

记第 i i i个点的坐标为 ( x i , y i , z i ) (x_i, y_i, z_i) (xi,yi,zi),则所有点的坐标可以组成一个 N × 3 N\times 3 N×3的矩阵,记作 X X X。令

X ′ = ( I − λ K ) X X ′ ′ = ( I − μ K ) X X'=(I-\lambda K)X\\ X''=(I-\mu K)X\\ X=(IλK)XX′′=(IμK)X

其中, I I I是单位矩阵, K = I − W K=I-W K=IW,W为 N × N N\times N N×N的加权矩阵,其元素 W i j W_{ij} Wij表示第 i , j i,j i,j的两个点是否相邻,如果不相邻则置零。

则经过 M M M次迭代之后,得到

X M = ( ( I − λ K ) ( I − λ K ) ) M X X^M=((I-\lambda K)(I-\lambda K))^MX XM=((IλK)(IλK))MX

taibin = []
for i in [1, 10, 50]:
    taibin.append(mesh.filter_smooth_taubin(i))
    taibin[-1].compute_vertex_normals()
    taibin[-1].translate([200*len(taibin),0,0])

o3d.visualization.draw_geometries(taibin+[mesh])

效果为

Open3d 曲面滤波_第4张图片

可见,就算迭代次数达到了50次,也没有出现变细的情况。

锐化

前三种滤波方法相当于把噪声抹平,锐化滤波与之相反,是凸显出不光滑 的部分,故而其算法与均值滤波相似,但要用当前值减去其相邻点的平均值。

由于加上噪声再做锐化,得到的图实在是没眼看,所以这回采用原始数据进行锐化

import open3d as o3d
mesh = o3d.io.read_triangle_mesh('knot.ply')
mesh.compute_vertex_normals()
sharpens = []
for i in [2, 4]:
    sharpens.append(mesh.filter_sharpen(i))
    sharpens[-1].compute_vertex_normals()
    sharpens[-1].translate([400*len(sharpens),0,0])

o3d.visualization.draw_geometries(sharpens+[mesh])

效果如下

Open3d 曲面滤波_第5张图片

你可能感兴趣的:(#,open3d,open3d,python,mesh,滤波,点云)