Created
December 18, 2020 12:10
-
-
Save cnd/45d1eafb41dd00571c830aca73537c5b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <typename TPixelType> | |
void AutoplanExporterDicom::doExport(mitk::Image* image, AutoplanExporter::ExportParams& exportParams, std::vector<boost::filesystem::path>& exportedFolders, const DoExportParams& params) | |
{ | |
std::vector<itk::MetaDataDictionary*> dicomMetaDataDictionaryArray = params.originalImage->GetMetaDataDictionaryArray(); | |
std::vector<itk::MetaDataDictionary*>* workDictionaryArray = &dicomMetaDataDictionaryArray; | |
std::unique_ptr<DicomAnonimizer> anonimizer = nullptr; | |
if (exportParams.m_Anonimize) { | |
anonimizer.reset(new DicomAnonimizer(dicomMetaDataDictionaryArray)); | |
workDictionaryArray = &anonimizer->getAnonimizedDictionaries(); | |
} | |
mitk::Image::Pointer exportedImage = image->Clone(); | |
int timeSteps = params.originalImage->GetTimeSteps(); | |
int numberOfComponents = params.originalImage->GetPixelType().GetNumberOfComponents(); | |
int size = (timeSteps > 1) ? timeSteps : numberOfComponents; | |
int arraySize = workDictionaryArray->size() / size; | |
auto itkImage = autoplan::castToItkImageReduce4D<TPixelType, 3>(exportedImage); | |
if (!itkImage) { | |
MITK_WARN << "Error transforming mitk image to itk image"; | |
return; | |
} | |
typedef itk::NumericSeriesFileNames OutputNamesGeneratorType; | |
typedef typename itk::ImageSeriesWriter<itk::Image<TPixelType, 3>, itk::Image<TPixelType, 2>> SeriesWriterType; | |
typename SeriesWriterType::Pointer seriesWriter = SeriesWriterType::New(); | |
seriesWriter->SetInput(itkImage); | |
AutoplanGDCMImageIO::Pointer gdcmIO = AutoplanGDCMImageIO::New(); | |
seriesWriter->SetImageIO(gdcmIO); | |
OutputNamesGeneratorType::Pointer outputNames = OutputNamesGeneratorType::New(); | |
outputNames->SetSeriesFormat(params.seriesFormat.c_str()); | |
int startIndex = arraySize * params.component + 1; | |
int endIndex = arraySize * (params.component + 1); | |
outputNames->SetStartIndex(startIndex); | |
outputNames->SetEndIndex(endIndex); | |
seriesWriter->SetFileNames(outputNames->GetFileNames()); | |
// Check if exported serie has serie uid | |
itk::MetaDataObject<std::string>::Pointer newSeriesUID = itk::MetaDataObject<std::string>::New(); | |
char uid[100]; | |
dcmGenerateUniqueIdentifier(uid, autoplan::AUTOPLAN_ORG_ROOT.c_str()); | |
newSeriesUID->SetMetaDataObjectValue(uid); | |
itk::MetaDataObject<std::string>::Pointer seriesDate, seriesTime; | |
itk::MetaDataObject<std::string>::Pointer encoding = itk::MetaDataObject<std::string>::New(); | |
encoding->SetMetaDataObjectValue("ISO_IR 192"); //< UTF-8 | |
if (!exportParams.m_Anonimize) { | |
seriesDate = itk::MetaDataObject<std::string>::New(); | |
seriesDate->SetMetaDataObjectValue(autoplan::getCurrentDateDICOMString()); | |
seriesTime = itk::MetaDataObject<std::string>::New(); | |
seriesTime->SetMetaDataObjectValue(autoplan::getCurrentTimeDICOMString()); | |
} | |
std::vector<itk::MetaDataDictionary*> timeStepDictionaryArray; | |
for (int j = startIndex - 1; j < endIndex; j++) { | |
timeStepDictionaryArray.push_back(workDictionaryArray->at(j)); | |
// Always set new series uid to never change the original series | |
timeStepDictionaryArray.back()->Set("0020|000e", newSeriesUID); | |
if (!exportParams.m_Anonimize) { // Set current date/time to series | |
static const char* dateTags[] = {"0008|0021", "0008|0023"}; | |
static const char* timeTags[] = {"0008|0031", "0008|0033"}; | |
for (auto tag: dateTags) { | |
timeStepDictionaryArray.back()->Set(tag, seriesDate); | |
} | |
for (auto tag: timeTags) { | |
timeStepDictionaryArray.back()->Set(tag, seriesTime); | |
} | |
timeStepDictionaryArray.back()->Set("0008|0005", encoding); | |
} | |
} | |
autoplan::DataStorageUtils::replaceMetadataByKey(timeStepDictionaryArray, "0028|1052", std::to_string(0)); | |
autoplan::DataStorageUtils::replaceMetadataByKey(timeStepDictionaryArray, "0028|1053", std::to_string(1)); | |
seriesWriter->SetMetaDataDictionaryArray(&timeStepDictionaryArray); | |
params.progressMonitor->addFilter(seriesWriter); | |
try { | |
seriesWriter->Update(); | |
} | |
catch (itk::ExceptionObject& excp) { | |
std::cerr << "Exception thrwon while writing the series " << std::endl; | |
std::cerr << excp << std::endl; | |
return; | |
} | |
params.progressMonitor->clear(); | |
} | |
template <typename TPixelType> | |
void AutoplanExporterDicom::doExportSegmentation(mitk::Image* parentImage | |
, AutoplanExporter::ExportParams& exportParams | |
, std::vector<boost::filesystem::path>& exportedFolders | |
, const DoExportSegmentationParams& params | |
) | |
{ | |
mitk::Image::Pointer resultImage(nullptr); | |
typedef typename itk::Image<TPixelType, 3> ImageType; | |
typename ImageType::Pointer resultItk = autoplan::ItkMitkImageConverter<ImageType>::mitkToItk(parentImage); | |
// TODO: possibly use constant values for different structures | |
int valuePixel = 1000; | |
int maskWidth = parentImage->GetLargestPossibleRegion().GetSize()[0]; | |
int maskHeight = parentImage->GetLargestPossibleRegion().GetSize()[1]; | |
int maskNumberSlice = parentImage->GetLargestPossibleRegion().GetSize()[2]; | |
for (mitk::Image* segmentationImage : params.notLungsSegmentations) { | |
int width = segmentationImage->GetLargestPossibleRegion().GetSize()[0]; | |
int height = segmentationImage->GetLargestPossibleRegion().GetSize()[1]; | |
int numberSlice = segmentationImage->GetLargestPossibleRegion().GetSize()[2]; | |
if (width <= maskWidth | |
&& height <= maskHeight | |
&& numberSlice <= maskNumberSlice) { | |
try | |
{ | |
typename ImageType::IndexType index; | |
typename ImageType::Pointer itkSeg = autoplan::ItkMitkImageConverter<ImageType>::mitkToItk(segmentationImage); | |
for (int k = 0; k < numberSlice; k++) { | |
index[2] = k; | |
for (int j = 0; j < height; j++) { | |
index[1] = j; | |
for (int i = 0; i < width; i++) { | |
index[0] = i; | |
TPixelType oldValue = itkSeg->GetPixel(index); | |
if (oldValue >= static_cast<TPixelType>(1)) { | |
resultItk->SetPixel(index, valuePixel); | |
} | |
} | |
} | |
} | |
valuePixel += 250; | |
} | |
catch (mitk::Exception& e) | |
{ | |
AUTOPLAN_ERROR << e.GetDescription(); | |
return; | |
} | |
} | |
} | |
resultImage = autoplan::ItkMitkImageConverter<ImageType>::itkToMitk(resultItk); | |
// if we have lungs segmentation use it as mask | |
if (params.lungsImage) { | |
if (params.lungsImage->GetLargestPossibleRegion().GetSize() == parentImage->GetLargestPossibleRegion().GetSize()) | |
{ | |
mitk::MaskImageFilter::Pointer maskFilter = mitk::MaskImageFilter::New(); | |
maskFilter->SetInput(parentImage); | |
maskFilter->SetMask(params.lungsImage); | |
maskFilter->OverrideOutsideValueOn(); | |
maskFilter->SetOutsideValue(parentImage->GetStatistics()->GetScalarValueMin()); | |
try | |
{ | |
maskFilter->Update(); | |
} | |
catch (itk::ExceptionObject& excpt) | |
{ | |
AUTOPLAN_ERROR << excpt.GetDescription(); | |
return; | |
} | |
resultImage = maskFilter->GetOutput(); | |
} | |
} | |
if (resultImage.IsNull()) { | |
return; | |
} | |
resultImage->SetGeometry(parentImage->GetGeometry()); | |
if (parentImage->GetTimeGeometry()) { | |
mitk::TimeGeometry::Pointer originalGeometry = parentImage->GetTimeGeometry()->Clone(); | |
resultImage->SetTimeGeometry(originalGeometry); | |
} | |
autoplan::DataStorageUtils::copyAndMergeImageProperties(parentImage, resultImage); | |
auto imageProp = parentImage->GetPropertyList(); | |
resultImage->SetPropertyList(imageProp); | |
resultImage->SetSpacing(parentImage->GetGeometry()->GetSpacing()); | |
resultImage->SetOrigin(parentImage->GetGeometry()->GetOrigin()); | |
if (params.lungsImage) { | |
autoplan::DataStorageUtils::replacePropertiesAndMetadataByKey(resultImage, "0008|0060", "SC"); | |
} | |
resultImage->CopyInformation(parentImage); | |
DoExportParams eparams; | |
eparams.component = params.component; | |
eparams.originalImage = resultImage; | |
eparams.seriesFormat = params.seriesFormat; | |
eparams.progressMonitor = params.progressMonitor; | |
doExport<TPixelType>(resultImage, exportParams, exportedFolders, eparams); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment