如何用Python去除Nifti图像各切片中的床区以优化无监督分割
去除Nifti图像切片中床区干扰的实操方案
一、先定位床区特征
床区在医学图像里通常有明显特征:要么是均匀低信号(CT)要么是均匀高信号(MRI),且几乎所有切片里都处于边缘位置。先拿任意一张切片(比如中间层)的聚类结果可视化,确定床区对应的聚类标签——比如观察颜色条,边缘大面积区域对应的标签值就是床区标签。
二、批量处理所有切片的方法
方法1:基于聚类标签直接过滤(最直接)
如果聚类已经把床区归为单独标签,直接把该标签设为背景即可:
import nibabel as nib import numpy as np # 加载数据 img = nib.load('your_raw_image.nii.gz') img_data = img.get_fdata() # 形状(512,512,299) cluster_data = nib.load('your_cluster_result.nii.gz').get_fdata() # 若聚类结果是单张切片((512,512)),复制到所有层 if cluster_data.shape == (512,512): cluster_data = np.repeat(cluster_data[..., np.newaxis], 299, axis=2) # 确定床区标签(比如可视化后发现是0) bed_label = 0 # 过滤床区:将床区标签替换为背景值(比如0) cleaned_cluster = np.where(cluster_data == bed_label, 0, cluster_data) # 可选:同时在原图像上掩码掉床区 cleaned_img = np.where(cluster_data == bed_label, 0, img_data) # 保存结果 nib.save(nib.Nifti1Image(cleaned_cluster, img.affine, img.header), 'cleaned_cluster.nii.gz') nib.save(nib.Nifti1Image(cleaned_img, img.affine, img.header), 'cleaned_raw_image.nii.gz')
方法2:基于图像强度阈值过滤(聚类没区分开床区时用)
如果聚类没单独分出床区,直接用原图像的强度特征过滤:
for slice_idx in range(299): slice_raw = img_data[..., slice_idx] slice_cluster = cluster_data[..., slice_idx] # 取切片强度的5百分位作为阈值(床区通常低于该值,可根据图像调整) threshold = np.percentile(slice_raw, 5) # 掩码掉低强度的床区 slice_cluster[slice_raw < threshold] = 0 cluster_data[..., slice_idx] = slice_cluster
方法3:基于形态学/连通区域分析(床区是边缘大块区域时用)
如果床区是边缘的大面积区域,保留中心最大的连通区域(对应人体组织)即可:
from skimage.measure import label from skimage.morphology import remove_small_objects for slice_idx in range(299): slice_cluster = cluster_data[..., slice_idx] # 转二进制掩码(非背景区域) binary_mask = slice_cluster != 0 # 标记所有连通区域 labeled_regions = label(binary_mask) # 计算每个区域的面积 region_areas = np.bincount(labeled_regions.flatten()) # 找到面积最大的区域(排除背景标签0) max_region_label = region_areas[1:].argmax() + 1 # 只保留最大区域,其余设为0 slice_cluster_clean = np.where(labeled_regions == max_region_label, slice_cluster, 0) cluster_data[..., slice_idx] = slice_cluster_clean
内容的提问来源于stack exchange,提问作者Manali Thakur
相关产品推荐
相关产品推荐

