Here is the code. The slices, loaded in one-by-one all look good, but I still can’t load them as one 3D volume.
If I save it as nii.gz it looks good. Unfortunately it is a requierement to save it as DICOM series.
(I also tried it with switching modality to “OT” but it didn’t make a difference)
import SimpleITK as sitk
import os
import time
class SaveOutlinedPrediction():
def __init__(self,ctpath,predictionpath,savepath):
self.ctpath=ctpath
self.predictionpath=predictionpath
self.savepath=savepath
self.originalct=self.readDicomSerie()
self.resampleToOriginalFilter=self.resampleToOriginal(self.originalct)
def __call__(self):
predictionct=sitk.ReadImage(self.predictionpath)
rgboriginal = sitk.Cast(sitk.RescaleIntensity(self.originalct), sitk.sitkUInt8)
red = [255, 0, 0]
green = [0, 255, 0]
blue = [0, 0, 255]
resampledpred=self.resampleToOriginal(predictionct)
labelpred=sitk.Cast(resampledpred, sitk.sitkLabelUInt8)
contour_overlaid_image = sitk.LabelMapContourOverlay(labelpred,
rgboriginal,
opacity=1,
contourThickness=[4, 4, 4],
dilationRadius=[3, 3, 3],
colormap=red + green + blue,
)
self.writeDicom(contour_overlaid_image)
#self.writeNii(contour_overlaid_image)
def readDicomSerie(self):
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(self.ctpath)
reader.SetFileNames(dicom_names)
reader.MetaDataDictionaryArrayUpdateOn()
reader.LoadPrivateTagsOn()
image = reader.Execute()
return image
def resampleToOriginal(self,imageToResample):
origdirection=self.originalct.GetDirection()
origorigin=self.originalct.GetOrigin()
resample = sitk.ResampleImageFilter()
resample.SetInterpolator(sitk.sitkNearestNeighbor)
resample.SetOutputDirection(origdirection)
resample.SetOutputOrigin(origorigin)
resample.SetOutputSpacing(self.originalct.GetSpacing())
resample.SetSize(self.originalct.GetSize())
imageToResample.SetOrigin(origorigin)
imageToResample.SetDirection(origdirection)
resampled=resample.Execute(imageToResample)
return resampled
def writeNii(self,outlinedImage):
sitk.WriteImage(outlinedImage, self.savepath, useCompression = True,compressionLevel = 1)
def writeDicom(self,outlinedImage):
if not os.path.exists(self.savepath):
os.makedirs(self.savepath)
# Load original series for meta
series_IDs = sitk.ImageSeriesReader.GetGDCMSeriesIDs(self.ctpath)
series_file_names = sitk.ImageSeriesReader.GetGDCMSeriesFileNames(self.ctpath, series_IDs[0])
self.series_reader = sitk.ImageSeriesReader()
self.series_reader.SetFileNames(series_file_names)
self.series_reader.MetaDataDictionaryArrayUpdateOn()
self.series_reader.LoadPrivateTagsOn()
self.series_reader.Execute()
report_writer = sitk.ImageFileWriter()
report_writer.KeepOriginalImageUIDOn()
tags_to_copy = [
"0010|0010", # Patient Name
"0010|0020", # Patient ID def writeDICOMFromMeta(self):
"0020|0011", # Series Number
"0010|0030", # Patient Birth Date
"0020|000d", # Study Instance UID, for machine consumption
"0020|0010", # Study ID, for human consumption
"0008|0020", # Study Date
"0008|0030", # Study Time
"0008|0050", # Accession Number
"0008|1030", # Study Description
]
modification_time = time.strftime("%H%M%S")
modification_date = time.strftime("%Y%m%d")
direction = outlinedImage.GetDirection()
series_tag_values = [
(k, self.series_reader.GetMetaData(0, k))
for k in tags_to_copy
if self.series_reader.HasMetaDataKey(0, k)
] + [
("0008|0031", modification_time), # Series Time
("0008|0021", modification_date), # Series Date
("0008|0008", "DERIVED\\SECONDARY"), # Image Type
(
"0020|000e",
"1.2.826.0.1.3680043.2.1125."
+ modification_date
+ ".1"
+ modification_time,
),
# Series Instance UID
(
"0020|0037",
"\\".join(
map(
str,
(
direction[0],
direction[3],
direction[6],
# Image Orientation (Patient)
direction[1],
direction[4],
direction[7],
),
)
),
),
(
"0008|103e",
self.series_reader.GetMetaData(0, "0008|103e") + "_prediction",
),
] # Series Description
for i in range(outlinedImage.GetDepth()):
image_slice = outlinedImage[:, :, i]
for tag, value in series_tag_values:
image_slice.SetMetaData(tag, value)
image_slice.SetMetaData("0008|0012", time.strftime("%Y%m%d"))
image_slice.SetMetaData("0008|0013", time.strftime("%H%M%S"))
image_slice.SetMetaData("0028|0004", "RGB")
image_slice.SetMetaData("0028|0002", str(3))
image_slice.SetMetaData("0028|0100", str(8))
image_slice.SetMetaData("0028|0101", str(8))
image_slice.SetMetaData("0028|0102", str(7))
image_slice.SetMetaData("0028|0103", str(0))
image_slice.SetMetaData("0020|0013", str(i))
image_slice.SetMetaData("0008|0060", "CT")
image_slice.SetMetaData(
"0020|0032",
"\\".join(
map(str, outlinedImage.TransformIndexToPhysicalPoint((0, 0, i)))
),
)
report_writer.SetFileName(os.path.join(self.savepath, str(i) + ".dcm"))
report_writer.Execute(image_slice)
if __name__ == "__main__":
ctpath=r'/dicomfile/original/SE000002'
predpath=r'/dicomfile/lungsegm/SE000002.nii.gz'
savepath=r'/dicomfile/outline/SE000002'
SaveOutlinedPrediction(ctpath,predpath,savepath)()