You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

86 lines
3.3 KiB

from typing import NamedTuple
import os
import torch
import numpy as np
import pydicom
from service.structs import PredictorInput, TagError, MetaTags
class InputImage(NamedTuple):
img: np.ndarray
ww: int
wc: int
uid: str
color_inversion: bool
def _get_ww_wc(study_ww, study_wc):
if type(study_ww) is pydicom.valuerep.DSfloat:
return int(study_ww), int(study_wc)
return int(study_ww[0]), int(study_wc[0])
def _is_color_inverted(study):
return study.PhotometricInterpretation == "MONOCHROME1"
def _prep_img(img_pack: InputImage) -> torch.Tensor:
img = img_pack.img.astype(np.float32)
lower_bound = img_pack.wc - 0.5 * img_pack.ww
upper_bound = img_pack.wc + 0.5 * img_pack.ww
img = np.clip(img, lower_bound, upper_bound)
img = ((img - lower_bound) / img_pack.ww) * 255
img = img.astype(np.uint8)
if img_pack.color_inversion:
img = 255 - img
return torch.from_numpy(img[None, ...])
def _check_required_tags(study: pydicom.FileDataset, pathology: str):
invalid_tags = []
if not (hasattr(study, "PhotometricInterpretation") and
study.PhotometricInterpretation in ("MONOCHROME1", "MONOCHROME2")):
invalid_tags.append("PhotometricInterpretation")
if pathology in ("shoulder", "wrist"):
if not (hasattr(study, "PixelSpacing") or
hasattr(study, "ImagerPixelSpacing")):
invalid_tags.append("PixelSpacing/ImagerPixelSpacing")
for tag in ("WindowWidth", "WindowCenter"):
if not hasattr(study, tag) or getattr(study, tag) == "":
invalid_tags.append(tag)
if len(invalid_tags) == 1:
raise TagError(f"DICOM тег {invalid_tags[0]} не заполнен, "\
"либо имеет некорректное значение")
elif len(invalid_tags) > 1:
raise TagError(f"DICOM теги {", ".join(invalid_tags)} не заполнены, "\
"либо имеют некорректные значения")
def _get_meta_tags(study: pydicom.FileDataset):
return MetaTags(study.StudyInstanceUID, study.SeriesInstanceUID,
getattr(study, "PatientID", None),
getattr(study, "AccessionNumber", None),
getattr(study, "IssuerOfPatientID", None),
getattr(study, "FillerOrderNumberImagingServiceRequest",
None))
def _get_px_size(study: pydicom.FileDataset):
if hasattr(study, "PixelSpacing"):
return study.PixelSpacing
if hasattr(study, "ImagerPixelSpacing"):
return study.ImagerPixelSpacing
return None, None
def prep_imgs(pathology: str, study_path: str) -> tuple[MetaTags, PredictorInput]:
instance = pydicom.dcmread(study_path, force=True)
_check_required_tags(instance, pathology)
meta_tags = _get_meta_tags(instance)
ww, wc = _get_ww_wc(instance.WindowWidth, instance.WindowCenter)
clr_inverted = _is_color_inverted(instance)
img = InputImage(instance.pixel_array, ww, wc, meta_tags.study_iuid, clr_inverted)
pred_input = PredictorInput(meta_tags.study_iuid, _prep_img(img),
getattr(instance, "ImageLaterality", None),
*_get_px_size(instance))
return meta_tags, pred_input