Dicom to PNG Conversion - output image is completely black

Viewed 1528

While conversion of dicom to png using Python, without getting any error. Output file is complete Black, although image array have variable values.

Code:

import pydicom
import cv2
import os

dicom = pydicom.dcmread(inputdir + f)
# print("dicom", dicom)
img = dicom.pixel_array
print("img", img)
cv2.imwrite(outdir + f.replace('.dcm','.png'),img)

Image array (for reference):

[[585 585 570 ... 570 572 570]
[585 585 585 ... 572 575 572]
[585 585 585 ... 553 568 575]
...
[854 854 854 ... 778 783 787]
[854 854 856 ... 783 785 787]
[854 856 856 ... 785 790 759]]
2 Answers

According to docs.opencv.org, cv2.imwrite generally "prefers" the image data to be in 8-bit representation (i.e. value ranges from 0 to 255 only).

In general, only 8-bit single-channel or 3-channel (with 'BGR' channel order) images can be saved using this function ...

I noticed that your image data is more than 8-bit, hence you will need to either (a) scale it then cast it to np.uint8, or (b) to reduce the bit representation to 8 bit.

Example of (a) scaling:

import numpy as np  # assuming that you have numpy installed
img = np.array(img, dtype = float) 
img = (img - img.min()) / (img.max() - img.min()) * 255.0  
img = img.astype(np.uint8)
cv2.imwrite(outdir + f.replace('.dcm','.png'),img)

or, Example of (b) bitshifting to 8-bit:

bit_depth = 10  #  assuming you know the bit representation
img = np.array(img, dtype = np.uint16)
img = img >> (bit_depth - 8)  
img = img.astype(np.uint8)
cv2.imwrite(outdir + f.replace('.dcm','.png'),img)

But since you are saving your image in PNG format, here is shorter way...

, with these exceptions:

  • 16-bit unsigned (CV_16U) images can be saved in the case of PNG, JPEG 2000, and TIFF formats
  • ...

you can just cast your image to np.uint16 :)

img = img.astype(np.uint16)
cv2.imwrite(outdir + f.replace('.dcm','.png'),img)

Adding the next line to code after "dicom.pixel_array" will do the trick.

## Rescaling grey scale between 0-255
scaled_img = (np.maximum(img,0) / img.max()) * 255.0
Related