|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +# @Author : LG |
| 3 | + |
| 4 | +import numpy as np |
| 5 | +import pydicom |
| 6 | +from pydicom.multival import MultiValue |
| 7 | +from PIL import Image |
| 8 | + |
| 9 | + |
| 10 | +def load_dcm_as_image(ds_file): |
| 11 | + ds = pydicom.dcmread(ds_file) |
| 12 | + # Apply Rescale Slope and Rescale Intercept if they exist |
| 13 | + pixel_array = ds.pixel_array.astype(float) |
| 14 | + rescale_slope = ds.get("RescaleSlope", 1) |
| 15 | + rescale_intercept = ds.get("RescaleIntercept", 0) |
| 16 | + if rescale_slope != 1 or rescale_intercept != 0: |
| 17 | + pixel_array = pixel_array * rescale_slope + rescale_intercept |
| 18 | + |
| 19 | + # Check for windowing information in the DICOM metadata |
| 20 | + window_center = ds.get("WindowCenter", None) |
| 21 | + window_width = ds.get("WindowWidth", None) |
| 22 | + |
| 23 | + if window_center is None or window_width is None: |
| 24 | + # If no windowing info, use the full dynamic range |
| 25 | + window_min = pixel_array.min() |
| 26 | + window_max = pixel_array.max() |
| 27 | + else: |
| 28 | + # Handle possible multi-valued tags by taking the first value |
| 29 | + if isinstance(window_center, MultiValue): |
| 30 | + window_center = window_center[0] |
| 31 | + if isinstance(window_width, MultiValue): |
| 32 | + window_width = window_width[0] |
| 33 | + |
| 34 | + window_min = window_center - window_width / 2 |
| 35 | + window_max = window_center + window_width / 2 |
| 36 | + |
| 37 | + # Apply windowing |
| 38 | + pixel_array = np.clip(pixel_array, window_min, window_max) |
| 39 | + |
| 40 | + # Normalize to 0-255 |
| 41 | + if window_max > window_min: |
| 42 | + pixel_array = ((pixel_array - window_min) / (window_max - window_min)) * 255.0 |
| 43 | + else: # Handle case where all pixels are the same |
| 44 | + pixel_array.fill(128) |
| 45 | + |
| 46 | + # Handle Photometric Interpretation |
| 47 | + photometric_interpretation = ds.get("PhotometricInterpretation", "MONOCHROME2") |
| 48 | + if photometric_interpretation == "MONOCHROME1": |
| 49 | + pixel_array = 255.0 - pixel_array |
| 50 | + |
| 51 | + # Convert to 8-bit unsigned integer |
| 52 | + image_8bit = pixel_array.astype(np.uint8) |
| 53 | + |
| 54 | + return Image.fromarray(image_8bit) |
| 55 | + |
| 56 | + |
| 57 | +if __name__ == '__main__': |
| 58 | + dcm_file = '../../example/images/image-00220.dcm' |
| 59 | + img = load_dcm_as_image(dcm_file) |
| 60 | + print(img) |
| 61 | + print(img.size) |
| 62 | + print(img.mode) |
| 63 | + img = np.array(img) |
| 64 | + print(img.shape) |
0 commit comments