diff --git a/Modules/TumorInvasionAnalysis/MiniApps/BasicDistanceMaps.cpp b/Modules/TumorInvasionAnalysis/MiniApps/BasicDistanceMaps.cpp index 8c124ed5a7..a3d86a48a3 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/BasicDistanceMaps.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/BasicDistanceMaps.cpp @@ -1,72 +1,72 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkCommandLineParser.h" #include "mitkITKImageImport.h" #include "mitkImage.h" #include #include "itkSignedDanielssonDistanceMapImageFilter.h" using namespace std; typedef itk::Image BinaryType; typedef itk::Image ResultType; int main(int argc, char *argv[]) { mitkCommandLineParser parser; parser.setTitle("Basic Distance Maps"); parser.setCategory("Features"); parser.setDescription("Creates Eucledian Distance Maps of a given ROI segmentation"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); - parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "(binary) seed file"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "distance map file name"); + parser.addArgument("input", "i", mitkCommandLineParser::Image, "(binary) seed file", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", "o", mitkCommandLineParser::File, "distance map file name", "", us::Any(), false, false, false, mitkCommandLineParser::Output); map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.size() == 0 || parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::string resultFile = us::any_cast(parsedArgs["output"]); std::string seedFile = us::any_cast(parsedArgs["input"]); mitk::Image::Pointer seedImage = mitk::IOUtil::Load(seedFile); BinaryType::Pointer itkSeed = BinaryType::New(); mitk::CastToItkImage(seedImage, itkSeed); itk::SignedDanielssonDistanceMapImageFilter::Pointer danielssonDistance = itk::SignedDanielssonDistanceMapImageFilter::New(); danielssonDistance->SetInput(itkSeed); danielssonDistance->SetUseImageSpacing(true); danielssonDistance->Update(); mitk::Image::Pointer result = mitk::Image::New(); mitk::GrabItkImageMemory(danielssonDistance->GetOutput(), result); mitk::IOUtil::Save(result, resultFile); return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/ConnectednessFeatureMaps.cpp b/Modules/TumorInvasionAnalysis/MiniApps/ConnectednessFeatureMaps.cpp index 70bd3fa7d6..15cc3de22e 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/ConnectednessFeatureMaps.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/ConnectednessFeatureMaps.cpp @@ -1,202 +1,202 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkCommandLineParser.h" #include "mitkITKImageImport.h" #include "mitkImage.h" #include #include #include #include // ITK #include "itkBinaryErodeImageFilter.h" #include "itkFlatStructuringElement.h" using namespace std; typedef itk::Image BinaryType; typedef itk::Image ResultType; typedef itk::Image, 3> ItkTensorImage; int main(int argc, char *argv[]) { // Setup CLI Module parsable interface mitkCommandLineParser parser; parser.setTitle("Connectedness Maps"); parser.setCategory("Features"); parser.setDescription("Computes connectedness maps"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); - parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "input file"); - parser.addArgument("seed", "s", mitkCommandLineParser::InputImage, "seed file"); - parser.addArgument("mask", "m", mitkCommandLineParser::InputImage, "mask file"); + parser.addArgument("input", "i", mitkCommandLineParser::Image, "input file", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("seed", "s", mitkCommandLineParser::Image, "seed file", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("mask", "m", mitkCommandLineParser::Image, "mask file", "", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument("mode", "t", mitkCommandLineParser::String, "Mode Feature | Vector | FeatureVector"); - parser.addArgument("vector", "v", mitkCommandLineParser::InputImage, "Tensor Image (.dti)"); + parser.addArgument("vector", "v", mitkCommandLineParser::Image, "Tensor Image (.dti)", "", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( - "confidence", "c", mitkCommandLineParser::InputImage, "confidence map (only when Tensor Images are used)"); - parser.addArgument("valueImage", "x", mitkCommandLineParser::InputImage, "image of values that are propagated"); + "confidence", "c", mitkCommandLineParser::Image, "confidence map (only when Tensor Images are used)", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("valueImage", "x", mitkCommandLineParser::Image, "image of values that are propagated", "", us::Any(), true, false, false, mitkCommandLineParser::Input); parser.addArgument("erodeSeed", "a", mitkCommandLineParser::Bool, "apply erosion of seed region"); parser.addArgument("rankFilter", "r", mitkCommandLineParser::Bool, "median filter for propagation"); - parser.addArgument("propMap", "p", mitkCommandLineParser::OutputFile, "[out] propagated map"); - parser.addArgument("distanceMap", "d", mitkCommandLineParser::OutputFile, "[out] connectedness map"); - parser.addArgument("euclidDistanceMap", "e", mitkCommandLineParser::OutputFile, "[out] euclid distance map"); + parser.addArgument("propMap", "p", mitkCommandLineParser::File, "[out] propagated map", "", us::Any(), false, false, false, mitkCommandLineParser::Output); + parser.addArgument("distanceMap", "d", mitkCommandLineParser::File, "[out] connectedness map", "", us::Any(), false, false, false, mitkCommandLineParser::Output); + parser.addArgument("euclidDistanceMap", "e", mitkCommandLineParser::File, "[out] euclid distance map", "", us::Any(), false, false, false, mitkCommandLineParser::Output); // Parse input parameters map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.size() == 0 || parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } bool useRank = false; bool applyErosion = false; bool useValueImage = false; if (parsedArgs.count("rankFilter") || parsedArgs.count("r")) useRank = true; if (parsedArgs.count("valueImage") || parsedArgs.count("x")) useValueImage = true; if (parsedArgs.count("erodeSeed") || parsedArgs.count("a")) applyErosion = true; std::string inputFile = us::any_cast(parsedArgs["input"]); std::string propMap = us::any_cast(parsedArgs["propMap"]); std::string conMap = us::any_cast(parsedArgs["distanceMap"]); std::string tensImageFile = us::any_cast(parsedArgs["vector"]); std::string maskFile = us::any_cast(parsedArgs["mask"]); std::string mode = us::any_cast(parsedArgs["mode"]); std::string seedFile = us::any_cast(parsedArgs["seed"]); std::string confFile = us::any_cast(parsedArgs["confidence"]); std::string euclidFile = us::any_cast(parsedArgs["euclidDistanceMap"]); std::string valueImageFile = ""; if (useValueImage) valueImageFile = us::any_cast(parsedArgs["valueImage"]); // Read-in image data mitk::Image::Pointer tmpImage; mitk::Image::Pointer inputImage = mitk::IOUtil::Load(inputFile); mitk::Image::Pointer maskImage = mitk::IOUtil::Load(maskFile); mitk::Image::Pointer seedImage = mitk::IOUtil::Load(seedFile); mitk::Image::Pointer valueImage; if (useValueImage) valueImage = mitk::IOUtil::Load(valueImageFile); mitk::Image::Pointer confImage; if (mode == "Vector" || mode == "FeatureVector") { MITK_INFO << "Load Tensor/Confidence"; tmpImage = mitk::IOUtil::Load(tensImageFile); confImage = mitk::IOUtil::Load(confFile); } mitk::TensorImage *diffusionImage = static_cast(tmpImage.GetPointer()); // Convert all input data to ITK BinaryType::Pointer itkSeed = BinaryType::New(); BinaryType::Pointer itkMask = BinaryType::New(); ResultType::Pointer itkImage = ResultType::New(); ItkTensorImage::Pointer itkTensor = ItkTensorImage::New(); ResultType::Pointer itkWeight = ResultType::New(); ResultType::Pointer itkValueImage = ResultType::New(); mitk::CastToItkImage(inputImage, itkImage); mitk::CastToItkImage(maskImage, itkMask); mitk::CastToItkImage(seedImage, itkSeed); if (useValueImage) mitk::CastToItkImage(valueImage, itkValueImage); if (applyErosion) { typedef itk::FlatStructuringElement<3> StructuringElementType; StructuringElementType::RadiusType elementRadius; elementRadius.Fill(2); elementRadius[2] = 0; StructuringElementType structuringElement = StructuringElementType::Box(elementRadius); typedef itk::BinaryErodeImageFilter BinaryErodeImageFilterType; BinaryErodeImageFilterType::Pointer erodeFilter = BinaryErodeImageFilterType::New(); erodeFilter->SetInput(itkSeed); erodeFilter->SetKernel(structuringElement); erodeFilter->SetForegroundValue(1); erodeFilter->Update(); itkSeed = erodeFilter->GetOutput(); } if (mode == "Vector" || mode == "FeatureVector") { mitk::CastToItkImage(diffusionImage, itkTensor); mitk::CastToItkImage(confImage, itkWeight); } // Setup filter itk::ConnectednessFilter::Pointer filter = itk::ConnectednessFilter::New(); filter->SetInputImage(itkImage); filter->SetInputSeed(itkSeed); filter->SetInputMask(itkMask); if (mode == "Vector") { filter->SetInputVectorField(itkTensor); filter->SetInputVectorFieldConfidenceMap(itkWeight); filter->SetMode(itk::ConnectednessFilter::VectorAgreement); } else if (mode == "FeatureVector") { filter->SetInputVectorField(itkTensor); filter->SetInputVectorFieldConfidenceMap(itkWeight); filter->SetMode(itk::ConnectednessFilter::FeatureVectorAgreement); } else filter->SetMode(itk::ConnectednessFilter::FeatureSimilarity); if (useValueImage) filter->SetPropagationImage(itkValueImage); filter->SetApplyRankFilter(useRank); filter->Update(); // Grab output and write results mitk::Image::Pointer result = mitk::Image::New(); mitk::GrabItkImageMemory(filter->GetOutput(), result); mitk::IOUtil::Save(result, propMap); mitk::Image::Pointer distance = mitk::Image::New(); mitk::GrabItkImageMemory(filter->GetDistanceImage().GetPointer(), distance); mitk::IOUtil::Save(distance, conMap); mitk::Image::Pointer euclidDistance = mitk::Image::New(); mitk::GrabItkImageMemory(filter->GetEuclideanDistanceImage().GetPointer(), euclidDistance); mitk::IOUtil::Save(euclidDistance, euclidFile); return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/HistogramAdaption.cpp b/Modules/TumorInvasionAnalysis/MiniApps/HistogramAdaption.cpp index 18ce5faada..ed8341829c 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/HistogramAdaption.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/HistogramAdaption.cpp @@ -1,104 +1,104 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkImageRegionIterator.h" #include "mitkIOUtil.h" #include "mitkImageCast.h" #include #include using namespace std; typedef itk::Image SeedImage; typedef itk::Image FeatureImage; typedef itk::ImageRegionIterator SeedIteratorType; typedef itk::ImageRegionIterator FeatureIteratorType; int main(int argc, char *argv[]) { mitkCommandLineParser parser; parser.setTitle("Contrast Adaption"); parser.setCategory("Preprocessing Tools"); parser.setDescription("Stretches or pushes image intensities above a given threshold"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); // Add command line argument names - parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "input image"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "output image"); + parser.addArgument("input", "i", mitkCommandLineParser::Image, "input image", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", "o", mitkCommandLineParser::File, "output image", "", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.addArgument("cutOff", "c", mitkCommandLineParser::Float, "value at which different slope is to be applied"); parser.addArgument( "slope", "s", mitkCommandLineParser::Float, "slope to be applied (total delta to max value starting from cutOff)"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size() == 0) return EXIT_FAILURE; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::string outFile = us::any_cast(parsedArgs["output"]); mitk::Image::Pointer inputFile = mitk::IOUtil::Load(us::any_cast(parsedArgs["input"])); float cutOff = us::any_cast(parsedArgs["cutOff"]); float slope = us::any_cast(parsedArgs["slope"]); FeatureImage::Pointer itkInputImage = FeatureImage::New(); mitk::CastToItkImage(inputFile, itkInputImage); double max = -99999; itk::ImageRegionIterator inputIt(itkInputImage, itkInputImage->GetLargestPossibleRegion()); while (!inputIt.IsAtEnd()) { if (inputIt.Get() > max) max = inputIt.Get(); ++inputIt; } inputIt.GoToBegin(); // Mapping while (!inputIt.IsAtEnd()) { if (inputIt.Get() > cutOff) { inputIt.Set(cutOff + slope * (inputIt.Get() - cutOff) / (max - cutOff)); } ++inputIt; } mitk::Image::Pointer mitkResult = mitk::Image::New(); // !! CastToItk behaves very differently depending on the original data type // if the target type is the same as the original, only a pointer to the data is set // and an additional GrabItkImageMemory will cause a segfault when the image is destroyed // GrabItkImageMemory - is not necessary in this case since we worked on the original data // See Bug 17538. if (inputFile->GetPixelType().GetComponentTypeAsString() != "double") mitkResult = mitk::GrabItkImageMemory(itkInputImage); else mitkResult = inputFile; mitk::IOUtil::Save(mitkResult, outFile); return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/MriNormalization.cpp b/Modules/TumorInvasionAnalysis/MiniApps/MriNormalization.cpp index 4c4fb51438..10abd75e35 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/MriNormalization.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/MriNormalization.cpp @@ -1,122 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkImageRegionIterator.h" #include "mitkCommandLineParser.h" #include "mitkIOUtil.h" #include "mitkImageCast.h" #include using namespace std; typedef itk::Image SeedImage; typedef itk::Image FeatureImage; typedef itk::ImageRegionIterator SeedIteratorType; typedef itk::ImageRegionIterator FeatureIteratorType; int main(int argc, char *argv[]) { mitkCommandLineParser parser; parser.setTitle("Mri Normalization"); parser.setCategory("Preprocessing Tools"); parser.setDescription( "Normalizes an MRI volume between medians of two given masks (e.g. ventricles and brain matter)"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); // Add command line argument names - parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "input image"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "output image"); + parser.addArgument("input", "i", mitkCommandLineParser::Image, "input image", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", "o", mitkCommandLineParser::File, "output image", "", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.addArgument( - "maxMask", "m", mitkCommandLineParser::InputImage, "mask of which median is set as maximal value (1)"); + "maxMask", "m", mitkCommandLineParser::Image, "mask of which median is set as maximal value (1)", "", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( - "minMask", "l", mitkCommandLineParser::InputImage, "mask of which median is set as minimal value (0)"); + "minMask", "l", mitkCommandLineParser::Image, "mask of which median is set as minimal value (0)", "", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( - "excludeMask", "e", mitkCommandLineParser::InputImage, "region which is exluded from the other two"); + "excludeMask", "e", mitkCommandLineParser::Image, "region which is exluded from the other two", "", us::Any(), false, false, false, mitkCommandLineParser::Input); map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.size() == 0 || parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::string outFile = us::any_cast(parsedArgs["output"]); mitk::Image::Pointer inputFile = mitk::IOUtil::Load(us::any_cast(parsedArgs["input"])); mitk::Image::Pointer maxMask = mitk::IOUtil::Load(us::any_cast(parsedArgs["maxMask"])); mitk::Image::Pointer minMask = mitk::IOUtil::Load(us::any_cast(parsedArgs["minMask"])); mitk::Image::Pointer excludeMask = mitk::IOUtil::Load(us::any_cast(parsedArgs["excludeMask"])); SeedImage::Pointer itkMaxImage = SeedImage::New(); SeedImage::Pointer itkMinImage = SeedImage::New(); SeedImage::Pointer itkExcludeImage = SeedImage::New(); FeatureImage::Pointer itkInputImage = FeatureImage::New(); mitk::CastToItkImage(inputFile, itkInputImage); mitk::CastToItkImage(maxMask, itkMaxImage); mitk::CastToItkImage(minMask, itkMinImage); mitk::CastToItkImage(excludeMask, itkExcludeImage); std::vector medianMin; std::vector medianMax; itk::ImageRegionIterator inputIt(itkInputImage, itkInputImage->GetLargestPossibleRegion()); itk::ImageRegionIterator excludeIt(itkExcludeImage, itkExcludeImage->GetLargestPossibleRegion()); itk::ImageRegionIterator minIt(itkMinImage, itkMinImage->GetLargestPossibleRegion()); itk::ImageRegionIterator maxIt(itkMaxImage, itkMaxImage->GetLargestPossibleRegion()); while (!inputIt.IsAtEnd()) { if (excludeIt.Get() == 0) { if (minIt.Get() != 0) medianMin.push_back(inputIt.Get()); if (maxIt.Get() != 0) medianMax.push_back(inputIt.Get()); } ++inputIt; ++excludeIt; ++minIt; ++maxIt; } std::sort(medianMax.begin(), medianMax.end()); std::sort(medianMin.begin(), medianMin.end()); mitk::ScalarType minVal = medianMin.at(medianMin.size() / 2); mitk::ScalarType maxVal = medianMax.at(medianMax.size() / 2); inputIt.GoToBegin(); // Create mapping while (!inputIt.IsAtEnd()) { inputIt.Set(1.0 * (inputIt.Get() - minVal) / (maxVal - minVal)); ++inputIt; } mitk::Image::Pointer mitkResult = mitk::Image::New(); mitkResult = mitk::GrabItkImageMemory(itkInputImage); mitk::IOUtil::Save(mitkResult, outFile); return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/MriOtsuNormalization.cpp b/Modules/TumorInvasionAnalysis/MiniApps/MriOtsuNormalization.cpp index 284cd5df10..1da7d1ce17 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/MriOtsuNormalization.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/MriOtsuNormalization.cpp @@ -1,124 +1,124 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkImageRegionIterator.h" #include "mitkCommandLineParser.h" #include "mitkIOUtil.h" #include "mitkImageCast.h" #include // ITK #include using namespace std; typedef itk::Image SeedImage; typedef itk::Image FeatureImage; typedef itk::ImageRegionIterator SeedIteratorType; typedef itk::ImageRegionIterator FeatureIteratorType; int main(int argc, char *argv[]) { mitkCommandLineParser parser; parser.setTitle("Mri Normalization"); parser.setCategory("Preprocessing Tools"); parser.setDescription("Normalizes an MRI volume based on regions determined by Otsu."); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); // Add command line argument names - parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "input image", "input image"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "output image", "output image"); + parser.addArgument("input", "i", mitkCommandLineParser::Image, "input image", "input image", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", "o", mitkCommandLineParser::File, "output image", "output image", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.addArgument("bins", "b", mitkCommandLineParser::Int, "number of regions (bins)", "number of regions (bins)"); parser.addArgument( "minBin", "l", mitkCommandLineParser::Int, "bin of which median is set to 0", "bin of which median is set to 0"); parser.addArgument( "maxBin", "h", mitkCommandLineParser::Int, "bin of which median is set to 1", "bin of which median is set to 1"); map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.size() == 0 || parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::string outFile = us::any_cast(parsedArgs["output"]); mitk::Image::Pointer inputFile = mitk::IOUtil::Load(us::any_cast(parsedArgs["input"])); int numberOfThresholds = us::any_cast(parsedArgs["bins"]); int minBin = us::any_cast(parsedArgs["minBin"]); int maxBin = us::any_cast(parsedArgs["maxBin"]); FeatureImage::Pointer itkInputImage = FeatureImage::New(); mitk::CastToItkImage(inputFile, itkInputImage); typedef itk::OtsuMultipleThresholdsImageFilter FilterType; FilterType::Pointer otsuFilter = FilterType::New(); otsuFilter->SetInput(itkInputImage); otsuFilter->SetNumberOfThresholds(numberOfThresholds - 1); otsuFilter->Update(); FeatureImage::Pointer itkLabelImage = otsuFilter->GetOutput(); std::vector medianMin; std::vector medianMax; itk::ImageRegionIterator inputIt(itkInputImage, itkInputImage->GetLargestPossibleRegion()); itk::ImageRegionIterator labelIt(itkLabelImage, itkLabelImage->GetLargestPossibleRegion()); while (!inputIt.IsAtEnd()) { if (labelIt.Get() == minBin) { medianMin.push_back(inputIt.Get()); } else if (labelIt.Get() == maxBin) { medianMax.push_back(inputIt.Get()); } ++inputIt; ++labelIt; } std::sort(medianMax.begin(), medianMax.end()); std::sort(medianMin.begin(), medianMin.end()); mitk::ScalarType minVal = medianMin.at(medianMin.size() / 2); mitk::ScalarType maxVal = medianMax.at(medianMax.size() / 2); inputIt.GoToBegin(); // labelIt.GoToBegin(); // Create mapping while (!inputIt.IsAtEnd()) { inputIt.Set(1.0 * (inputIt.Get() - minVal) / (maxVal - minVal)); // inputIt.Set(labelIt.Get()); ++inputIt; //++labelIt; } mitk::Image::Pointer mitkResult = mitk::Image::New(); mitkResult = mitk::GrabItkImageMemory(itkInputImage); mitk::IOUtil::Save(mitkResult, outFile); return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/TumorInvasionAnalysisTool.cpp b/Modules/TumorInvasionAnalysis/MiniApps/TumorInvasionAnalysisTool.cpp index e666ba8694..f87b47b1f9 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/TumorInvasionAnalysisTool.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/TumorInvasionAnalysisTool.cpp @@ -1,350 +1,350 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // MITK - DataCollection #include #include #include #include #include "mitkDataCollectionImageIterator.h" #include #include // CTK #include "mitkCommandLineParser.h" // ITK #include using namespace std; int main(int argc, char *argv[]) { // Setup CLI Module parsable interface mitkCommandLineParser parser; parser.setTitle("Tumor Invasion Analysis"); parser.setCategory("Tumor Analysis"); parser.setDescription("Learns and predicts Invasion behavior"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); // Add command line argument names parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Show options"); - parser.addArgument("loadFile", "l", mitkCommandLineParser::InputFile, "DataCollection File"); + parser.addArgument("loadFile", "l", mitkCommandLineParser::File, "DataCollection File", "", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( "colIds", "c", mitkCommandLineParser::String, "Patient Identifiers from DataCollection used for training"); parser.addArgument( "testId", "t", mitkCommandLineParser::String, "Patient Identifier from DataCollection used for testing"); parser.addArgument("features", "b", mitkCommandLineParser::String, "Features"); parser.addArgument("stats", "s", mitkCommandLineParser::String, "Output file for stats"); parser.addArgument("ratio", "q", mitkCommandLineParser::Float, "ratio of tumor to healthy"); parser.addArgument("treeDepth", "d", mitkCommandLineParser::Int, "limits tree depth"); parser.addArgument("forestSize", "f", mitkCommandLineParser::Int, "number of trees"); parser.addArgument("samplingMode", "m", mitkCommandLineParser::Int, "mode of sample selection"); parser.addArgument("configName", "n", mitkCommandLineParser::String, "human readable name for configuration"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "output folder for results"); - parser.addArgument("forest", "t", mitkCommandLineParser::OutputFile, "store trained forest to file"); + parser.addArgument("output", "o", mitkCommandLineParser::Directory, "output folder for results", "", us::Any(), false, false, false, mitkCommandLineParser::Output); + parser.addArgument("forest", "t", mitkCommandLineParser::File, "store trained forest to file", "", us::Any(), false, false, false, mitkCommandLineParser::Output); map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.size() == 0) return EXIT_SUCCESS; if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } // Default values float ratio = 1.0; bool useStatsFile = false; unsigned int forestSize = 250; unsigned int treeDepth = 0; unsigned int samplingMode = 1; std::string configName = ""; std::string outputFolder = ""; std::string forestFile = ""; std::vector features; std::vector trainingIds; std::vector testingIds; std::vector loadIds; // features + masks needed for training and evaluation std::string outputFile; std::string xmlFile; std::ofstream experimentFS; // Parse input parameters { if (parsedArgs.count("colIds") || parsedArgs.count("c")) { std::istringstream ss(us::any_cast(parsedArgs["colIds"])); std::string token; while (std::getline(ss, token, ',')) trainingIds.push_back(token); } if (parsedArgs.count("output") || parsedArgs.count("o")) { outputFolder = us::any_cast(parsedArgs["output"]); } if (parsedArgs.count("configName") || parsedArgs.count("n")) { configName = us::any_cast(parsedArgs["configName"]); } if (parsedArgs.count("features") || parsedArgs.count("b")) { std::istringstream ss(us::any_cast(parsedArgs["features"])); std::string token; while (std::getline(ss, token, ',')) features.push_back(token); } if (parsedArgs.count("treeDepth") || parsedArgs.count("d")) { treeDepth = us::any_cast(parsedArgs["treeDepth"]); } if (parsedArgs.count("ratio") || parsedArgs.count("q")) { ratio = us::any_cast(parsedArgs["ratio"]); } if (parsedArgs.count("forestSize") || parsedArgs.count("f")) { forestSize = us::any_cast(parsedArgs["forestSize"]); } if (parsedArgs.count("samplingMode") || parsedArgs.count("m")) { samplingMode = us::any_cast(parsedArgs["samplingMode"]); } if (parsedArgs.count("stats") || parsedArgs.count("s")) { useStatsFile = true; experimentFS.open(us::any_cast(parsedArgs["stats"]).c_str(), std::ios_base::app); } if (parsedArgs.count("forest") || parsedArgs.count("t")) { forestFile = us::any_cast(parsedArgs["stats"]); } if (parsedArgs.count("testId") || parsedArgs.count("t")) { std::istringstream ss(us::any_cast(parsedArgs["testId"])); std::string token; while (std::getline(ss, token, ',')) testingIds.push_back(token); } for (unsigned int i = 0; i < features.size(); i++) { loadIds.push_back(features.at(i)); } loadIds.push_back("GTV"); loadIds.push_back("BRAINMASK"); loadIds.push_back("TARGET"); if (parsedArgs.count("stats") || parsedArgs.count("s")) { outputFile = us::any_cast(parsedArgs["stats"]); } if (parsedArgs.count("loadFile") || parsedArgs.count("l")) { xmlFile = us::any_cast(parsedArgs["loadFile"]); } else { MITK_ERROR << parser.helpText(); return EXIT_FAILURE; } } mitk::DataCollection::Pointer trainCollection; mitk::DataCollection::Pointer testCollection; { mitk::DiffusionCollectionReader colReader; // Load only relevant images colReader.SetDataItemNames(loadIds); colReader.AddSubColIds(testingIds); testCollection = colReader.LoadCollection(xmlFile); colReader.ClearDataElementIds(); colReader.ClearSubColIds(); colReader.SetDataItemNames(loadIds); colReader.AddSubColIds(trainingIds); trainCollection = colReader.LoadCollection(xmlFile); } std::cout << "Setup Training" << std::endl; mitk::TumorInvasionClassification classifier; classifier.SetClassRatio(ratio); classifier.SetTrainMargin(7, 1); classifier.SamplesWeightingActivated(true); classifier.SelectTrainingSamples(trainCollection, samplingMode); // Learning stage std::cout << "Start Training" << std::endl; classifier.LearnProgressionFeatures(trainCollection, features, forestSize, treeDepth); if (forestFile != "") classifier.SaveRandomForest(forestFile); std::cout << "Start Predict" << std::endl; classifier.PredictInvasion(testCollection, features); if (false && outputFolder != "") { std::cout << "Saving files to " << outputFolder << std::endl; mitk::DiffusionCollectionWriter::ExportCollectionToFolder(trainCollection, "/tmp/dumple"); } classifier.SanitizeResults(testCollection); { mitk::DataCollectionImageIterator gtvIt(testCollection, "GTV"); mitk::DataCollectionImageIterator result(testCollection, "RESULTOPEN"); while (!gtvIt.IsAtEnd()) { if (gtvIt.GetVoxel() != 0) { result.SetVoxel(2); } result++; gtvIt++; } } mitk::CollectionStatistic stat2; mitk::ProgressionValueToIndexMapper progressionValueToIndexMapper; mitk::BinaryValueToIndexMapper binaryValueToIndexMapper; stat2.SetCollection(testCollection); stat2.SetClassCount(2); stat2.SetGoldName("TARGET"); stat2.SetTestName("RESULTOPEN"); stat2.SetMaskName("BRAINMASK"); stat2.SetGroundTruthValueToIndexMapper(&binaryValueToIndexMapper); stat2.SetTestValueToIndexMapper(&progressionValueToIndexMapper); stat2.Update(); stat2.ComputeRMSD(); // FIXME: DICE value available after calling Print method std::ostringstream out2; stat2.Print(out2, std::cout, true); std::cout << std::endl << std::endl << out2.str() << std::endl; // Exclude GTV from Statistics by removing it from brain mask, // insert GTV as tumor region, since it is known before, in the result. { mitk::DataCollectionImageIterator gtvIt(testCollection, "GTV"); mitk::DataCollectionImageIterator brainMaskIter(testCollection, "BRAINMASK"); mitk::DataCollectionImageIterator result(testCollection, "RESULTOPEN"); while (!gtvIt.IsAtEnd()) { if (gtvIt.GetVoxel() != 0) { brainMaskIter.SetVoxel(0); result.SetVoxel(2); } result++; gtvIt++; brainMaskIter++; } } mitk::CollectionStatistic stat; stat.SetCollection(testCollection); stat.SetClassCount(2); stat.SetGoldName("TARGET"); stat.SetTestName("RESULTOPEN"); stat.SetMaskName("BRAINMASK"); stat.SetGroundTruthValueToIndexMapper(&binaryValueToIndexMapper); stat.SetTestValueToIndexMapper(&progressionValueToIndexMapper); stat.Update(); stat.ComputeRMSD(); // WARN: DICE value computed within Print method, so values are only available // after // calling Print() std::ostringstream out; stat.Print(out, std::cout, true); std::cout << std::endl << std::endl << out.str() << std::endl; // Statistics for original GTV excluded (Dice,Sensitivity) and for Gold // Standard vs prediction (RMSE) mitk::StatisticData statData = stat.GetStatisticData(1).at(0); mitk::StatisticData statData2 = stat2.GetStatisticData(1).at(0); std::cout << "Writing Stats to file" << std::endl; // one line output if (useStatsFile) { experimentFS << "Tree_Depth " << treeDepth << ','; experimentFS << "Forest_Size " << forestSize << ','; experimentFS << "Tumor/healthy_ratio " << ratio << ','; experimentFS << "Sample_Selection " << samplingMode << ','; experimentFS << "Trainined_on: " << ','; for (unsigned int i = 0; i < trainingIds.size(); i++) { experimentFS << trainingIds.at(i) << "/"; } experimentFS << ','; experimentFS << "Tested_on: " << ','; for (unsigned int i = 0; i < testingIds.size(); i++) { experimentFS << testingIds.at(i) << "/"; } experimentFS << ','; experimentFS << "Features_used: " << ','; if (configName == "") { for (unsigned int i = 0; i < features.size(); i++) { experimentFS << features.at(i) << "/"; } } else experimentFS << configName; experimentFS << ','; experimentFS << "---- STATS ---" << ','; experimentFS << " Sensitivity " << statData.m_Sensitivity << ','; experimentFS << " DICE " << statData.m_DICE << ','; experimentFS << " RMSE " << statData2.m_RMSD << ','; experimentFS << std::endl; } if (outputFolder != "") { std::cout << "Saving files to " << outputFolder << std::endl; mitk::DiffusionCollectionWriter::ExportCollectionToFolder(testCollection, outputFolder); } return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/TumorProgressionMapping.cpp b/Modules/TumorInvasionAnalysis/MiniApps/TumorProgressionMapping.cpp index 148979fefc..f5998afe20 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/TumorProgressionMapping.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/TumorProgressionMapping.cpp @@ -1,554 +1,554 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // MITK #include #include #include #include #include #include #include #include // ITK #include "itkImageDuplicator.h" #include "itkPermuteAxesImageFilter.h" #include "itkTileImageFilter.h" #include #include #include #include #include #include #include // VTK #include #include #include #include #include // MITK #include #include "itkRescaleIntensityImageFilter.h" #include using namespace std; typedef unsigned short PixelType; typedef double InputPixelType; typedef itk::Image, 2> RGB2DImage; typedef itk::RGBPixel RGBPixelType; typedef std::vector FileList; typedef std::vector ImageList; /// Create list of all files in provided folder ending with same postfix static FileList CreateFileList(std::string folder, std::string postfix) { itk::Directory::Pointer dir = itk::Directory::New(); FileList fileList; if (dir->Load(folder.c_str())) { int n = dir->GetNumberOfFiles(); for (int r = 0; r < n; r++) { std::string filename = dir->GetFile(r); if (filename == "." || filename == "..") continue; filename = folder + filename; if (!itksys::SystemTools::FileExists(filename.c_str())) continue; if (postfix.compare(filename.substr(filename.length() - postfix.length())) == 0) fileList.push_back(filename); } } std::sort(fileList.begin(), fileList.end()); return fileList; } class mitkProgressionVisualization { public: mitkProgressionVisualization() {} /** * @brief ConvertToRGBImage converts a gray image to RGB by filling all three channels with the gray intensity * @param grayImage * @return */ mitk::Image::Pointer ConvertToRGBImage(mitk::Image::Pointer grayImage) { mitk::Image::Pointer rgbImage = mitk::Image::New(); unsigned int *dim = grayImage->GetDimensions(); rgbImage->Initialize(mitk::MakePixelType(), 3, dim); rgbImage->SetGeometry(grayImage->GetGeometry()); itk::Image::Pointer itkGrayImage = itk::Image::New(); mitk::CastToItkImage(grayImage, itkGrayImage); mitk::ImagePixelWriteAccessor writeAcc(rgbImage); typedef itk::RescaleIntensityImageFilter, itk::Image> RescaleFilterType; RescaleFilterType::Pointer rescaleFilter = RescaleFilterType::New(); rescaleFilter->SetInput(itkGrayImage); rescaleFilter->SetOutputMinimum(0); rescaleFilter->SetOutputMaximum(255 * 255); rescaleFilter->Update(); itk::Index<3> idx; RGBPixelType value; // Fill rgb image with gray values for (idx[2] = 0; (unsigned int)idx[2] < dim[2]; idx[2]++) { for (idx[1] = 0; (unsigned int)idx[1] < dim[1]; idx[1]++) { for (idx[0] = 0; (unsigned int)idx[0] < dim[0]; idx[0]++) { value.Fill(rescaleFilter->GetOutput()->GetPixel(idx)); writeAcc.SetPixelByIndex(idx, value); } } } return rgbImage; } RGB2DImage::Pointer TextAsImage(std::string text) { vtkSmartPointer textImage = vtkSmartPointer::New(); vtkSmartPointer freetype = vtkSmartPointer::New(); vtkSmartPointer prop = vtkSmartPointer::New(); float color[3] = {1, 1, 1}; float opacity = 1.0; prop->SetColor(color[0], color[1], color[2]); prop->SetFontSize(40); prop->SetOpacity(opacity); textImage->AllocateScalars(VTK_UNSIGNED_SHORT, 3); freetype->RenderString(prop, vtkUnicodeString::from_utf8(text.c_str()), 72, textImage); textImage->Modified(); int *extent = textImage->GetExtent(); RGB2DImage::Pointer itkImage = RGB2DImage::New(); RGB2DImage::IndexType start; start.Fill(0); RGB2DImage::SizeType size; size[0] = extent[1]; size[1] = extent[3]; size[2] = 0; RGB2DImage::RegionType region(start, size); itkImage->SetRegions(region); itkImage->Allocate(); RGB2DImage::IndexType idx; for (unsigned int y = 0; y < size[1]; y++) { for (unsigned int x = 0; x < size[0]; x++) { PixelType *pixel = static_cast(textImage->GetScalarPointer(x, y, 0)); RGBPixelType values; values.Fill(0); values[0] = pixel[1]; values[1] = pixel[1]; values[2] = pixel[1]; idx.Fill(0); idx[0] = x; idx[1] = y; itkImage->SetPixel(idx, values); } } typedef itk::PermuteAxesImageFilter PermuteAxesImageFilterType; itk::FixedArray order; order[0] = 1; order[1] = 0; PermuteAxesImageFilterType::Pointer permuteAxesFilter = PermuteAxesImageFilterType::New(); permuteAxesFilter->SetInput(itkImage); permuteAxesFilter->SetOrder(order); permuteAxesFilter->Update(); RGB2DImage::Pointer itkResultImage = RGB2DImage::New(); itkResultImage->SetRegions(region); itkResultImage->Allocate(); itkResultImage->Graft(permuteAxesFilter->GetOutput()); return itkResultImage; } /** * @brief AddColouredOverlay - Overlays the rgbImage with an coloured overlay * * For all positions in overlayImage not zero, its value is multiplied the the colour value and added * to the rgbImage. * * @param rgbImage - input rgbImage to which the coloured overlay is added * @param overlayImage * @param color */ void AddColouredOverlay(mitk::Image::Pointer rgbImage, mitk::Image::Pointer overlayImage, mitk::Color color) { unsigned int *dim = rgbImage->GetDimensions(); itk::Image::Pointer itkOverlayImage = itk::Image::New(); mitk::CastToItkImage(overlayImage.GetPointer(), itkOverlayImage); mitk::ImagePixelWriteAccessor writeAcc(rgbImage); itk::Index<3> idx; itk::RGBPixel value; unsigned short overlayVal = 0; // Fill rgb image with gray values for (idx[2] = 0; (unsigned int)idx[2] < dim[2]; idx[2]++) { for (idx[1] = 0; (unsigned int)idx[1] < dim[1]; idx[1]++) { for (idx[0] = 0; (unsigned int)idx[0] < dim[0]; idx[0]++) { overlayVal = 255 * itkOverlayImage->GetPixel(idx); value = writeAcc.GetPixelByIndex(idx); value[0] = std::min((int)(value[0] + overlayVal * color[0]), 254 * 255); value[1] = std::min((int)(value[1] + overlayVal * color[1]), 254 * 255); value[2] = std::min((int)(value[2] + overlayVal * color[2]), 254 * 255); writeAcc.SetPixelByIndex(idx, value); } } } } itk::Image, 2>::Pointer ExtractSlice( itk::Image, 3>::Pointer itkImage, unsigned int sliceNo) { typedef itk::Image InputImageType; typedef itk::Image OutputImageType; int dim[3]; dim[0] = itkImage->GetLargestPossibleRegion().GetSize()[0]; dim[1] = itkImage->GetLargestPossibleRegion().GetSize()[1]; dim[2] = itkImage->GetLargestPossibleRegion().GetSize()[2]; itk::Index<3> desiredStart; itk::Size<3> desiredSize; // case AXIAL: // 3rd dimension fixed desiredStart.Fill(0); desiredStart[2] = sliceNo; desiredSize.Fill(0); desiredSize[0] = dim[0]; desiredSize[1] = dim[1]; desiredSize[2] = 0; itk::ImageRegion<3> desiredRegion(desiredStart, desiredSize); // Extract slice itk::ExtractImageFilter::Pointer extractSlice = itk::ExtractImageFilter::New(); extractSlice->SetInput(itkImage); extractSlice->SetExtractionRegion(desiredRegion); extractSlice->SetDirectionCollapseToIdentity(); extractSlice->Update(); return extractSlice->GetOutput(); } }; static std::string GetName(std::string fileName, std::string suffix = "_T2.nrrd") { fileName = itksys::SystemTools::GetFilenameName(fileName); return fileName.substr(0, fileName.length() - suffix.length() - 11); // 10 = date length } static std::string GetDate(std::string fileName, std::string suffix = "_T2.nrrd") { fileName = itksys::SystemTools::GetFilenameName(fileName); fileName = fileName.substr(fileName.length() - suffix.length() - 10, 10); // 10 = date length return fileName; } static ImageList LoadPreprocessedFiles(FileList files) { ImageList images; for (unsigned int i = 0; i < files.size(); ++i) { images.push_back(mitk::IOUtil::Load(files.at(i))); } return images; } int main(int argc, char *argv[]) { // Parse Command-Line Arguments mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); parser.setTitle("Tumor Progression Mapping"); parser.setCategory("Preprocessing Tools"); parser.setContributor("MBI"); parser.setDescription("Convert a set of co-registered and resampled follow-up images into a 2D png overview (and " "optionally in a 4D NRRD Volume).\nNaming convecntion of files is " "IDENTIFIER_YYYY-MM-DD_MODALITY.nrrd"); parser.setArgumentPrefix("--", "-"); - parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input folder containing all follow ups"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output file (PNG)"); + parser.addArgument("input", "i", mitkCommandLineParser::Directory, "Input folder containing all follow ups", "", us::Any(), false, false, false, mitkCommandLineParser::Input); + parser.addArgument("output", "o", mitkCommandLineParser::File, "Output file (PNG)", "", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.addArgument("blanked", "b", mitkCommandLineParser::Bool, "Only Display Morphology"); parser.addArgument("morphology", "m", mitkCommandLineParser::String, "Morphology postfix.", "_T2.nrrd"); parser.addArgument( "segmentation", "s", mitkCommandLineParser::String, "Segmentation postfix. Default: _GTV.nrrd", "_GTV.nrrd"); - parser.addArgument("4dVolume", "v", mitkCommandLineParser::OutputFile, "Filepath to merged 4d NRRD Volume."); + parser.addArgument("4dVolume", "v", mitkCommandLineParser::File, "Filepath to merged 4d NRRD Volume.", "", us::Any(), false, false, false, mitkCommandLineParser::Output); parser.addArgument( "skip", "k", mitkCommandLineParser::Int, "Number of slices to be skipped from top and from button (Default 0)"); parser.addArgument( "interval", "n", mitkCommandLineParser::Int, "1 - for all slices, 2 - every second, 3 - every third ..."); parser.addArgument("opacity", "c", mitkCommandLineParser::Float, "Opacity of overlay [0,1] invisible -> visible"); map parsedArgs = parser.parseArguments(argc, argv); if (parsedArgs.size() == 0) return EXIT_SUCCESS; // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } std::string outputFile; std::string inputFolder; if (parsedArgs.count("input") || parsedArgs.count("i")) { inputFolder = us::any_cast(parsedArgs["input"]) + "/"; } if (parsedArgs.count("output") || parsedArgs.count("o")) { outputFile = us::any_cast(parsedArgs["output"]); } int skip = 0; int interval = 1; float opacity = .3; if (parsedArgs.count("skip") || parsedArgs.count("k")) { skip = us::any_cast(parsedArgs["skip"]); } if (parsedArgs.count("interval") || parsedArgs.count("n")) { interval = us::any_cast(parsedArgs["interval"]); } if (parsedArgs.count("opacity") || parsedArgs.count("c")) { opacity = us::any_cast(parsedArgs["opacity"]); } FileList morphFiles; FileList segFiles; std::string refPattern; std::string segPattern; if (parsedArgs.count("morphology") || parsedArgs.count("m")) { refPattern = us::any_cast(parsedArgs["morphology"]); } else return EXIT_FAILURE; if (parsedArgs.count("segmentation") || parsedArgs.count("s")) { segPattern = us::any_cast(parsedArgs["segmentation"]); } bool blank = false; if (parsedArgs.count("blanked") || parsedArgs.count("b")) { blank = true; } /// END Parsing CL Options typedef itk::Image OutputImageType; typedef itk::Image InputImageType; mitkProgressionVisualization progressVis; morphFiles = CreateFileList(inputFolder, refPattern); segFiles = CreateFileList(inputFolder, segPattern); ImageList morphImages = LoadPreprocessedFiles(morphFiles); ImageList segImages; if (segFiles.size() > 0 && blank == false) segImages = LoadPreprocessedFiles(segFiles); mitk::Image::Pointer rgbImage; // define color for overlay image mitk::Color color; color.Fill(0); color[0] = 200 * opacity; color[1] = 0; // Set up itk time image filter to contain 0..N-1 images itk::TileImageFilter::Pointer tileFilter = itk::TileImageFilter::New(); itk::FixedArray layout; unsigned int noOfTimeSteps = morphImages.size(); layout[0] = noOfTimeSteps; layout[1] = 0; // automatic number of neccessary rows tileFilter->SetLayout(layout); // Get Reference image (all images are expected to have exact same dimensions!) std::string fileName = morphFiles.at(0); mitk::Image *referenceImg = morphImages.at(0); mitk::Image::Pointer merged4D; std::string volumeFile; if (parsedArgs.count("4dVolume") || parsedArgs.count("v")) { volumeFile = us::any_cast(parsedArgs["4dVolume"]); if (volumeFile != "") { unsigned int *dims = new unsigned int[4]; dims[0] = referenceImg->GetDimensions()[0]; dims[1] = referenceImg->GetDimensions()[1]; dims[2] = referenceImg->GetDimensions()[2]; dims[3] = morphImages.size(); merged4D = mitk::Image::New(); merged4D->Initialize(referenceImg->GetPixelType(), 4, dims); merged4D->GetTimeGeometry()->Expand(noOfTimeSteps); } } unsigned int *dim = referenceImg->GetDimensions(); unsigned int sliceMaxAxial = dim[2]; // Now iterate over all data sets, extract overlay and add it to reference image mitk::Image *morphImage; mitk::Image *segmentationImage = nullptr; for (unsigned int i = 0; i < noOfTimeSteps; i++) { MITK_INFO << "File : " << i << " of /" << noOfTimeSteps; int currentSliceNo = 0; // Retrieve images of current time step fileName = morphFiles.at(i); morphImage = morphImages.at(i); // Create 4D Volume image if (volumeFile != "") { mitk::ImagePixelReadAccessor readAc(morphImage); merged4D->GetGeometry(i)->SetSpacing(referenceImg->GetGeometry()->GetSpacing()); merged4D->GetGeometry(i)->SetOrigin(referenceImg->GetGeometry()->GetOrigin()); merged4D->GetGeometry(i)->SetIndexToWorldTransform(referenceImg->GetGeometry()->GetIndexToWorldTransform()); merged4D->SetVolume(readAc.GetData(), i); } MITK_INFO << "-- Convert to RGB"; rgbImage = progressVis.ConvertToRGBImage(morphImage); // Add current seg in red color.Fill(0); color[0] = 200 * opacity; if (!blank) { segmentationImage = segImages.at(i); if (segmentationImage != nullptr) { MITK_INFO << "-- Add Overlay"; progressVis.AddColouredOverlay(rgbImage, segmentationImage, color); } } // Add Segmentation of next time step in red if (i == 0) { MITK_INFO << "Skipping retro view in first time step"; } else { color.Fill(0); // Add previous in green color[1] = 200 * opacity; if (!blank) { mitk::Image *nextSeg = segImages.at(i - 1); MITK_INFO << "-- Add Overlay of next Step"; progressVis.AddColouredOverlay(rgbImage, nextSeg, color); } } // Now save all slices from overlay in output folder MITK_INFO << "-- Extract Slices"; for (int slice = sliceMaxAxial - skip - 1; slice > skip; slice -= interval) // sliceMaxAxial/40.0f)) { InputImageType::Pointer itkImage = InputImageType::New(); InputImageType::Pointer itkImage2; mitk::CastToItkImage(rgbImage, itkImage); typedef itk::ImageDuplicator DuplicatorType; DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(itkImage); duplicator->Update(); itkImage2 = duplicator->GetOutput(); itk::Image::Pointer extractedSlice = itk::Image::New(); extractedSlice->Graft(progressVis.ExtractSlice(itkImage2, slice)); tileFilter->SetInput(((currentSliceNo + 1) * (noOfTimeSteps) + i), extractedSlice); tileFilter->SetInput(i, progressVis.TextAsImage(GetDate(fileName))); currentSliceNo++; } } MITK_INFO << "Tile Filter Update"; tileFilter->Update(); // Write the output image typedef itk::ImageFileWriter WriterType; WriterType::Pointer writer = WriterType::New(); writer->SetInput(tileFilter->GetOutput()); std::string patientName; patientName = GetName(fileName); if (blank) writer->SetFileName(outputFile); else writer->SetFileName(outputFile); writer->Update(); if (volumeFile != "") mitk::IOUtil::Save(merged4D, volumeFile); return EXIT_SUCCESS; } diff --git a/Modules/TumorInvasionAnalysis/MiniApps/TumorResponseEvaluationTool.cpp b/Modules/TumorInvasionAnalysis/MiniApps/TumorResponseEvaluationTool.cpp index 6cb72895cf..911384c128 100644 --- a/Modules/TumorInvasionAnalysis/MiniApps/TumorResponseEvaluationTool.cpp +++ b/Modules/TumorInvasionAnalysis/MiniApps/TumorResponseEvaluationTool.cpp @@ -1,266 +1,266 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // MITK - DataCollection #include #include #include #include #include "mitkDataCollectionImageIterator.h" #include #include // CTK #include "mitkCommandLineParser.h" // ITK #include using namespace std; int main(int argc, char *argv[]) { // Setup CLI Module parsable interface mitkCommandLineParser parser; parser.setTitle("Tumor Invasion Analysis"); parser.setCategory("Tumor Analysis"); parser.setDescription("Learns and predicts Invasion behavior"); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); // Add command line argument names parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Show options"); - parser.addArgument("loadFile", "l", mitkCommandLineParser::InputFile, "DataCollection File"); + parser.addArgument("loadFile", "l", mitkCommandLineParser::File, "DataCollection File", "", us::Any(), false, false, false, mitkCommandLineParser::Input); parser.addArgument( "colIds", "c", mitkCommandLineParser::String, "Patient Identifiers from DataCollection used for training"); parser.addArgument( "testId", "t", mitkCommandLineParser::String, "Patient Identifier from DataCollection used for testing"); parser.addArgument("features", "b", mitkCommandLineParser::String, "Features"); parser.addArgument("stats", "s", mitkCommandLineParser::String, "Output file for stats"); parser.addArgument("ratio", "q", mitkCommandLineParser::Float, "ratio of tumor to healthy"); parser.addArgument("treeDepth", "d", mitkCommandLineParser::Int, "limits tree depth"); parser.addArgument("forestSize", "f", mitkCommandLineParser::Int, "number of trees"); parser.addArgument("configName", "n", mitkCommandLineParser::String, "human readable name for configuration"); - parser.addArgument("output", "o", mitkCommandLineParser::OutputDirectory, "output folder for results"); - parser.addArgument("forest", "t", mitkCommandLineParser::OutputFile, "store trained forest to file"); + parser.addArgument("output", "o", mitkCommandLineParser::Directory, "output folder for results", "", us::Any(), false, false, false, mitkCommandLineParser::Output); + parser.addArgument("forest", "t", mitkCommandLineParser::File, "store trained forest to file", "", us::Any(), false, false, false, mitkCommandLineParser::Output); map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.size() == 0) return EXIT_SUCCESS; if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } // Default values float ratio = 1.0; bool useStatsFile = false; unsigned int forestSize = 250; unsigned int treeDepth = 0; std::string configName = ""; std::string outputFolder = ""; std::string forestFile = ""; std::vector features; std::vector trainingIds; std::vector testingIds; std::vector loadIds; // features + masks needed for training and evaluation std::string outputFile; std::string xmlFile; std::ofstream experimentFS; // Parse input parameters { if (parsedArgs.count("colIds") || parsedArgs.count("c")) { std::istringstream ss(us::any_cast(parsedArgs["colIds"])); std::string token; while (std::getline(ss, token, ',')) trainingIds.push_back(token); } if (parsedArgs.count("output") || parsedArgs.count("o")) { outputFolder = us::any_cast(parsedArgs["output"]); } if (parsedArgs.count("configName") || parsedArgs.count("n")) { configName = us::any_cast(parsedArgs["configName"]); } if (parsedArgs.count("features") || parsedArgs.count("b")) { std::istringstream ss(us::any_cast(parsedArgs["features"])); std::string token; while (std::getline(ss, token, ',')) features.push_back(token); } if (parsedArgs.count("treeDepth") || parsedArgs.count("d")) { treeDepth = us::any_cast(parsedArgs["treeDepth"]); } if (parsedArgs.count("ratio") || parsedArgs.count("q")) { ratio = us::any_cast(parsedArgs["ratio"]); } if (parsedArgs.count("forestSize") || parsedArgs.count("f")) { forestSize = us::any_cast(parsedArgs["forestSize"]); } if (parsedArgs.count("stats") || parsedArgs.count("s")) { useStatsFile = true; experimentFS.open(us::any_cast(parsedArgs["stats"]).c_str(), std::ios_base::app); } if (parsedArgs.count("forest") || parsedArgs.count("t")) { forestFile = us::any_cast(parsedArgs["stats"]); } if (parsedArgs.count("testId") || parsedArgs.count("t")) { std::istringstream ss(us::any_cast(parsedArgs["testId"])); std::string token; while (std::getline(ss, token, ',')) testingIds.push_back(token); } for (unsigned int i = 0; i < features.size(); i++) { loadIds.push_back(features.at(i)); } loadIds.push_back("GTV"); loadIds.push_back("BRAINMASK"); loadIds.push_back("TARGET"); if (parsedArgs.count("stats") || parsedArgs.count("s")) { outputFile = us::any_cast(parsedArgs["stats"]); } if (parsedArgs.count("loadFile") || parsedArgs.count("l")) { xmlFile = us::any_cast(parsedArgs["loadFile"]); } else { MITK_ERROR << parser.helpText(); return EXIT_FAILURE; } } mitk::DataCollection::Pointer trainCollection; mitk::DataCollection::Pointer testCollection; { mitk::DiffusionCollectionReader colReader; // Load only relevant images colReader.SetDataItemNames(loadIds); colReader.AddSubColIds(testingIds); testCollection = colReader.LoadCollection(xmlFile); colReader.ClearDataElementIds(); colReader.ClearSubColIds(); colReader.SetDataItemNames(loadIds); colReader.AddSubColIds(trainingIds); trainCollection = colReader.LoadCollection(xmlFile); } std::cout << "Setup Training" << std::endl; mitk::TumorInvasionClassification classifier; classifier.SetClassRatio(ratio); classifier.SamplesWeightingActivated(true); classifier.PrepareResponseSamples(trainCollection); // Learning stage std::cout << "Start Training" << std::endl; classifier.LearnProgressionFeatures(trainCollection, features, forestSize, treeDepth); if (forestFile != "") classifier.SaveRandomForest(forestFile); std::cout << "Start Predict" << std::endl; classifier.PredictInvasion(testCollection, features); if (outputFolder != "") { std::cout << "Saving files to " << outputFolder << std::endl; mitk::DiffusionCollectionWriter::ExportCollectionToFolder(trainCollection, "/tmp/dumple"); } /* prepare target values to match training values: * 0 - excluded (e.g. out of brainmask) * 1 - no involvement (healthy all the time) * 2 - formerly healthy, now tumor (rezivid) * 3 - formerly tumor, now necroses (responsive) */ { mitk::DataCollectionImageIterator gtvIter(testCollection, "GTV"); mitk::DataCollectionImageIterator targetIt(testCollection, "TARGET"); while (!gtvIter.IsAtEnd()) { if (targetIt.GetVoxel() == 0 && gtvIter.GetVoxel() == 0) targetIt.SetVoxel(1); if (targetIt.GetVoxel() == 0 && gtvIter.GetVoxel() == 1) targetIt.SetVoxel(3); if (targetIt.GetVoxel() == 1 && gtvIter.GetVoxel() == 0) targetIt.SetVoxel(2); targetIt++; gtvIter++; } } mitk::CollectionStatistic stats; mitk::ProgressionValueToIndexMapper progressionValueToIndexMapper; mitk::BinaryValueToIndexMapper binaryValueToIndexMapper; stats.SetCollection(testCollection); stats.SetClassCount(4); stats.SetGoldName("TARGET"); stats.SetTestName("RESULT"); stats.SetMaskName("BRAINMASK"); stats.SetGroundTruthValueToIndexMapper(&binaryValueToIndexMapper); stats.SetTestValueToIndexMapper(&binaryValueToIndexMapper); stats.Update(); std::ostringstream outStr; stats.Print(outStr, std::cout, true); std::cout << std::endl << std::endl << outStr.str() << std::endl; if (useStatsFile) std::cout << "dummy" << std::endl; if (outputFolder != "") { std::cout << "Saving files to " << outputFolder << std::endl; mitk::DiffusionCollectionWriter::ExportCollectionToFolder(testCollection, outputFolder); } return EXIT_SUCCESS; }