Skip to content

Convert DICOM

DICOM to JPG

Converts a single dicom file to an 8 bit format

Convert

#Code modified from Ian Pan https://storage.googleapis.com/kaggle-forum-message-attachments/1010629/17014/convert_to_jpeg_for_kaggle.py

def convert_ct_dicom_to_8bit(dicom_file, windows = [[350,40],[1500,-500],[120,70]], imsize=(256.,256.), should_remove_padding = True):
    '''
    Given a DICOM file, window specifications, and image size, return the
    image as a Numpy array scaled to [0,255] of the specified size.

    Parameters
    ----------
    dicom_file: str
        filename that ends in .dcm
    windows: list of lists of ints
        list of window width and window level values
    imsize: tuplet of float
        desired output image size
    should_remove_padding: bool
        if True will remove extra rows/columns of zeroes around the image
    '''
    array = apply_slope_intercept(dicom_file)

    if should_remove_padding:
        array = remove_padding(array)

    #different width, level for each RGB channel
    image = apply_windows(array, windows)
    #resize
    image = resize(image, imsize)

    return image

Save as jpg

    image = convert_ct_dicom_to_8bit(dicom_file, windows = [[350,40],[1500,-500],[120,70]], imsize=(256.,256.), should_remove_padding = True)
    im = Image.fromarray(image)
    im.save(dicom_file[-4:] + '.jpg')

Supporting functions

import pandas as pd
import numpy as np
import pydicom
from scipy.ndimage.interpolation import zoom

#Applies slope and intercept from DICOM tags
def apply_slope_intercept(dicom_file):
    array = dicom_file.pixel_array.copy()
    try:
        slope = float(dicom_file.RescaleSlope)
        intercept = float(dicom_file.RescaleIntercept)
    except Exception:
        slope = 1
        intercept = 0
    if slope != 1 or intercept != 0:
        array = array * slope
        array = array + intercept
    return array

#Removes zeroes around image
def remove_padding(array):
    array = array.copy()
    nonzeros = np.nonzero(array)
    x1 = np.min(nonzeros[0]) ; x2 = np.max(nonzeros[0])
    y1 = np.min(nonzeros[1]) ; y2 = np.max(nonzeros[1])
    return array[x1:x2,y1:y2]

#Apply different W/L settings to different channels to take advantage of RGB structure
def apply_windows(array, windows):
    layers = []
    for values in windows:
        if len(value) >= 2:
            ww = values[0]
            wl = values[1]
            layers.append(np.expand_dims(window(array, WL=wl, WW=ww), axis=3))
    if len(layers) == 0:
        return np.expand_dims(window(array, WL=350, WW=40), axis=3)
    else:
        return np.concatenate(layers, axis=3)

#Resize
def resize(image, imsize):
    rat = max(imsize) / np.max(image.shape[1:])
    return zoom(image, [1.,rat,rat,1.], prefilter=False, order=1)

Common window width and window level for CT exams

Target WW WL
brain 80 40
subdural 215 75
stroke_1 8 32
stroke_2 40 40
temporal_bone 2800 600
neck_soft_tissue 375 40
lung 1500 -500
emphysema 800 -800
mediastinum 400 40
pulmonary_embolism 700 100
abdomen 350 40
liver 120 70
kidney 700 50
bone 2500 480

DICOM to/from nifti

Convert CT nifti to DICOM

Use the convert_ct function in common_utils to convert nifti files to DICOM for upload to MD.ai. You'll need to choose your input and output directories. Optionally, you can change the plane or default window/level settings. You'll also need a sample dicom which you can download from sample image

results = mdai.common_utils.convert_ct(
    input_dir=None,
    output_dir=None,
    input_ext=".nii.gz",
    plane="axial",
    sample_dicom_fp=os.path.join(os.path.dirname(""), "./sample_dicom.dcm"),
    window_center=40,
    window_width=350,
)

This function will write the converted DICOM files to the output directory and will give each image from a nifti file the same Study and Series UIDs. Use the CLI tool to upload the newly created DICOM images into your project

Convert DICOM to nifti

Use the dicom2nifiti library from icometrix

!pip install dicom2nifti
import dicom2nifti
dicom2nifti.convert_directory(dicom_directory, output_folder, compression=True, reorient=True)

This will convert the dicom files from the dicom_directory to the output_folder.

Support functions

DICOM UIDs and tags from your original files

Use this code on your original data to create dictionaries of the UIDs from the image filenames. You can also use this as a base for getting additional DICOM tags such as PatientPosition, SeriesDescription, InstanceNumber, etc.

from pathlib import Path
import pydicom as py

images_path = Path('MY_PATH')
original_fn = list(images_path.glob('**/*.dcm'))

file_dict_sop = dict()
file_dict_series = dict()
file_dict_study = dict()

for f in original_fn:
    d = py.dcmread(str(f))
    file_dict_sop[f] = d.SOPInstanceUID
    file_dict_series[f] = d.SeriesInstanceUID
    file_dict_study[f] = d.StudyInstanceUID