简体   繁体   中英

Medical Imaging with python

I have an image in DICOM format, this image is composed of a set of RAW files (a specific case 122, which would be the number of slices that the image would have, depth in Z). The size of the image is 512x512x122 voxels. The program I have made reads iteratively these files using pydicom. Once I read them, I store the pixel data in a numpy array so I can visualize with matplotlib. I am doing all this because I am going to use PENELOPE to perform some simulations and, coincidentally, the RAW format that can be produced or is compatible with AMIDE is the same one used by PENELOPE (if it is OK in AMIDE, it will be OK for PENELOPE). That's why I try, first of all, from the original image in DICOM format to export it to another format compatible with AMIDE. I have tried to save it in RAW format and the image is broken, on the other hand in NIFTI format the AMIDE image looks like the original one, but I lose all the information concerning the Hounsfield units and, therefore, this image is not suitable to perform a simulation. I need a solution that allows me to save the image in a format compatible with AMIDE (ideally in RAW format, but I have not been able to do it well and I can't think how) and keep the Hounsfield units.(1)

I have also tried converting to Hounsfield units directly and the image comes out, but the Hounsfield unit information is lost.(2)

(1)

array_filenames = []
array_slices = []
array_volume = []

for filename in os.listdir(path):
    array_filenames.append(filename.split("IMG")[1])

array_filenames.sort() #ordenamos la lista

for j, elto in enumerate(array_filenames): array_filenames[j] = f"IMG{array_filenames[j]}" #completamos el nombre del fichero, "IMG****"

for slice in array_filenames:
    filename_good = path + "\\" + slice
    array_slices.append(pydicom.read_file(filename_good))

for elto_z in array_slices:
    array_volume.append(elto_z.pixel_array)
    
array_imagen = np.array(array_volume)

img = nib.Nifti1Image(array_imagen , affine=np.eye(4))
nib.save(img, path_save + "\\" + "name.nii.gz")

(2)

array_filenames = []
array_slices = []
array_volume = []
n_rodajas = 0
for filename in os.listdir(path):
        
    if(filename.split(".")[-1] == "raw" or filename.split(".")[-1] == "nii" or filename.split(".")[-1] == "png"):
        continue
        
    elif isinstance(int(filename.split("I")[-1]), int):
        array_filenames.append(int(filename.split("I")[-1]))
        n_rodajas += 1
        
array_filenames.sort()
# print(array_filenames)
for j, elto in enumerate(array_filenames): array_filenames[j] = f"I{array_filenames[j]}"
#print(array_filenames)


#Abrimos el primer fichero para obtener datos relevantes
ds = pydicom.dcmread(os.path.join(path, array_filenames[0]))
img_size = (int(ds.Rows), int(ds.Columns), n_rodajas)
voxel_spacing = ( float(ds.PixelSpacing[0]), float(ds.PixelSpacing[1]), float(ds.SliceThickness))

#Creamos una matriz tridemnsional para almacenar los valores HU
img_HU = np.zeros(img_size, dtype = ds.pixel_array.dtype)

for i, slice in enumerate(array_filenames):
    #filename_good = path + "\\" + slice
    # print(filename_good)
    #array_slices.append(pydicom.read_file(filename_good))
    filename_good = path + "\\" + slice
    data_set = pydicom.dcmread(filename_good)
    raw_array = data_set.pixel_array
    slope = data_set.RescaleSlope
    intercept = data_set.RescaleIntercept
    img_HU[:, :, i] = raw_array.astype(ds.pixel_array.dtype) * slope * intercept

Both codes bring up the images, but the information from the Hounsfield units is lost.

Original image:原图

Image created in NIFTI format:以 NIFTI 格式创建的图像

Dicom files contain pixel values in "raw" values, that are machine dependent. So for CT's, the actual values stored in the pixel_array tag are not in (physical) HU values, and they need to be converted to HU values based on other tags in the file.

The most common way is a linear transform using rescale slope and intercept tags (but not the only one - you could google those tags above and find more info about them, as well as the various LUT (lookup table) transforms that dicom support)

Pydicom recently added a method to return the pixel data in physical values by applying the pixel value transformations automatically for you, depending on what tags are present (rescale, LUT's etc). See https://pydicom.github.io/pydicom/dev/old/working_with_pixel_data.html#modality-lut-or-rescale-operation

In your code above, from the (1) example, all you need to do is change these lines:

for elto_z in array_slices:
   array_volume.append(elto_z.pixel_array)

to:

for elto_z in array_slices:
   array_volume.append(apply_modality_lut(elto_z.pixel_array, elto_z)

with this in your includes:

from pydicom.pixel_data_handlers.util import apply_modality_lut

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM