diff --git a/README.md b/README.md index 3763842..5ad1e0a 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Inference model integration SDK - [Testing the inference server](#testing-the-inference-server) - [To send an inference request to the mock inference server](#to-send-an-inference-request-to-the-mock-inference-server) - [Running Unit Tests](#running-unit-tests) +- [Handling different photometric interpretations of input files](#handling-different-photometric-interpretations-of-input-files) - [Nifti image format support](#nifti-image-format-support) - [Secondary capture support](#secondary-capture-support) @@ -319,6 +320,25 @@ python3 -m unittest You must have Python 3.6+ installed. +## Handling different photometric interpretations of input files + +DICOM files can have multiple photometric interpretations (RGB, YBR, grayscale, etc.). +It is the responsibility of the model developer to handle all the possible interpretations supported for the input image types (CT, Xray, etc.). + +In `utils/image_conversion.py` there is a function that converts MONOCHROME1 (0 is white) image files to MONOCHROME2 (0 is black). +You can use it like this: + +```python +for dcm_file in dicom_instances: + dcm = pydicom.read_file(dcm_file) + dcm = convert_monochrome_1to2(dcm) + + # If you need to convert the pydicom object back to a BytesIO object: + # dcm_bytes = convert_dataset_to_bytes(dcm) +``` + +Other conversions might be necessary and might be added in the future. + ## Nifti image format support In the `utils/image_conversion.py` there are a few functions that can be helpful if your model accepts Nifti files as input or generates Nifti output files. diff --git a/inference-test-tool/utils.py b/inference-test-tool/utils.py index b743692..5371eca 100644 --- a/inference-test-tool/utils.py +++ b/inference-test-tool/utils.py @@ -85,6 +85,7 @@ def sort_images(images): np.dot(np.subtract(np.array(item2.position), np.array(pos)), direction))) def get_pixels(dicom_file): + """ Gets RGB pixels from a DICOM file. If they were 16 bit ints then they will be converted to uint8. """ pixels = dicom_file.pixel_array if dicom_file.PhotometricInterpretation == 'PALETTE COLOR': pixels = apply_color_lut(pixels, dicom_file) diff --git a/utils/image_conversion.py b/utils/image_conversion.py index 25627fa..cd4e00d 100644 --- a/utils/image_conversion.py +++ b/utils/image_conversion.py @@ -1,7 +1,8 @@ import numpy as np import SimpleITK as sitk -from pydicom import dcmread -from pydicom.filebase import DicomBytesIO +from pydicom import dcmread, dcmwrite +from pydicom.filebase import DicomBytesIO, DicomFileLike +from io import BytesIO ARTERYS_PROBABILITY_MASK='probability_mask' ARTERYS_BINARY='binary' @@ -62,3 +63,32 @@ def get_masks_from_nifti_file(nifti_file, data_type=ARTERYS_PROBABILITY_MASK, nu return np.array(output) return [arr] + + +def convert_monochrome_1to2(dcm): + """If the DICOM file `dcm` is in MONOCHROME1 then convert it to MONOCHROME2 """ + if dcm.PhotometricInterpretation == 'MONOCHROME1': + pixels = dcm.pixel_array + + # handle different dtypes + if pixels.dtype in [np.uint8, np.int8, np.uint16, np.int16]: + pixels = np.invert(pixels) + else: + raise RuntimeError("Non integer image data types currently not supported.") + + # Update original DICOM file + dcm.PixelData = pixels.tobytes() + dcm.PhotometricInterpretation = 'MONOCHROME2' + + return dcm + + +def convert_dataset_to_bytes(dataset): + """ Get a Bytes object from a DICOM dataset. + Adapted from https://pydicom.github.io/pydicom/dev/auto_examples/memory_dataset.html + """ + with BytesIO() as buffer: + memory_dataset = DicomFileLike(buffer) + dcmwrite(memory_dataset, dataset) + memory_dataset.seek(0) + return memory_dataset.read()