对DICOM图像重新采样,使其大小和间距与同一原点对齐

2024-09-20 03:38:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一套4个DICOM CT卷,我正在用SimpleITK ImageSeriesReader阅读。其中两幅图像分别代表病人手术前后的CT图像。另外两幅图像是在前两幅CT图像上分割的二值分割掩模。这些分割是源CT的一个ROI。在

所有4张CT图像,大小、间距、原点和方向都不同。我尝试过应用这个GitHub要点https://gist.github.com/zivy/79d7ee0490faee1156c1277a78e4a4c4来调整我的图像大小为512x512x512,间距为1x1x1。但是,它不能将图像放在正确的位置。分割后的结构总是放在CT图像的中心,而不是正确的位置,正如你从图片中看到的那样。在

这是我的“原始”DICOM图像与它的肿瘤分割(橙色斑点)。在

enter image description here

这是在“调整大小”算法并写入磁盘后(与之前相同的图像,只是由于不一致,肿瘤呈绿色斑点): enter image description here

用于将所有4个DICOM卷重采样到相同维度的代码:

def resize_resample_images(images):
    """ Resize all the images to the same dimensions, spacing and origin.
        Usage: newImage = resize_image(source_img_plan, source_img_validation, ROI(ablation/tumor)_mask)
        1. translate to same origin
        2. largest number of slices and interpolate the others.
        3. same resolution 1x1x1 mm3 - resample
        4. (physical space)
        Slice Thickness (0018,0050)
        ImagePositionPatient (0020,0032)
        ImageOrientationPatient (0020,0037)
        PixelSpacing (0028,0030)
        Frame Of Reference UID (0020,0052)
    """
    # %% Define tuple to store the images
    tuple_resized_imgs = collections.namedtuple('tuple_resized_imgs',
                                                ['img_plan',
                                                 'img_validation',
                                                 'ablation_mask',
                                                 'tumor_mask'])
    # %% Create Reference image with zero origin, identity direction cosine matrix and isotropic dimension
    dimension = images.img_plan.GetDimension()  #
    reference_direction = np.identity(dimension).flatten()
    reference_size = [512] * dimension
    reference_origin = np.zeros(dimension)
    data = [images.img_plan, images.img_validation, images.ablation_mask, images.tumor_mask]

    reference_spacing = np.ones(dimension) # resize to isotropic size
    reference_image = sitk.Image(reference_size, images.img_plan.GetPixelIDValue())
    reference_image.SetOrigin(reference_origin)
    reference_image.SetSpacing(reference_spacing)
    reference_image.SetDirection(reference_direction)
    reference_center = np.array(
        reference_image.TransformContinuousIndexToPhysicalPoint(np.array(reference_image.GetSize()) / 2.0))

    #%% Paste the GT segmentation masks before transformation
    tumor_mask_paste = (paste_roi_image(images.img_plan, images.tumor_mask))
    ablation_mask_paste = (paste_roi_image(images.img_validation, images.ablation_mask))
    images.tumor_mask = tumor_mask_paste
    images.ablation_mask = ablation_mask_paste


    # %%  Apply transforms
    data_resized = []
    for idx,img in enumerate(data):
        transform = sitk.AffineTransform(dimension) # use affine transform with 3 dimensions
        transform.SetMatrix(img.GetDirection()) # set the cosine direction matrix
        # TODO: check translation when computing the segmentations
        transform.SetTranslation(np.array(img.GetOrigin()) - reference_origin) # set the translation.
        # Modify the transformation to align the centers of the original and reference image instead of their origins.
        centering_transform = sitk.TranslationTransform(dimension)
        img_center = np.array(img.TransformContinuousIndexToPhysicalPoint(np.array(img.GetSize()) / 2.0))
        centering_transform.SetOffset(np.array(transform.GetInverse().TransformPoint(img_center) - reference_center))
        centered_transform = sitk.Transform(transform)
        centered_transform.AddTransform(centering_transform)
        # Using the linear interpolator as these are intensity images, if there is a need to resample a ground truth
        # segmentation then the segmentation image should be resampled using the NearestNeighbor interpolator so that
        # no new labels are introduced.

        if (idx==1 or idx==2): # temporary solution to resample the GT image with NearestNeighbour
            resampled_img = sitk.Resample(img, reference_image, centered_transform, sitk.sitkNearestNeighbor, 0.0)

        else:
             resampled_img = sitk.Resample(img, reference_image, centered_transform, sitk.sitkLinear, 0.0)
        # append to list
        data_resized.append(resampled_img)


    # assuming the order stays the same, reassigng back to tuple
    resized_imgs = tuple_resized_imgs(img_plan=data_resized[0],
                                      img_validation=data_resized[1],
                                      ablation_mask=data_resized[2],
                                      tumor_mask=data_resized[3])

将ROI分段图像“粘贴”到正确大小的代码。可能是多余的。

^{pr2}$

Tags: theto图像imageimgdatanptransform