In many AI for healthcare problems, images are provided in DICOM format and need to be converted to png or jpeg formats before using them to train a model. Below is a brief tutorial on how to convert CT dicom images to png format.

Step 01: Make sure the following packages are already installed on your machine or virtual environment.

# pip install pydicom
# pip install pylibjpeg pylibjpeg-libjpeg pydicom
# pip install --upgrade numpy
# opencv 

Step 02: Import all necessary libraries.

import numpy as np
import pydicom
import pylibjpeg
import os
import cv2
import dask
from tqdm.notebook import tqdm
from dask.diagnostics import ProgressBar
from pathlib import Path

Step 03: Write the Code

Here’s the code for handling multiple CT DICOM images and how to save them into pngs in your custom folders.

def Dicom_to_Image(input):
    """
    input: full dicom image path
    output: single channel image array with pixel values between 0 and 255
    """
    
    dcm_Img = pydicom.read_file(Path)

    rows = dcm_Img.get(0x00280010).value     #Get number of rows from tag (0028, 0010)
    cols = dcm_Img.get(0x00280011).value     #Get number of cols from tag (0028, 0011)

    #Instance_Number = int(dcm_Img.get(0x00200013).value)      #Get actual slice instance number from tag (0020, 0013)

    #Window_Center = dcm_Img.get(0x00281050).value    #Get window center from tag (0028, 1050)
    #Window_Width = dcm_Img.get(0x00281051).value     #Get window width from tag (0028, 1051)
    Window_Center = np.array(dcm_Img.WindowCenter)
    Window_Width = np.array(dcm_Img.WindowWidth)
    
    if Window_Center.size > 1:
      Window_Max = Window_Center[0] + Window_Width[0] / 2
      Window_Min = Window_Center[0] - Window_Width[0] / 2
    else:
      Window_Max = Window_Center + Window_Width / 2
      Window_Min = Window_Center - Window_Width / 2


    if (dcm_Img.get(0x00281052) is None):
        Rescale_Intercept = 0
    else:
        Rescale_Intercept = int(dcm_Img.get(0x00281052).value)

    if (dcm_Img.get(0x00281053) is None):
        Rescale_Slope = 1
    else:
        Rescale_Slope = int(dcm_Img.get(0x00281053).value)
    New_Img = np.zeros((rows, cols), np.uint8)
    Pixels = dcm_Img.pixel_array

    for i in range(0, rows):
        for j in range(0, cols):
            Pix_Val = Pixels[i][j]
            Rescale_Pix_Val = Pix_Val * Rescale_Slope + Rescale_Intercept

            if (Rescale_Pix_Val > Window_Max):       #if intensity is greater than max window
                New_Img[i][j] = 255
            elif (Rescale_Pix_Val < Window_Min):     #if intensity is less than min window
                New_Img[i][j] = 0
            else:
               New_Img[i][j] = int(((Rescale_Pix_Val - Window_Min) / (Window_Max - Window_Min)) * 255)     #Normalize the intensities
    output = New_Img
    
    return output


def dcm_to_png(filepath, outdir):
    """
        filepath: full dicom image path
        outdir: directory name where you want your image to be saved
    """
  image = Dicom_to_Image(filepath)
  dcm_filename = filepath.parts[-1]
  png_filename = dcm_filename.replace('.dcm','.png') # replace '.png' with '.jpg' to save image in jpeg format
  cv2.imwrite(outdir + png_filename, image) # image saved in outdir with png_filename in PNG format
  
  
outdir = '/Output Directory/' # Set directory where all png images will be saved
if not os.path.exists(outdir): # Loop to convert many images from dicom to PNG or JPEG
  os.mkdir(outdir)
  
dicom_img_paths = Path("/Input Directory/")  # Directory full of many dicom images to be converted
for imagepath in tqdm(dicom_img_paths):
  dcm_to_png(imagepath, outdir)

The images produced in the above code are grayscale images saved as 8 bit single channel png.

Updated:

Leave a comment