3D分割掩码ROI尺寸适配、冗余体素去除及边界框代码修复求助
解决3D分割掩码裁剪为ROI及修复边界框绘制问题
原代码存在的问题
- 未处理分割掩码全为0的情况,此时
np.where(segmentation)返回空数组,调用np.min/np.max会直接报错 - 边界框绘制时直接给图像赋值为1,若原图像是浮点型(比如CT/MRI常用的0-1或0-255范围),这个值可能不在图像灰度范围内,导致边界框看不见
- 核心需求是裁剪ROI去除多余体素,但原代码只实现了边界框绘制,没完成裁剪功能
实现裁剪3D数据到ROI区域
要提取分割掩码对应的ROI,只需找到非零体素的坐标范围,然后对图像和分割掩码进行切片即可:
import numpy as np import nibabel as nib import matplotlib.pyplot as plt def get_roi_coords(segmentation): """获取分割掩码对应的ROI坐标范围""" coords = np.where(segmentation > 0) # 只取前景体素 if len(coords[0]) == 0: raise ValueError("分割掩码中没有前景体素") min_coords = np.min(coords, axis=1) max_coords = np.max(coords, axis=1) + 1 # 切片是左闭右开,所以+1 return min_coords, max_coords def crop_to_roi(image_data, segmentation_data): """将图像和分割掩码裁剪到ROI区域""" min_coords, max_coords = get_roi_coords(segmentation_data) # 对三个维度进行切片 cropped_image = image_data[min_coords[0]:max_coords[0], min_coords[1]:max_coords[1], min_coords[2]:max_coords[2]] cropped_seg = segmentation_data[min_coords[0]:max_coords[0], min_coords[1]:max_coords[1], min_coords[2]:max_coords[2]] return cropped_image, cropped_seg
修复后的3D边界框绘制函数
针对原边界框绘制的问题,加入空分割判断,同时用图像的最大灰度值来绘制边界,确保可见:
def draw_3d_bounding_box(image, segmentation): """在图像上绘制3D边界框(基于分割掩码)""" # 先获取ROI坐标 coords = np.where(segmentation > 0) if len(coords[0]) == 0: print("分割掩码中没有前景体素,跳过边界框绘制") return image min_coords = np.min(coords, axis=1) max_coords = np.max(coords, axis=1) + 1 # 用图像的最大灰度值作为边界框颜色,确保可见 box_value = np.max(image) # 绘制边界框的棱边 # x轴方向的四条竖线 image[min_coords[0]:max_coords[0], min_coords[1], min_coords[2]] = box_value image[min_coords[0]:max_coords[0], max_coords[1]-1, min_coords[2]] = box_value image[min_coords[0]:max_coords[0], min_coords[1], max_coords[2]-1] = box_value image[min_coords[0]:max_coords[0], max_coords[1]-1, max_coords[2]-1] = box_value # y轴方向的四条横线 image[min_coords[0], min_coords[1]:max_coords[1], min_coords[2]] = box_value image[max_coords[0]-1, min_coords[1]:max_coords[1], min_coords[2]] = box_value image[min_coords[0], min_coords[1]:max_coords[1], max_coords[2]-1] = box_value image[max_coords[0]-1, min_coords[1]:max_coords[1], max_coords[2]-1] = box_value # z轴方向的四条竖线 image[min_coords[0], min_coords[1], min_coords[2]:max_coords[2]] = box_value image[max_coords[0]-1, min_coords[1], min_coords[2]:max_coords[2]] = box_value image[min_coords[0], max_coords[1]-1, min_coords[2]:max_coords[2]] = box_value image[max_coords[0]-1, max_coords[1]-1, min_coords[2]:max_coords[2]] = box_value return image
完整使用示例
# 加载数据 image = nib.load('/Tr_0351_0000.nii.gz') image_data = image.get_fdata() segmentation = nib.load('/Tr_0351.nii.gz') segmentation_data = segmentation.get_fdata() # 裁剪到ROI区域 cropped_image, cropped_seg = crop_to_roi(image_data, segmentation_data) # 在裁剪后的图像上绘制边界框 image_with_box = draw_3d_bounding_box(cropped_image.copy(), cropped_seg) # 用copy避免修改原数据 # 可视化中间切片 slice_idx = cropped_image.shape[2] // 2 plt.imshow(image_with_box[:, :, slice_idx], cmap='gray') plt.title(f"ROI切片 {slice_idx}(带边界框)") plt.show()
内容的提问来源于stack exchange,提问作者curiousha
相关产品推荐
相关产品推荐

