I'm trying to create a mew dicom image from a standard-sized (512 x 512 or 256 x 256) numpy array. It seems like this should be straightforward, and I've adapted my code from http://code.google.com/p/pydicom/source/browse/source/dicom/examples/write_new.py, which appears to execute the same process, but when I save the file, I can't view it either in RadiAnt or MicroDicom.
import dicom, dicom.UID
from dicom.dataset import Dataset, FileDataset
def write_dicom(pixel_array,filename):
file_meta = Dataset()
ds = FileDataset(filename, {},file_meta = file_meta,preamble="\0"*128)
ds.PixelData = pixel_array.tostring()
ds.save_as(filename)
return
if __name__ == "__main__":
import numpy as np
pixel_array = np.tile(np.arange(256).reshape(16,16), (16,16)) * 4
write_dicom(pixel_array,'pretty.dcm')
2020 update :)
None of these answers worked for me. This is what I ended up with to save a valid monochrome 16bpp MR slice which is correctly displayed at least in Slicer, Radiant and MicroDicom:
Note the following:
DICOM is a really complicated format. There are many dialects, and compatibilty is rather a question of luck. You could alternatively try
nibabel
, maybe its dialect is more appealing to RadiAnt or MicroDicom.In general, I'd recommend using Nifti-format whenever possible. Its standard is much more concise, and incompatibilities are rare. nibabel also supports this.
The above example works but causes many tools to complain about the DICOMs and they cannot even be read at all using itk/SimpleITK as a stack. The best way I have found for making DICOMs from numpy is by using the SimpleITK tools and generating the DICOMs slice-by-slice. A basic example (https://github.com/zivy/SimpleITK/blob/8e94451e4c0e90bcc6a1ffdd7bc3d56c81f58d80/Examples/DicomSeriesReadModifyWrite/DicomSeriesReadModifySeriesWrite.py) shows how to load in a stack, perform a transformation and then resave the files, but this can easily be modified by using the
The number of tags ultimately in output image is quite large and so manually creating all of them is tedious. Additionally SimpleITK supports 8, 16, 32-bit images as well as RGB so it is much easier than making them in pydicom.
Here is a functional version of the code I needed to write. It will write a 16-bit grayscale DICOM image from a given 2D array of pixels. According to the DICOM standard, the UIDs should be unique for each image and series, which this code doesn't worry about, because I don't know what the UIDs actually do. If anyone else does, I'll be happy to add it in.