Skip to content

Issue with Multilayer NIfTI to DICOM SEG Conversion - Double (Incorrect) Number of Frames in Output DCM SEG #510

@zain18jan2000

Description

@zain18jan2000

I am trying to convert a multilayer NIFTI file to a DICOM SEG file using the itkimage2segimage tool from dcmqi. After conversion the output DICOM SEG file contains two times the actual number of frames.

For example:

If input NIFTI has 203 frames and 2 labels segmentations (e.g., Liver, Spleen).
My multilayer output Dicom SEG file contains 2 × 203 = 406 frames, with each set of 203 frames corresponding to a single label. however the expected multilayer output DICOM SEG file should contains 203 frames only, where each frame contains the combined segmentation for both labels.

Here is the Python code I used to perform the conversion:

import nibabel as nib  # To validate NIfTI labels
import subprocess
import os
import pydicom
import json


def get_unique_labels_from_nifti(nifti_file):
    """
    Extracts unique labels from the NIfTI file.
    Args:
        nifti_file (str): Path to the NIfTI file.
    Returns:
        list: Sorted unique labels (intensity values) in the NIfTI file.
    """
    nifti_data = nib.load(nifti_file).get_fdata()
    unique_labels = sorted(set(nifti_data.flatten()))
    return [int(label) for label in unique_labels if label > 0]  # Exclude background (0)


def convert_nifti_to_dcm_seg(nifti_file, dicom_dir, output_seg_file):
    """
    Converts a NIfTI segmentation file to DICOM SEG using itkimage2segimage.

    Args:
        nifti_file (str): Path to the input NIfTI file.
        dicom_dir (str): Directory containing the DICOM files.
        output_seg_file (str): Path to save the output DICOM SEG file.
    """
    # Ensure output directory exists
    os.makedirs(os.path.dirname(output_seg_file), exist_ok=True)

    # Extract the StudyInstanceUID from one of the DICOM files in the directory
    dicom_file = os.path.join(dicom_dir, os.listdir(dicom_dir)[0])
    study_instance_uid = pydicom.dcmread(dicom_file).StudyInstanceUID

    # Validate the labels in the NIfTI file
    labels_in_nifti = get_unique_labels_from_nifti(nifti_file)
    print(f"Unique labels in NIfTI file: {labels_in_nifti}")

    # Generate segment attributes for each class
    segment_attributes = []

    # Example descriptions for each label
    descriptions = {
        labels_in_nifti[0]: "Liver",
        labels_in_nifti[1]: "Spleen"
    }

    for i, label in enumerate(labels_in_nifti):
        segment_attributes.append({
            "SegmentNumber": i+1,
            "labelID": label,
            "SegmentDescription": descriptions.get(label, "Unknown"),
            "SegmentAlgorithmType": "AUTOMATIC",
            "SegmentAlgorithmName": "TotalSegmentator",
            "SegmentedPropertyCategoryCodeSequence": {
                "CodeValue": "T-D0050" if label == labels_in_nifti[0] else "T-62000",
                "CodingSchemeDesignator": "SCT",
                "CodeMeaning": "Anatomical Structure"
            },
            "SegmentedPropertyTypeCodeSequence": {
                "CodeValue": "10200004" if label == labels_in_nifti[0] else "10200005",
                "CodingSchemeDesignator": "SCT",
                "CodeMeaning": descriptions.get(label, "Unknown")
            }
        })

    # Construct metadata
    metadata = {
        "ContentCreatorName": "Reader1",
        "ClinicalTrialSeriesID": "Session1",
        "ClinicalTrialTimePointID": "1",
        "SeriesDescription": "Segmentation",
        "SeriesNumber": "300",
        "InstanceNumber": "1",
        "BodyPartExamined": "Liver and Spleen",
        "segmentAttributes": [segment_attributes],
        "ContentLabel": "SEGMENTATION",
        "ContentDescription": "Image segmentation",
        "ClinicalTrialCoordinatingCenterName": "dcmqi"
    }

    # Save metadata to a JSON file
    metadata_file = os.path.join(os.path.dirname(output_seg_file), "metadata.json")
    with open(metadata_file, "w") as f:
        json.dump(metadata, f, indent=4)

    # Construct the command to convert the NIfTI to DICOM SEG
    cmd = [
        r'/media/zain/New Volume/PycharmProjects/XRAD/.venv/lib/python3.10/site-packages/dcmqi/bin/itkimage2segimage',
        "--inputImageList", nifti_file,
        "--inputMetadata", metadata_file,
        "--outputDICOM", output_seg_file,
        "--inputDICOMDirectory", dicom_dir,
        "--skip", "0"
    ]

    try:
        # Execute the command
        result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        print("Conversion successful!")
        print("Output:", result.stdout)
    except subprocess.CalledProcessError as e:
        # Handle errors
        print("Error during conversion:")
        print("Output:", e.stdout)
        print("Error:", e.stderr)


# Example usage
nifti_file = "niftis/2.25.1937671288494678696440169598763456789/2.25.1937671288494678696440169598763456789_seg.nii.gz"  # Path to your NIfTI file
dicom_dir = "dicoms/2.25.1937671288494678696440169598763456789/"  # Directory containing the DICOM files
output_seg_file = "./output/multi_class_seg.dcm"  # Path to save the DICOM SEG file

convert_nifti_to_dcm_seg(nifti_file, dicom_dir, output_seg_file)

Conversion command used in above python script

itkimage2segimage --inputImageList <nifti_file> \
                  --inputMetadata <metadata.json> \
                  --outputDICOM <output_seg_file> \
                  --inputDICOMDirectory <dicom_dir> \
                  --skip 0

To help debug this issue, I am sharing the files - link

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions