如何连接2D切片中的二进制曲面并绘制3D连接轮廓?
连接二进制曲面生成3D轮廓的实现方案
你可以通过提取每个2D切片的轮廓点,再将相邻切片的对应轮廓点连接,来生成3D连接轮廓。以下提供两种实现方式:
方式一:针对规则矩形区域(无需额外依赖)
如果你的二进制区域是规则的矩形(如示例中的2x2方块),可以直接计算区域的角点坐标,再绘制轮廓和连接线段:
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import matplotlib matplotlib.use('Qt5Agg') # 生成网格数据 x, y = np.meshgrid(np.linspace(0,1,20), np.linspace(0,1,20)) z_vals = np.linspace(0, 2, 4) u = np.zeros((len(z_vals), 20, 20)) # 填充二进制数据 for i in range(len(z_vals)): u[i, i+5:i+7, i+5:i+7] = 1 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 存储每个切片的轮廓点 slice_contours = [] # 绘制每个切片的2D轮廓线 for idx, z in enumerate(z_vals): # 获取矩形区域的边界坐标 y_min = y[idx+5, 0] y_max = y[idx+7, 0] x_min = x[0, idx+5] x_max = x[0, idx+7] # 定义矩形的四个角点(闭合轮廓) points = np.array([ [x_min, y_min], [x_max, y_min], [x_max, y_max], [x_min, y_max], [x_min, y_min] ]) slice_contours.append((points, z)) # 在当前z高度绘制轮廓线 ax.plot(points[:,0], points[:,1], zs=z, zdir='z', color='gold', linewidth=2) # 连接相邻切片的对应角点 for i in range(len(slice_contours)-1): curr_points, curr_z = slice_contours[i] next_points, next_z = slice_contours[i+1] # 逐个连接对应点(跳过最后一个重复的闭合点) for p_curr, p_next in zip(curr_points[:-1], next_points[:-1]): ax.plot([p_curr[0], p_next[0]], [p_curr[1], p_next[1]], [curr_z, next_z], color='gold', linewidth=2) # 设置坐标轴标签 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show()
方式二:通用不规则区域(依赖scikit-image)
如果你的二进制区域形状不规则,可以用scikit-image的find_contours函数提取轮廓,再连接相邻切片的轮廓点:
首先确保安装scikit-image:
pip install scikit-image
然后运行以下代码:
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from skimage.measure import find_contours import matplotlib matplotlib.use('Qt5Agg') # 生成网格数据 x, y = np.meshgrid(np.linspace(0,1,20), np.linspace(0,1,20)) z_vals = np.linspace(0, 2, 4) u = np.zeros((len(z_vals), 20, 20)) # 填充二进制数据 for i in range(len(z_vals)): u[i, i+5:i+7, i+5:i+7] = 1 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 存储每个切片的轮廓点 slice_contours = [] # 提取并绘制每个切片的轮廓线 for idx, z in enumerate(z_vals): # 提取水平集为0.5的轮廓(区分0和1的区域) contours = find_contours(u[idx], level=0.5) for contour in contours: # 将轮廓的索引坐标转换为实际x、y值 y_coords = y[contour[:,0].astype(int), 0] x_coords = x[0, contour[:,1].astype(int)] contour_points = np.column_stack((x_coords, y_coords)) slice_contours.append((contour_points, z)) # 在当前z高度绘制轮廓线 ax.plot(contour_points[:,0], contour_points[:,1], zs=z, zdir='z', color='gold', linewidth=2) # 连接相邻切片的对应轮廓点(假设每个切片只有一个轮廓且点顺序对应) for i in range(len(slice_contours)-1): curr_points, curr_z = slice_contours[i] next_points, next_z = slice_contours[i+1] # 若轮廓点数量一致,逐个连接对应点 if len(curr_points) == len(next_points): for p_curr, p_next in zip(curr_points, next_points): ax.plot([p_curr[0], p_next[0]], [p_curr[1], p_next[1]], [curr_z, next_z], color='gold', linewidth=2) # 设置坐标轴标签 ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show()
这两种方式都能将各个切片的黄色区域连接成完整的3D轮廓框架,其中方式一适合规则形状,方式二更通用。
内容的提问来源于stack exchange,提问作者A. Heintz
相关产品推荐
相关产品推荐

