前面我们获得了PSF的点云数据,这里可以进一步通过 open3d 模块提供的泊松曲面重建功能来计算得到surface。
结果如上所示,分别是k3d中作的三维点云,使用alphashape方法重建的点云表面,和使用泊松重建的曲面。完整代码如下:
import matplotlib.pyplot as pltfrom aicsimageio import AICSImagefrom glob import globimport numpy as npimport open3d as o3dfrom sklearn.cluster import DBSCAN
fps = glob("*.czi")a = AICSImage(fps[1])data = a.get_image_data("ZYX", C=0)zs, ys, xs = np.where(data>0)locs = np.vstack([xs, ys, zs]).T
# 第一次聚类用于去噪clustering = DBSCAN(eps=3, min_samples=3).fit(locs)inds = np.where(clustering.labels_>-1)locs2 = locs[inds]# 第二次聚类用于分开不同的大clusterclustering2 = DBSCAN(eps=10, min_samples=3).fit(locs2)
# 取其中一个点云cluster进行尝试inds3 = np.where(clustering2.labels_==3)locs3 = locs2[inds3]
# 转换为o3d的点云对象pt = o3d.geometry.PointCloud()pt.points = o3d.utility.Vector3dVector(locs3)
# 使用 alphashape 计算点云的表面mesh1 = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(pt, alpha=2)# alpha参数越大,表面越光滑,但可能舍弃的点越多mesh1.compute_vertex_normals()# 查看 alphashape 方法得到的 mesh# o3d.visualization.draw_geometries([pt, mesh1], width=400, height=300, mesh_show_back_face=True)
# 基于泊松方法重建点云表面pt2 = mesh1.sample_points_poisson_disk(len(locs3))# disk可以输入一个整数,代表采样密度,如果一个单位体积中点密度高,这个数值就写高点pt2.estimate_normals()mesh2, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pt2, depth=3)mesh2.compute_vertex_normals()# 按照密度上伪彩d = np.asarray(densities)dc = plt.get_cmap('plasma')((d-d.min())/(d.max()-d.min()))dc = dc[:,:3]mesh2.vertex_colors = o3d.utility.Vector3dVector(dc)# 查看泊松重建表面效果o3d.visualization.draw_geometries([pt, mesh2], width=400, height=300, mesh_show_back_face=True)# 保存网格为3d文件,支持其它三维作图软件查看o3d.io.write_triangle_mesh("psf.gltf", mesh2)open3d 提供的渲染窗口非常简陋,所以可以导出为比较通用的三维格式比如 gltf 文件,然后使用其它软件进行渲染查看包括制作视频。这里介绍一个最简单的微软出品的 3D Viewer。
打开刚刚保存的 psf.gltf 文件,可以看到我们添加的伪彩(按 density)保留了下来,而且可以自己调整环境照明,甚至是快速制作动画,但是这里只有预制的几种动画模式,不支持自定义编辑。