返回列表

14th Place Solution

596. SenNet + HOA - Hacking the Human Vasculature in 3D | blood-vessel-segmentation

开始: 2023-11-07 结束: 2024-02-06 医学影像分析 数据算法赛
第14名解决方案
作者:YumeNeko (Kashiwaba) | 排名:第14名 | 发布日期:2024年2月7日

概述

overview

  • 2.5D分割模型:输入N个连续切片(在通道方向堆叠),输出对应的N通道掩码
  • 输入图像仅裁剪肾脏区域,然后调整大小

流程详情

1. 预处理

1-1. 归一化

  • 计算整个肾脏的亮度值直方图,并基于最小值和最大值进行归一化
  • 按图像单位基于最大最小值归一化会导致图像外观变化,造成推理结果不自然切换。因此采用基于整个肾脏亮度分布的归一化方法
  • 代码实现:
def get_min_max_val(image_dir):
    img_paths = sorted(glob(os.path.join(image_dir, "*.tif")))
    
    pixels = np.zeros((65536,), dtype=np.int64)
    for img_path in tqdm(img_paths):
        img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
        _pixels = np.bincount(img.flatten(), minlength=65536)
        pixels += _pixels

    bin = 1000
    hist = []
    bins = []
    for i in range(0, 65535+bin, bin):
        hist.append(pixels[i:i+bin].sum())
        bins.append(i)
    hist = np.array(hist)
    hist_rate = hist/hist.max()
    idxes = np.where(hist_rate>0.01)[0]
    min_idx = idxes[0]
    max_idx = idxes[-1]
    return bins[min_idx]-5000, bins[max_idx]+5000

min_val, max_val = get_min_max_val(inference_img_dir)
img = cv2.imread(path, cv2.IMREAD_UNCHANGED)
img = img.astype('float32')
img = np.clip(img, min_value, max_value)
img = (img-min_value)/max_value

1-2. 裁剪

  • 使用分割模型推断整个肾脏的掩码,从而获得肾脏区域的矩形框
    crop
  • 肾脏分割模型使用Unet(骨干网络:efficientnet_b4),仅使用kidney_1_dense作为训练数据
  • 仅裁剪肾脏区域消除了图像中的浪费区域,大大提高了血管分割的准确性
  • 训练过程中,矩形的高度和宽度会随机增减±5%作为数据增强

1-3. 调整大小

  • 由于本次比赛指标对掩码要求严格,将图像调整到更大的尺寸非常重要
  • 在解决方案中,将图像调整至GPU内存允许的最大尺寸(1536~1920范围内)
  • 使用OpenCV的resize函数调整掩码后再调整回原始大小会导致像素向右下方偏移,造成精度显著下降。因此需谨慎处理:
    • 使用仿射变换,同时平移0.5个像素并缩放图像,防止像素错位
    • 此想法受凝结尾迹比赛解决方案的启发

2. 血管分割

模型

  • 使用Unet(smp实现),骨干网络包括resnest14d、resnest50d、maxvit_tiny,最终提交采用等权重集成
  • 采用2.5D模型:输入由n(5或7)个连续切片在通道方向堆叠组成的图像,输出对应的n通道掩码

数据

  • 训练数据:kidney_1_dense,验证数据:kidney_3_dense
  • 部分模型使用kidney_2和伪标签数据作为外部训练数据

增强

  • 使用旋转、翻转和亮度增强(albumentations实现)
  • 尝试过形状变换类增强(如Distortion),但因会降低CV/LB精度而未使用

推理

  • 在XY、XZ和ZY方向分别进行推理
  • 推理时使用比训练更大的输入尺寸,提高了CV和LB精度
  • 阈值根据CV确定,使用0.25

总结

最终分数如下表所示:

模型 N(通道数) 训练数据 验证数据 输入尺寸(训练) 输入尺寸(推理) CV分数 公开分数 私有分数
resnest14d 7 kidney_1_dense kidney_3_dense 1920x1920 2304x2304 0.909 0.835 0.659
resnest50d 5 kidney_1_dense kidney_3_dense 1536x1536 1920x1920 0.903 0.818 0.599
maxvit_tiny 7 kidney_1_dense, kidney_2(伪标签), extra_data(伪标签) kidney_3_dense 1536x1536 2048x2048 0.901 0.810 0.623
集成 - - - - - 0.913 0.824 0.645
同比赛其他方案