2021SC@SDUSC
open3D 网格和图片的应用
本篇对前面分析的Mesh和Image相关的知识进行应用。我们小组进行了讨论,结合open3D在python方面对网格和图片的实现,我们用python代码进行了一些相关算法的实现。
网格变形
算法原理
Open3D中的deform_as_rigid_as_possible函数,使用少量的约束使得三角网格变形,实现了Sorkine and M. Alexa, As-rigid-as-possible surface modeling, Symposium on Geometry processing, 2007.中的尽可能严格的算法。
以优化下面的能量函数:
∑
i
=
1
∑
j
∈
N
(
i
)
w
i
j
∣
∣
(
p
i
′
−
p
j
′
)
−
R
i
(
p
i
−
p
j
)
∣
∣
2
\sum_{i=1}\sum_{j\in N(i)}\ w_{ij}||(p_i'-p_j')-R_i(p_i-p_j)||^2
∑i=1∑j∈N(i) wij∣∣(pi′−pj′)−Ri(pi−pj)∣∣2
式中:
R
i
R_i
Ri表示要优化的旋转矩阵,
p
i
p_i
pi和
p
j
p_j
pj分别表示优化前后的顶点位置,
N
(
i
)
N(i)
N(i) 表示顶点
i
i
i的邻域集合。
w
i
j
w_{ij}
wij权重表示余切权重。
代码实现
import open3d as o3d
import numpy as np
mesh = o3d.io.read_triangle_mesh("data//Armadillo.ply")
vertices = np.asarray(mesh.vertices)
static_ids = [idx for idx in np.where(vertices[:, 1] < -30)[0]]
static_pos = []
for id in static_ids:
static_pos.append(vertices[id])
handle_ids = [2490]
handle_pos = [vertices[2490] + np.array((-40, -40, -40))]
constraint_ids = o3d.utility.IntVector(static_ids + handle_ids)
constraint_pos = o3d.utility.Vector3dVector(static_pos + handle_pos)
with o3d.utility.VerbosityContextManager(
o3d.utility.VerbosityLevel.Debug) as cm:
mesh_prime = mesh.deform_as_rigid_as_possible(constraint_ids, # 三角网格的顶点
constraint_pos, # 顶点优化后的位置
max_iter=50) # 迭代次数
print('Original Mesh')
R = mesh.get_rotation_matrix_from_xyz((0, np.pi, 0))
o3d.visualization.draw_geometries([mesh.rotate(R, center=mesh.get_center())])
print('Deformed Mesh')
mesh_prime.compute_vertex_normals()
o3d.visualization.draw_geometries(
[mesh_prime.rotate(R, center=mesh_prime.get_center())])
去除mesh中的噪点
算法原理
各种重建算法的结果(比如RGBD Integration 并不是只有一个三角网格而是有多个网格。一些较小的部分(相比如主物体较小)是由于噪声引起的,我们会想要移除它。Open3d实现了一个连通分量算法cluster_connected_triangles,将每个三角形分配给一个连接的三角集群,从集群中返回每一个三角形的索引triangle_cluters,和每一个集群中三角形的数量cluter_n_triangles还有集群的表面积cluster_area。
代码实现
下面的代码展示cluster_connected_triangles的应用和如何使用它来删除假三角形。
import open3d as o3d
import numpy as np
import copy
mesh = o3d.io.read_triangle_mesh("bunny.ply")
vert = np.asarray(mesh.vertices)
min_vert, max_vert = vert.min(axis=0), vert.max(axis=0)
for _ in range(30):
cube = o3d.geometry.TriangleMesh.create_box() # 生成小立方体作为噪声添加到mesh
cube.scale(0.005, center=cube.get_center()) # 立方体参数
cube.translate(
(
np.random.uniform(min_vert[0], max_vert[0]),
np.random.uniform(min_vert[1], max_vert[1]),
np.random.uniform(min_vert[2], max_vert[2]),
),
relative=False,
)
mesh += cube
mesh.compute_vertex_normals()
print("Show input mesh")
o3d.visualization.draw_geometries([mesh])
print("Cluster connected triangles")
with o3d.utility.VerbosityContextManager(
o3d.utility.VerbosityLevel.Debug) as cm:
triangle_clusters, cluster_n_triangles, cluster_area = (
mesh.cluster_connected_triangles()) #将每个三角形分配给一组连通的三角形
triangle_clusters = np.asarray(triangle_clusters) #返回每个三角形集群的索引
cluster_n_triangles = np.asarray(cluster_n_triangles)
cluster_area = np.asarray(cluster_area)
print("Show mesh with small clusters removed")
mesh_0 = copy.deepcopy(mesh)
triangles_to_remove = cluster_n_triangles[triangle_clusters] < 100
mesh_0.remove_triangles_by_mask(triangles_to_remove)
o3d.visualization.draw_geometries([mesh_0])
print("Show largest cluster")
mesh_1 = copy.deepcopy(mesh)
largest_cluster_idx = cluster_n_triangles.argmax()
triangles_to_remove = triangle_clusters != largest_cluster_idx
mesh_1.remove_triangles_by_mask(triangles_to_remove)
o3d.visualization.draw_geometries([mesh_1])
读取、显示、保存图片
主要函数
1、Open3D中
i
m
g
=
o
3
d
.
i
o
.
r
e
a
d
i
m
a
g
e
(
"
y
7.
p
n
g
"
)
img = o3d.io.read_image("y7.png")
img=o3d.io.readimage("y7.png")实现图片图像数据的读取,支持的图片格式为jpg、png;
2、图像的大小可以很容易地使用
p
r
i
n
t
(
i
m
g
)
print(img)
print(img)来获取;
3、
o
3
d
.
i
o
.
w
r
i
t
e
i
m
a
g
e
(
"
天
使
.
j
p
g
"
,
i
m
g
)
o3d.io.write_image("天使.jpg", img)
o3d.io.writeimage("天使.jpg",img)实现图片的保存、支持的图片格式为jpg、png;
4、
o
3
d
.
v
i
s
u
a
l
i
z
a
t
i
o
n
.
d
r
a
w
g
e
o
m
e
t
r
i
e
s
(
)
o3d.visualization.draw_geometries()
o3d.visualization.drawgeometries()实现图片的显示。
代码实现
import open3d as o3d
print("Testing IO for images")
img = o3d.io.read_image("y7.png") # 读取图片(支持jpg和png格式)
print(img) # 图片大小
o3d.io.write_image("天使.jpg", img) # 保存图片
o3d.visualization.draw_geometries([img], window_name="Open3D显示图像",
width=1024, height=768,
left=50, top=50,
mesh_show_back_face=False) # 显示图片
小结
本篇对前面分析的Mesh和Image相关的知识进行应用。我们小组进行了讨论,结合open3D在python方面对网格和图片的实现,我们用python代码进行了一些相关算法的实现,这使得我们对open3D在Mesh和RGBD图像等方面的应用的理解更为深刻了。