Tutorial

Working with DICOM Images in Python for Deep Learning

Difficulty: Beginner Time: 15 min read

Introduction

DICOM (Digital Imaging and Communications in Medicine) is the international standard for medical images and related information. In this cookbook, we'll learn how to read DICOM files using Python, extract metadata, handle windowing/leveling (Hounsfield Units), and prepare the pixel data for PyTorch deep learning models using MONAI.

Architecture Overview


graph LR
    DICOM(Raw DICOM Files) --> Pydicom(Pydicom Extract Metadata)
    DICOM --> Window(Window / Leveling)
    Window --> NIfTI(Optional: dcm2niix to NIfTI)
    Window --> MONAI(MONAI Transform Pipeline)
    MONAI --> Tensor(PyTorch Tensors)
        

Prerequisites

  • Python 3.8+
  • pydicom, MONAI, and dcm2niix installed

Step 1: Install Dependencies

pip install pydicom monai matplotlib numpy torch dcm2niix

Step 2: Read DICOM Metadata with pydicom

DICOM files contain more than just pixels; they hold critical PHI and scanner metadata.

import pydicom

# Load the DICOM file
ds = pydicom.dcmread('sample_image.dcm')

# Access metadata
print(f"Patient ID: {ds.PatientID}")
print(f"Modality: {ds.Modality}")
print(f"Study Date: {ds.StudyDate}")

# Extract raw pixel array
pixels = ds.pixel_array

Step 3: Handling Hounsfield Units (CT Windowing)

Raw pixel arrays often need to be converted to Hounsfield Units (HU) using the Rescale Intercept and Rescale Slope metadata tags. We then apply a "window" to isolate specific tissues (e.g., lungs vs bone).

import numpy as np

def apply_windowing(image, ds, window_center, window_width):
    # Apply Rescale Slope / Intercept
    slope = getattr(ds, 'RescaleSlope', 1)
    intercept = getattr(ds, 'RescaleIntercept', 0)
    image = image * slope + intercept
    
    # Calculate Window Level min/max
    img_min = window_center - window_width // 2
    img_max = window_center + window_width // 2
    
    # Clip and normalize
    image = np.clip(image, img_min, img_max)
    image = (image - img_min) / (img_max - img_min)
    return image

# Example: Lung Window (Center: -600, Width: 1500)
lung_window_img = apply_windowing(pixels, ds, -600, 1500)

Step 4: Converting DICOM series to NIfTI

For 3D convolutional networks, it is often easier to convert a folder of 2D DICOM slices into a single 3D NIfTI volume using dcm2niix.

# Assuming dcm2niix is installed on your system
dcm2niix -z y -o ./output_folder/ -f %p_%i ./dicom_folder/

Step 5: Build a Data Loading Pipeline with MONAI

When training models, we need efficient data loaders. MONAI provides DICOM and NIfTI-native transforms.

import monai
from monai.transforms import Compose, LoadImaged, EnsureChannelFirstd, ScaleIntensityd, ToTensord

# Define a transformation pipeline for a dictionary of image paths
transforms = Compose([
    LoadImaged(keys=["image"]),
    EnsureChannelFirstd(keys=["image"]),
    ScaleIntensityd(keys=["image"]),
    ToTensord(keys=["image"])
])

# Create a dataset and dataloader
data = [{"image": "sample_image.dcm"}]
dataset = monai.data.Dataset(data=data, transform=transforms)
dataloader = monai.data.DataLoader(dataset, batch_size=1)

# Iterate through batches
for batch in dataloader:
    img_tensor = batch["image"]
    print(img_tensor.shape) # e.g. [1, 1, 512, 512]

Conclusion

With pydicom, proper windowing techniques, and MONAI, preparing raw hospital DICOM streams for high-performance PyTorch models is seamless and efficient.