From 8ae33e32eee93dcfe350d21722a188d3370687dc Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 13 Jul 2026 11:23:04 +0100 Subject: [PATCH] refactor: handle multi-frame DICOM files by extracting the middle frame in get_PIL_image functions --- helpers/pydicom_PIL.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/helpers/pydicom_PIL.py b/helpers/pydicom_PIL.py index 7cec5855..9c22d9ff 100644 --- a/helpers/pydicom_PIL.py +++ b/helpers/pydicom_PIL.py @@ -89,9 +89,13 @@ def get_PIL_image(dataset): raise TypeError("Cannot show image -- DICOM dataset does not have " "pixel data") + # Handle multi-frame DICOM files by extracting the middle frame + pixel_array = dataset.pixel_array + if len(pixel_array.shape) == 3: + pixel_array = pixel_array[pixel_array.shape[0] // 2] # Apply modality lut - array = apply_modality_lut(dataset.pixel_array, dataset) + array = apply_modality_lut(pixel_array, dataset) # voi lut doesn't seem to help #array = apply_voi_lut(array, dataset) @@ -115,7 +119,8 @@ def get_PIL_image(dataset): # PIL size = (width, height) size = (dataset.Columns, dataset.Rows) - array = dataset.pixel_array + # For multi-frame we already have the middle frame sliced as 2D in pixel_array + array = pixel_array #array = apply_modality_lut(array, dataset) @@ -124,17 +129,11 @@ def get_PIL_image(dataset): #array = apply_windowing(array, dataset) array = lin_stretch_img(array, 0.1, 99.9) # Apply "linear stretching" (lower percentile 0.1 goes to 0, and percentile 99.9 to 255). - if dataset["PhotometricInterpretation"].value == "MONOCHROME1": # We need to invert array = np.invert(array) return PIL.Image.fromarray(array).convert('L') - pixel_data = array.tostring() - # Recommended to specify all details - # by http://www.pythonware.com/library/pil/handbook/image.htm - im = PIL.Image.frombuffer(mode, size, pixel_data, - "raw", mode, 0, 1) else: ew = dataset['WindowWidth'] ec = dataset['WindowCenter'] @@ -159,6 +158,11 @@ def get_PIL_image2(dataset): if ('PixelData' not in dataset): raise TypeError("Cannot show image -- DICOM dataset does not have " "pixel data") + + pixel_array = dataset.pixel_array + if len(pixel_array.shape) == 3: + pixel_array = pixel_array[pixel_array.shape[0] // 2] + # can only apply LUT if these window info exists if ('WindowWidth' not in dataset) or ('WindowCenter' not in dataset): bits = dataset.BitsAllocated @@ -176,20 +180,14 @@ def get_PIL_image2(dataset): raise TypeError("Don't know PIL mode for %d BitsAllocated " "and %d SamplesPerPixel" % (bits, samples)) - # PIL size = (width, height) - size = (dataset.Columns, dataset.Rows) - - # Recommended to specify all details - # by http://www.pythonware.com/library/pil/handbook/image.htm - im = PIL.Image.frombuffer(mode, size, dataset.PixelData, - "raw", mode, 0, 1) + im = PIL.Image.fromarray(pixel_array).convert('L') else: ew = dataset['WindowWidth'] ec = dataset['WindowCenter'] ww = int(ew.value[0] if ew.VM > 1 else ew.value) wc = int(ec.value[0] if ec.VM > 1 else ec.value) - image = get_LUT_value(dataset.pixel_array, ww, wc) + image = get_LUT_value(pixel_array, ww, wc) # Convert mode to L since LUT has only 256 values: # http://www.pythonware.com/library/pil/handbook/image.htm im = PIL.Image.fromarray(image).convert('L')