Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to convert dicom to jpeg #352

Closed
wanghaisheng opened this issue May 11, 2017 · 14 comments
Closed

how to convert dicom to jpeg #352

wanghaisheng opened this issue May 11, 2017 · 14 comments
Labels

Comments

@wanghaisheng
Copy link

what i want is to get a jpeg file for each dcm file ?is there any best practices of pydicom ,i find nothing looking over documentation

@scaramallion
Copy link
Member

scaramallion commented May 12, 2017

Not tested, but you should be able to use pillow and numpy:

from PIL.Image import fromarray

ds = read_file('file-in.dcm')
im = fromarray(ds.pixel_array)
im.save('file-out.jpg')

You will likely have to do some work to ensure you have the image data in a suitable format prior to saving.

@mrbean-bremen
Copy link
Member

I think this can be closed as answered.

@tedivm
Copy link

tedivm commented Jul 21, 2018

This doesn't work for me, so I'm guessing it doesn't work for others. I'm including some code that converts a dicom file into a png for the next person who ends up here via google :-)

import numpy as np
import png
import pydicom

ds = pydicom.dcmread(path)

shape = ds.pixel_array.shape

# Convert to float to avoid overflow or underflow losses.
image_2d = ds.pixel_array.astype(float)

# Rescaling grey scale between 0-255
image_2d_scaled = (np.maximum(image_2d,0) / image_2d.max()) * 255.0

# Convert to uint
image_2d_scaled = np.uint8(image_2d_scaled)

# Write the PNG file
with open(destination, 'wb') as png_file:
    w = png.Writer(shape[1], shape[0], greyscale=True)
    w.write(png_file, image_2d_scaled)

@wanghaisheng
Copy link
Author

@tedivm wonderful

@rohit-ptl
Copy link

rohit-ptl commented Feb 26, 2019

Thanks @tedivm. Wrapped your code into a function for convenient copy-paste

import numpy as np
import png, os, pydicom

source_folder = r'path\to\source'
output_folder = r'path\to\output\folder'


def dicom2png(source_folder, output_folder):
    list_of_files = os.listdir(source_folder)
    for file in list_of_files:
        try:
            ds = pydicom.dcmread(os.path.join(source_folder,file))
            shape = ds.pixel_array.shape

            # Convert to float to avoid overflow or underflow losses.
            image_2d = ds.pixel_array.astype(float)

            # Rescaling grey scale between 0-255
            image_2d_scaled = (np.maximum(image_2d,0) / image_2d.max()) * 255.0

            # Convert to uint
            image_2d_scaled = np.uint8(image_2d_scaled)

            # Write the PNG file
            with open(os.path.join(output_folder,file)+'.png' , 'wb') as png_file:
                w = png.Writer(shape[1], shape[0], greyscale=True)
                w.write(png_file, image_2d_scaled)
        except:
            print('Could not convert: ', file)


dicom2png(source_folder, output_folder)

@tedivm
Copy link

tedivm commented Feb 26, 2019

@Rohit-Patel - you forgot to import os ;-)

@samra-irshad
Copy link

This doesn't work for me, so I'm guessing it doesn't work for others. I'm including some code that converts a dicom file into a png for the next person who ends up here via google :-)

import numpy as np
import png
import pydicom

ds = pydicom.dcmread(path)

shape = ds.pixel_array.shape

# Convert to float to avoid overflow or underflow losses.
image_2d = ds.pixel_array.astype(float)

# Rescaling grey scale between 0-255
image_2d_scaled = (np.maximum(image_2d,0) / image_2d.max()) * 255.0

# Convert to uint
image_2d_scaled = np.uint8(image_2d_scaled)

# Write the PNG file
with open(destination, 'wb') as png_file:
    w = png.Writer(shape[1], shape[0], greyscale=True)
    w.write(png_file, image_2d_scaled)

Only solution that worked for my problem, thank you!

@kyshel
Copy link

kyshel commented Jul 10, 2020

This doesn't work for me, so I'm guessing it doesn't work for others. I'm including some code that converts a dicom file into a png for the next person who ends up here via google :-)

import numpy as np
import png
import pydicom

ds = pydicom.dcmread(path)

shape = ds.pixel_array.shape

# Convert to float to avoid overflow or underflow losses.
image_2d = ds.pixel_array.astype(float)

# Rescaling grey scale between 0-255
image_2d_scaled = (np.maximum(image_2d,0) / image_2d.max()) * 255.0

# Convert to uint
image_2d_scaled = np.uint8(image_2d_scaled)

# Write the PNG file
with open(destination, 'wb') as png_file:
    w = png.Writer(shape[1], shape[0], greyscale=True)
    w.write(png_file, image_2d_scaled)

@tedivm
got an error, maybe it can be optimized?

Traceback (most recent call last):
  File "D:/ml/untitled/dcm2png.py", line 81, in <module>
    dcm2png(file,'png2\\'+file+'.png')
  File "D:/ml/untitled/dcm2png.py", line 16, in dcm2png
    shape = ds.pixel_array.shape
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\dataset.py", line 778, in __getattr__
    return object.__getattribute__(self, name)
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\dataset.py", line 1615, in pixel_array
    self.convert_pixel_data()
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\dataset.py", line 1324, in convert_pixel_data
    self._convert_pixel_data_without_handler()
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\dataset.py", line 1434, in _convert_pixel_data_without_handler
    raise last_exception
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\dataset.py", line 1414, in _convert_pixel_data_without_handler
    self._do_pixel_data_conversion(handler)
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\dataset.py", line 1441, in _do_pixel_data_conversion
    arr = handler.get_pixeldata(self)
  File "D:\ProgramData\Anaconda3\envs\py36\lib\site-packages\pydicom\pixel_data_handlers\numpy_handler.py", line 263, in get_pixeldata
    "Unable to convert the pixel data: one of Pixel Data, Float "
AttributeError: Unable to convert the pixel data: one of Pixel Data, Float Pixel Data or Double Float Pixel Data must be present in the dataset

@ykuo2
Copy link

ykuo2 commented Jun 4, 2021

I'm working on this problem recently. It turns out that there are many things to consider on converting DICOM to JPG.
For example, we have to check tags/attributes below and adjust accordingly

  • window center(level) and window width
  • does it need to apply VOI LUT function
  • does it need negative inversion
  • does it contains more than one images (eg. fluoroscopic images)
  • does it contains filetype that is not an image (eg. PDF file)
  • if it is a colored file, there are some matrix manipulation to work on
  • and many amazing DICOM tags/attributes...

Here is my preliminary package , please have a look, hope it would help.

import dicom2jpg

dicom_img_01 = "/Users/user/Desktop/img01.dcm"
dicom_dir = "/Users/user/Desktop/Patient_01"
export_location = "/Users/user/Desktop/BMP_files"

# convert single DICOM file to jpg format
dicom2jpg.dicom2jpg(dicom_img_01)  

# convert all DICOM files in dicom_dir folder to png format
dicom2jpg.dicom2png(dicom_dir)  

# convert all DICOM files in dicom_dir folder to bmp, to a specified location
dicom2jpg.dicom2bmp(dicom_dir, target_root=export_location) 

@tommy-qichang
Copy link

I think there's some fundamental issues here. The Dicom image data has much larger range (eg. CT: -1024 HU to 3071 HU)and if you convert it to uint8, you loss information.

@kyshel
Copy link

kyshel commented Jun 23, 2021

@tommy-qichang so, is there some recommend ways to convert that not lost info? maybe convert to 3 channel ?

@tommy-qichang
Copy link

I think PIL support I16 so @scaramallion 's solution should be better.

@scaramallion
Copy link
Member

scaramallion commented Jun 23, 2021

PIL's JPEG2000 plugin doesn't support encoding signed data. It might "work" but it won't be correct.

@yehudahkay
Copy link

None of the answers worked for me with a single frame dicom, the colors were always off. Strange when using a multi frame dicom the following code worked fine

for index, slice in enumerate(pixel_array):
                cv2.imwrite(filename, slice)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests