You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

3D分割掩码ROI尺寸适配、冗余体素去除及边界框代码修复求助

解决3D分割掩码裁剪为ROI及修复边界框绘制问题

原代码存在的问题

  1. 未处理分割掩码全为0的情况,此时np.where(segmentation)返回空数组,调用np.min/np.max会直接报错
  2. 边界框绘制时直接给图像赋值为1,若原图像是浮点型(比如CT/MRI常用的0-1或0-255范围),这个值可能不在图像灰度范围内,导致边界框看不见
  3. 核心需求是裁剪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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:18:10