Skip to content

Conver metadata types to native and assign metadata to in-mem output image #186

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 43 additions & 6 deletions monai/deploy/operators/monai_seg_inference_operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,44 @@ def overlap(self, val: float):
raise ValueError("Overlap must be between 0 and 1.")
self._overlap = val

def _convert_dicom_metadata_datatype(self, metadata: Dict):
"""Converts metadata in pydicom types to the corresponding native types.

It is knwon that some values of the metadata are of the pydicom types, for images converted
from DICOM series. Need to use this function to convert the types with best effort and for
the few knowns metadata attributes, until the following issue is addressed:
https://github.com/Project-MONAI/monai-deploy-app-sdk/issues/185

Args:
metadata (Dict): The metadata for an Image object
"""

if not metadata:
return metadata

# Try to convert data type for the well knowned attributes. Add more as needed.
if metadata.get("series_instance_uid", None):
try:
metadata["series_instance_uid"] = str(metadata["series_instance_uid"])
except Exception:
pass
if metadata.get("row_pixel_spacing", None):
try:
metadata["row_pixel_spacing"] = float(metadata["row_pixel_spacing"])
except Exception:
pass
if metadata.get("col_pixel_spacing", None):
try:
metadata["col_pixel_spacing"] = float(metadata["col_pixel_spacing"])
except Exception:
pass

print("Converted Image object metadata:")
for k, v in metadata.items():
print(f"{k}: {v}, type {type(v)}")

return metadata

def compute(self, op_input: InputContext, op_output: OutputContext, context: ExecutionContext):
"""Infers with the input image and save the predicted image to output

Expand All @@ -145,11 +183,10 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
if not input_image:
raise ValueError("Input is None.")

img_name = "Img_in_context"
try:
img_name = input_image.metadata().get["series_instance_uid", img_name]
except Exception: # Best effort
pass
# Need to try to convert the data type of a few metadata attributes.
input_img_metadata = self._convert_dicom_metadata_datatype(input_image.metadata())
# Need to give a name to the image as in-mem Image obj has no name.
img_name = str(input_img_metadata.get("series_instance_uid", "Img_in_context"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this str() cast here since when the uid had already been converted to str?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, unnecessary, I left it there just for double safety and be explicit.


pre_transforms: Compose = self._pre_transform
post_transforms: Compose = self._post_transforms
Expand Down Expand Up @@ -196,7 +233,7 @@ def compute(self, op_input: InputContext, op_output: OutputContext, context: Exe
out_ndarray = np.swapaxes(out_ndarray, 2, 0).astype(np.uint8)
print(f"Output Seg image numpy array shaped: {out_ndarray.shape}")
print(f"Output Seg image pixel max value: {np.amax(out_ndarray)}")
out_image = Image(out_ndarray)
out_image = Image(out_ndarray, input_img_metadata)
op_output.set(out_image, "seg_image")
finally:
# Reset state on completing this method execution.
Expand Down