diff --git a/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp b/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp index e057ba0fb0..3da1fcf4d7 100644 --- a/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp +++ b/Modules/Classification/CLMiniApps/CLGlobalImageFeatures.cpp @@ -1,603 +1,660 @@ /*=================================================================== 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. ===================================================================*/ #ifndef mitkCLPolyToNrrd_cpp #define mitkCLPolyToNrrd_cpp #include "time.h" #include #include #include #include "mitkCommandLineParser.h" #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include "itkNearestNeighborInterpolateImageFunction.h" #include "itkResampleImageFilter.h" #include #include #include "QmitkRegisterClasses.h" #include "QmitkRenderWindow.h" #include "vtkRenderLargeImage.h" #include "vtkPNGWriter.h" typedef itk::Image< double, 3 > FloatImageType; typedef itk::Image< unsigned char, 3 > MaskImageType; template void ResampleImage(itk::Image* itkImage, float resolution, mitk::Image::Pointer& newImage) { typedef itk::Image ImageType; typedef itk::ResampleImageFilter ResampleFilterType; typename ResampleFilterType::Pointer resampler = ResampleFilterType::New(); auto spacing = itkImage->GetSpacing(); auto size = itkImage->GetLargestPossibleRegion().GetSize(); for (int i = 0; i < VImageDimension; ++i) { size[i] = size[i] / (1.0*resolution)*(1.0*spacing[i])+1.0; } spacing.Fill(resolution); resampler->SetInput(itkImage); resampler->SetSize(size); resampler->SetOutputSpacing(spacing); resampler->SetOutputOrigin(itkImage->GetOrigin()); resampler->SetOutputDirection(itkImage->GetDirection()); resampler->Update(); newImage->InitializeByItk(resampler->GetOutput()); mitk::GrabItkImageMemory(resampler->GetOutput(), newImage); } template static void CreateNoNaNMask(itk::Image* itkValue, mitk::Image::Pointer mask, mitk::Image::Pointer& newMask) { typedef itk::Image< TPixel, VImageDimension> LFloatImageType; typedef itk::Image< unsigned char, VImageDimension> LMaskImageType; typename LMaskImageType::Pointer itkMask = LMaskImageType::New(); mitk::CastToItkImage(mask, itkMask); typedef itk::ImageDuplicator< LMaskImageType > DuplicatorType; typename DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(itkMask); duplicator->Update(); auto tmpMask = duplicator->GetOutput(); itk::ImageRegionIterator mask1Iter(itkMask, itkMask->GetLargestPossibleRegion()); itk::ImageRegionIterator mask2Iter(tmpMask, tmpMask->GetLargestPossibleRegion()); itk::ImageRegionIterator imageIter(itkValue, itkValue->GetLargestPossibleRegion()); while (!mask1Iter.IsAtEnd()) { mask2Iter.Set(0); if (mask1Iter.Value() > 0) { // Is not NaN if (imageIter.Value() == imageIter.Value()) { mask2Iter.Set(1); } } ++mask1Iter; ++mask2Iter; ++imageIter; } newMask->InitializeByItk(tmpMask); mitk::GrabItkImageMemory(tmpMask, newMask); } template static void ResampleMask(itk::Image* itkMoving, mitk::Image::Pointer ref, mitk::Image::Pointer& newMask) { typedef itk::Image< TPixel, VImageDimension> LMaskImageType; typedef itk::NearestNeighborInterpolateImageFunction< LMaskImageType> NearestNeighborInterpolateImageFunctionType; typedef itk::ResampleImageFilter ResampleFilterType; typename NearestNeighborInterpolateImageFunctionType::Pointer nn_interpolator = NearestNeighborInterpolateImageFunctionType::New(); typename LMaskImageType::Pointer itkRef = LMaskImageType::New(); mitk::CastToItkImage(ref, itkRef); typename ResampleFilterType::Pointer resampler = ResampleFilterType::New(); resampler->SetInput(itkMoving); resampler->SetReferenceImage(itkRef); resampler->UseReferenceImageOn(); resampler->SetInterpolator(nn_interpolator); resampler->Update(); newMask->InitializeByItk(resampler->GetOutput()); mitk::GrabItkImageMemory(resampler->GetOutput(), newMask); } static void ExtractSlicesFromImages(mitk::Image::Pointer image, mitk::Image::Pointer mask, mitk::Image::Pointer maskNoNaN, int direction, std::vector &imageVector, std::vector &maskVector, std::vector &maskNoNaNVector) { typedef itk::Image< double, 2 > FloatImage2DType; typedef itk::Image< unsigned char, 2 > MaskImage2DType; FloatImageType::Pointer itkFloat = FloatImageType::New(); MaskImageType::Pointer itkMask = MaskImageType::New(); MaskImageType::Pointer itkMaskNoNaN = MaskImageType::New(); mitk::CastToItkImage(mask, itkMask); mitk::CastToItkImage(maskNoNaN, itkMaskNoNaN); mitk::CastToItkImage(image, itkFloat); int idxA, idxB, idxC; switch (direction) { case 0: idxA = 1; idxB = 2; idxC = 0; break; case 1: idxA = 0; idxB = 2; idxC = 1; break; case 2: idxA = 0; idxB = 1; idxC = 2; break; default: idxA = 1; idxB = 2; idxC = 0; break; } auto imageSize = image->GetLargestPossibleRegion().GetSize(); FloatImageType::IndexType index3D; FloatImage2DType::IndexType index2D; FloatImage2DType::SpacingType spacing2D; spacing2D[0] = itkFloat->GetSpacing()[idxA]; spacing2D[1] = itkFloat->GetSpacing()[idxB]; for (int i = 0; i < imageSize[idxC]; ++i) { FloatImage2DType::RegionType region; FloatImage2DType::IndexType start; FloatImage2DType::SizeType size; start[0] = 0; start[1] = 0; size[0] = imageSize[idxA]; size[1] = imageSize[idxB]; region.SetIndex(start); region.SetSize(size); FloatImage2DType::Pointer image2D = FloatImage2DType::New(); image2D->SetRegions(region); image2D->Allocate(); MaskImage2DType::Pointer mask2D = MaskImage2DType::New(); mask2D->SetRegions(region); mask2D->Allocate(); MaskImage2DType::Pointer masnNoNaN2D = MaskImage2DType::New(); masnNoNaN2D->SetRegions(region); masnNoNaN2D->Allocate(); for (int a = 0; a < imageSize[idxA]; ++a) { for (int b = 0; b < imageSize[idxB]; ++b) { index3D[idxA] = a; index3D[idxB] = b; index3D[idxC] = i; index2D[0] = a; index2D[1] = b; image2D->SetPixel(index2D, itkFloat->GetPixel(index3D)); mask2D->SetPixel(index2D, itkMask->GetPixel(index3D)); masnNoNaN2D->SetPixel(index2D, itkMaskNoNaN->GetPixel(index3D)); } } image2D->SetSpacing(spacing2D); mask2D->SetSpacing(spacing2D); masnNoNaN2D->SetSpacing(spacing2D); mitk::Image::Pointer tmpFloatImage = mitk::Image::New(); tmpFloatImage->InitializeByItk(image2D.GetPointer()); mitk::GrabItkImageMemory(image2D, tmpFloatImage); mitk::Image::Pointer tmpMaskImage = mitk::Image::New(); tmpMaskImage->InitializeByItk(mask2D.GetPointer()); mitk::GrabItkImageMemory(mask2D, tmpMaskImage); mitk::Image::Pointer tmpMaskNoNaNImage = mitk::Image::New(); tmpMaskNoNaNImage->InitializeByItk(masnNoNaN2D.GetPointer()); mitk::GrabItkImageMemory(masnNoNaN2D, tmpMaskNoNaNImage); imageVector.push_back(tmpFloatImage); maskVector.push_back(tmpMaskImage); maskNoNaNVector.push_back(tmpMaskNoNaNImage); } } static void SaveSliceOrImageAsPNG(mitk::Image::Pointer image, mitk::Image::Pointer mask, std::string path, int index) { // Create a Standalone Datastorage for the single purpose of saving screenshots.. mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); QmitkRenderWindow renderWindow; renderWindow.GetRenderer()->SetDataStorage(ds); auto nodeI = mitk::DataNode::New(); nodeI->SetData(image); auto nodeM = mitk::DataNode::New(); nodeM->SetData(mask); ds->Add(nodeI); ds->Add(nodeM); mitk::TimeGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews(geo); mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); unsigned int numberOfSteps = 1; if (sliceNaviController) { numberOfSteps = sliceNaviController->GetSlice()->GetSteps(); sliceNaviController->GetSlice()->SetPos(0); } renderWindow.show(); renderWindow.resize(256, 256); for (unsigned int currentStep = 0; currentStep < numberOfSteps; ++currentStep) { if (sliceNaviController) { sliceNaviController->GetSlice()->SetPos(currentStep); } renderWindow.GetRenderer()->PrepareRender(); vtkRenderWindow* renderWindow2 = renderWindow.GetVtkRenderWindow(); mitk::BaseRenderer* baserenderer = mitk::BaseRenderer::GetInstance(renderWindow2); auto vtkRender = baserenderer->GetVtkRenderer(); vtkRender->GetRenderWindow()->WaitForCompletion(); vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New(); magnifier->SetInput(vtkRender); magnifier->SetMagnification(3.0); std::stringstream ss; ss << path << "_Idx-" << index << "_Step-"<> tmpImageName; auto fileWriter = vtkPNGWriter::New(); fileWriter->SetInputConnection(magnifier->GetOutputPort()); fileWriter->SetFileName(tmpImageName.c_str()); fileWriter->Write(); fileWriter->Delete(); } } int main(int argc, char* argv[]) { mitk::GIFFirstOrderStatistics::Pointer firstOrderCalculator = mitk::GIFFirstOrderStatistics::New(); mitk::GIFVolumetricStatistics::Pointer volCalculator = mitk::GIFVolumetricStatistics::New(); mitk::GIFCooccurenceMatrix::Pointer coocCalculator = mitk::GIFCooccurenceMatrix::New(); mitk::GIFCooccurenceMatrix2::Pointer cooc2Calculator = mitk::GIFCooccurenceMatrix2::New(); mitk::GIFNeighbouringGreyLevelDependenceFeature::Pointer ngldCalculator = mitk::GIFNeighbouringGreyLevelDependenceFeature::New(); mitk::GIFGrayLevelRunLength::Pointer rlCalculator = mitk::GIFGrayLevelRunLength::New(); + mitk::GIFGreyLevelSizeZone::Pointer glszCalculator = mitk::GIFGreyLevelSizeZone::New(); std::vector features; features.push_back(firstOrderCalculator.GetPointer()); features.push_back(volCalculator.GetPointer()); features.push_back(coocCalculator.GetPointer()); features.push_back(cooc2Calculator.GetPointer()); features.push_back(ngldCalculator.GetPointer()); features.push_back(rlCalculator.GetPointer()); - + features.push_back(glszCalculator.GetPointer()); mitkCommandLineParser parser; parser.setArgumentPrefix("--", "-"); mitk::cl::GlobalImageFeaturesParameter param; param.AddParameter(parser); parser.addArgument("--","-", mitkCommandLineParser::String, "---", "---", us::Any(),true); for (auto cFeature : features) { cFeature->AddArguments(parser); } parser.addArgument("--", "-", mitkCommandLineParser::String, "---", "---", us::Any(), true); parser.addArgument("description","d",mitkCommandLineParser::String,"Text","Description that is added to the output",us::Any()); parser.addArgument("direction", "dir", mitkCommandLineParser::String, "Int", "Allows to specify the direction for Cooc and RL. 0: All directions, 1: Only single direction (Test purpose), 2,3,4... Without dimension 0,1,2... ", us::Any()); parser.addArgument("slice-wise", "slice", mitkCommandLineParser::String, "Int", "Allows to specify if the image is processed slice-wise (number giving direction) ", us::Any()); parser.addArgument("output-mode", "omode", mitkCommandLineParser::Int, "Int", "Defines if the results of an image / slice are written in a single row (0 , default) or column (1)."); // Miniapp Infos parser.setCategory("Classification Tools"); parser.setTitle("Global Image Feature calculator"); parser.setDescription("Calculates different global statistics for a given segmentation / image combination"); parser.setContributor("MBI"); std::map parsedArgs = parser.parseArguments(argc, argv); param.ParseParameter(parsedArgs); if (parsedArgs.size()==0) { return EXIT_FAILURE; } if ( parsedArgs.count("help") || parsedArgs.count("h")) { return EXIT_SUCCESS; } bool savePNGofSlices = true; std::string folderForPNGOfSlices = "E:\\tmp\\bonekamp\\fig\\"; - std::string version = "Version: 1.18"; + std::string version = "Version: 1.19"; MITK_INFO << version; std::ofstream log; if (param.useLogfile) { log.open(param.logfilePath, std::ios::app); log << version; log << "Image: " << param.imagePath; log << "Mask: " << param.maskPath; } mitk::Image::Pointer image; mitk::Image::Pointer mask; mitk::Image::Pointer tmpImage = mitk::IOUtil::LoadImage(param.imagePath); mitk::Image::Pointer tmpMask = mitk::IOUtil::LoadImage(param.maskPath); image = tmpImage; mask = tmpMask; if ((image->GetDimension() != mask->GetDimension())) { MITK_INFO << "Dimension of image does not match. "; MITK_INFO << "Correct one image, may affect the result"; if (image->GetDimension() == 2) { mitk::Convert2Dto3DImageFilter::Pointer multiFilter2 = mitk::Convert2Dto3DImageFilter::New(); multiFilter2->SetInput(tmpImage); multiFilter2->Update(); image = multiFilter2->GetOutput(); } if (mask->GetDimension() == 2) { mitk::Convert2Dto3DImageFilter::Pointer multiFilter3 = mitk::Convert2Dto3DImageFilter::New(); multiFilter3->SetInput(tmpMask); multiFilter3->Update(); mask = multiFilter3->GetOutput(); } } int writeDirection = 0; if (parsedArgs.count("output-mode")) { writeDirection = us::any_cast(parsedArgs["output-mode"]); } if (param.resampleToFixIsotropic) { mitk::Image::Pointer newImage = mitk::Image::New(); AccessByItk_2(image, ResampleImage, param.resampleResolution, newImage); image = newImage; } if ( ! mitk::Equal(mask->GetGeometry(0)->GetOrigin(), image->GetGeometry(0)->GetOrigin())) { MITK_INFO << "Not equal Origins"; if (param.ensureSameSpace) { MITK_INFO << "Warning!"; MITK_INFO << "The origin of the input image and the mask do not match. They are"; MITK_INFO << "now corrected. Please check to make sure that the images still match"; image->GetGeometry(0)->SetOrigin(mask->GetGeometry(0)->GetOrigin()); } else { return -1; } } if (param.resampleMask) { mitk::Image::Pointer newMaskImage = mitk::Image::New(); AccessByItk_2(mask, ResampleMask, image, newMaskImage); mask = newMaskImage; } if ( ! mitk::Equal(mask->GetGeometry(0)->GetSpacing(), image->GetGeometry(0)->GetSpacing())) { MITK_INFO << "Not equal Sapcings"; if (param.ensureSameSpace) { MITK_INFO << "Warning!"; MITK_INFO << "The spacing of the mask was set to match the spacing of the input image."; MITK_INFO << "This might cause unintended spacing of the mask image"; image->GetGeometry(0)->SetSpacing(mask->GetGeometry(0)->GetSpacing()); } else { MITK_INFO << "The spacing of the mask and the input images is not equal."; MITK_INFO << "Terminating the programm. You may use the '-fi' option"; return -1; } } int direction = 0; if (parsedArgs.count("direction")) { direction = mitk::cl::splitDouble(parsedArgs["direction"].ToString(), ';')[0]; } MITK_INFO << "Start creating Mask without NaN"; mitk::Image::Pointer maskNoNaN = mitk::Image::New(); AccessByItk_2(image, CreateNoNaNMask, mask, maskNoNaN); //CreateNoNaNMask(mask, image, maskNoNaN); bool sliceWise = false; int sliceDirection = 0; int currentSlice = 0; bool imageToProcess = true; std::vector floatVector; std::vector maskVector; std::vector maskNoNaNVector; if ((parsedArgs.count("slice-wise")) && image->GetDimension() > 2) { MITK_INFO << "Enabled slice-wise"; sliceWise = true; sliceDirection = mitk::cl::splitDouble(parsedArgs["slice-wise"].ToString(), ';')[0]; MITK_INFO << sliceDirection; ExtractSlicesFromImages(image, mask, maskNoNaN, sliceDirection, floatVector, maskVector, maskNoNaNVector); MITK_INFO << "Slice"; } for (auto cFeature : features) { if (param.defineGlobalMinimumIntensity) { cFeature->SetMinimumIntensity(param.globalMinimumIntensity); cFeature->SetUseMinimumIntensity(true); } if (param.defineGlobalMaximumIntensity) { cFeature->SetMaximumIntensity(param.globalMaximumIntensity); cFeature->SetUseMaximumIntensity(true); } if (param.defineGlobalNumberOfBins) { cFeature->SetBins(param.globalNumberOfBins); } cFeature->SetParameter(parsedArgs); cFeature->SetDirection(direction); } bool addDescription = parsedArgs.count("description"); mitk::cl::FeatureResultWritter writer(param.outputPath, writeDirection); std::string description = ""; if (addDescription) { description = parsedArgs["description"].ToString(); } mitk::Image::Pointer cImage = image; mitk::Image::Pointer cMask = mask; mitk::Image::Pointer cMaskNoNaN = maskNoNaN; if (param.useHeader) { writer.AddColumn("Patient"); writer.AddColumn("Image"); writer.AddColumn("Segmentation"); } // Create a QTApplication and a Datastorage // This is necessary in order to save screenshots of // each image / slice. QApplication qtapplication(argc, argv); QmitkRegisterClasses(); + std::vector allStats; + while (imageToProcess) { if (sliceWise) { cImage = floatVector[currentSlice]; cMask = maskVector[currentSlice]; cMaskNoNaN = maskNoNaNVector[currentSlice]; imageToProcess = (floatVector.size()-1 > (currentSlice)) ? true : false ; } else { imageToProcess = false; } if (param.writePNGScreenshots) { SaveSliceOrImageAsPNG(cImage, cMask, param.pngScreenshotsPath, currentSlice); } if (param.writeAnalysisImage) { mitk::IOUtil::SaveImage(cImage, param.anaylsisImagePath); } if (param.writeAnalysisMask) { mitk::IOUtil::SaveImage(cImage, param.analysisMaskPath); } mitk::AbstractGlobalImageFeature::FeatureListType stats; for (auto cFeature : features) { cFeature->CalculateFeaturesUsingParameters(cImage, cMask, cMaskNoNaN, stats); } for (std::size_t i = 0; i < stats.size(); ++i) { std::cout << stats[i].first << " - " << stats[i].second << std::endl; } writer.AddHeader(description, currentSlice, stats, param.useHeader, addDescription); if (true) { writer.AddColumn(param.imageFolder); writer.AddColumn(param.imageName); writer.AddColumn(param.maskName); } writer.AddResult(description, currentSlice, stats, param.useHeader, addDescription); + allStats.push_back(stats); ++currentSlice; } + if (sliceWise) + { + mitk::AbstractGlobalImageFeature::FeatureListType statMean, statStd; + for (std::size_t i = 0; i < allStats[0].size(); ++i) + { + auto cElement1 = allStats[0][i]; + cElement1.first = "SliceWise Mean " + cElement1.first; + cElement1.second = 0.0; + auto cElement2 = allStats[0][i]; + cElement2.first = "SliceWise Var. " + cElement2.first; + cElement2.second = 0.0; + statMean.push_back(cElement1); + statStd.push_back(cElement2); + } + + for (auto cStat : allStats) + { + for (std::size_t i = 0; i < cStat.size(); ++i) + { + statMean[i].second += cStat[i].second / (1.0*allStats.size()); + } + } + + for (auto cStat : allStats) + { + for (std::size_t i = 0; i < cStat.size(); ++i) + { + statStd[i].second += (cStat[i].second - statMean[i].second)*(cStat[i].second - statMean[i].second) / (1.0*allStats.size()); + } + } + + for (std::size_t i = 0; i < statMean.size(); ++i) + { + std::cout << statMean[i].first << " - " << statMean[i].second << std::endl; + std::cout << statStd[i].first << " - " << statStd[i].second << std::endl; + } + if (true) + { + writer.AddColumn(param.imageFolder); + writer.AddColumn(param.imageName); + writer.AddColumn(param.maskName + " - Mean"); + } + writer.AddResult(description, currentSlice, statMean, param.useHeader, addDescription); + if (true) + { + writer.AddColumn(param.imageFolder); + writer.AddColumn(param.imageName); + writer.AddColumn(param.maskName + " - Var."); + } + writer.AddResult(description, currentSlice, statStd, param.useHeader, addDescription); + } + if (param.useLogfile) { log << "Finished calculation"; log.close(); } return 0; } #endif diff --git a/Modules/Classification/CLMiniApps/CLImageTypeConverter.cpp b/Modules/Classification/CLMiniApps/CLImageTypeConverter.cpp index 2b94f4c168..c636160a8b 100644 --- a/Modules/Classification/CLMiniApps/CLImageTypeConverter.cpp +++ b/Modules/Classification/CLMiniApps/CLImageTypeConverter.cpp @@ -1,107 +1,108 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include "mitkIOUtil.h" #include #include #define CONVERT_IMAGE(TYPE, DIM) itk::Image::Pointer itkImage = itk::Image::New(); \ MITK_INFO << "Data Type for Conversion: "<< typeid(TYPE).name(); \ mitk::CastToItkImage(image, itkImage); \ mitk::CastToMitkImage(itkImage, outputImage) int main(int argc, char* argv[]) { mitkCommandLineParser parser; parser.setTitle("Image Type Converter"); parser.setCategory("Preprocessing Tools"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--","-"); // Add command line argument names parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input file:", "Input file",us::Any(),false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output file:", "Output file", us::Any(), false); parser.addArgument("type", "t", mitkCommandLineParser::OutputFile, "Type definition:", "Define Scalar data type: int, uint, short, ushort, char, uchar, float, double", us::Any(), false); std::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 inputName = us::any_cast(parsedArgs["input"]); std::string outputName = us::any_cast(parsedArgs["output"]); std::string type = us::any_cast(parsedArgs["type"]); mitk::Image::Pointer image = mitk::IOUtil::LoadImage(inputName); mitk::Image::Pointer outputImage = mitk::Image::New(); if (type.compare("int") == 0) { CONVERT_IMAGE(int, 3); } else if (type.compare("uint") == 0) { CONVERT_IMAGE(unsigned int, 3); } else if (type.compare("char") == 0) { CONVERT_IMAGE(char, 3); } else if (type.compare("uchar") == 0) { CONVERT_IMAGE(unsigned char, 3); } else if (type.compare("short") == 0) { CONVERT_IMAGE(short, 3); } else if (type.compare("ushort") == 0) { CONVERT_IMAGE(unsigned short, 3); } else if (type.compare("float") == 0) { CONVERT_IMAGE(float, 3); } else if (type.compare("double") == 0) { CONVERT_IMAGE(double, 3); } else if (type.compare("none") == 0) { MITK_INFO << " No conversion performed"; + outputImage = image; } else { CONVERT_IMAGE(double, 3); } mitk::IOUtil::SaveImage(outputImage, outputName); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/Modules/Classification/CLMiniApps/CLN4.cpp b/Modules/Classification/CLMiniApps/CLN4.cpp index 65e742a61b..4ff96603bc 100644 --- a/Modules/Classification/CLMiniApps/CLN4.cpp +++ b/Modules/Classification/CLMiniApps/CLN4.cpp @@ -1,112 +1,121 @@ /*=================================================================== 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 "mitkCommandLineParser.h" #include "mitkIOUtil.h" #include #include "mitkCommandLineParser.h" #include #include int main(int argc, char* argv[]) { typedef itk::Image MaskImageType; typedef itk::Image ImageType; typedef itk::N4BiasFieldCorrectionImageFilter < ImageType, MaskImageType, ImageType > FilterType; mitkCommandLineParser parser; parser.setTitle("N4 Bias Field Correction"); parser.setCategory("Classification Command Tools"); parser.setDescription(""); parser.setContributor("MBI"); parser.setArgumentPrefix("--", "-"); // Add command line argument names parser.addArgument("help", "h", mitkCommandLineParser::Bool, "Help:", "Show this help text"); parser.addArgument("input", "i", mitkCommandLineParser::InputDirectory, "Input file:", "Input file", us::Any(), false); parser.addArgument("mask", "m", mitkCommandLineParser::OutputFile, "Output file:", "Mask file", us::Any(), false); parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output file:", "Output file", us::Any(), false); parser.addArgument("number-of-controllpoints", "noc", mitkCommandLineParser::Int, "Parameter", "The noc for the point grid size defining the B-spline estimate (default 4)", us::Any(), true); parser.addArgument("number-of-fitting-levels", "nofl", mitkCommandLineParser::Int, "Parameter", "Number of fitting levels for the multi-scale approach (default 1)", us::Any(), true); parser.addArgument("number-of-histogram-bins", "nofl", mitkCommandLineParser::Int, "Parameter", "number of bins defining the log input intensity histogram (default 200)", us::Any(), true); parser.addArgument("spline-order", "so", mitkCommandLineParser::Int, "Parameter", "Define the spline order (default 3)", us::Any(), true); parser.addArgument("winer-filter-noise", "wfn", mitkCommandLineParser::Float, "Parameter", "Noise estimate defining the Wiener filter (default 0.01)", us::Any(), true); - + parser.addArgument("number-of-maximum-iterations", "nomi", mitkCommandLineParser::Int, "Parameter", "Spezifies the maximum number of iterations per run", us::Any(), true); + // ToDo: Number Of Maximum Iterations durchschleifen std::map parsedArgs = parser.parseArguments(argc, argv); // Show a help message if (parsedArgs.count("help") || parsedArgs.count("h")) { std::cout << parser.helpText(); return EXIT_SUCCESS; } MaskImageType::Pointer itkMsk = MaskImageType::New(); mitk::Image::Pointer img = mitk::IOUtil::LoadImage(parsedArgs["mask"].ToString()); mitk::CastToItkImage(img, itkMsk); ImageType::Pointer itkImage = ImageType::New(); mitk::Image::Pointer img2 = mitk::IOUtil::LoadImage(parsedArgs["input"].ToString()); mitk::CastToItkImage(img2, itkImage); FilterType::Pointer filter = FilterType::New(); filter->SetInput(itkImage); filter->SetMaskImage(itkMsk); if (parsedArgs.count("number-of-controllpoints") > 0) { int variable = us::any_cast(parsedArgs["maximum-iterations"]); MITK_INFO << "Number of controll points: " << variable; filter->SetNumberOfControlPoints(variable); } if (parsedArgs.count("number-of-fitting-levels") > 0) { int variable = us::any_cast(parsedArgs["number-of-fitting-levels"]); MITK_INFO << "Number of fitting levels: " << variable; filter->SetNumberOfFittingLevels(variable); } if (parsedArgs.count("number-of-histogram-bins") > 0) { int variable = us::any_cast(parsedArgs["number-of-histogram-bins"]); MITK_INFO << "Number of histogram bins: " << variable; filter->SetNumberOfHistogramBins(variable); } if (parsedArgs.count("spline-order") > 0) { int variable = us::any_cast(parsedArgs["spline-order"]); MITK_INFO << "Spline Order " << variable; filter->SetSplineOrder(variable); } if (parsedArgs.count("winer-filter-noise") > 0) { float variable = us::any_cast(parsedArgs["winer-filter-noise"]); MITK_INFO << "Number of histogram bins: " << variable; filter->SetWienerFilterNoise(variable); } + if (parsedArgs.count("number-of-maximum-iterations") > 0) + { + int variable = us::any_cast(parsedArgs["number-of-maximum-iterations"]); + MITK_INFO << "Number of Maximum Iterations: " << variable; + auto list = filter->GetMaximumNumberOfIterations(); + list.Fill(variable); + filter->SetMaximumNumberOfIterations(list); + } filter->Update(); auto out = filter->GetOutput(); mitk::Image::Pointer outImg = mitk::Image::New(); mitk::CastToMitkImage(out, outImg); mitk::IOUtil::SaveImage(outImg, parsedArgs["output"].ToString()); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp b/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp new file mode 100644 index 0000000000..2bffe322a0 --- /dev/null +++ b/Modules/Classification/CLMiniApps/CLOverlayRoiCenterOfMass.cpp @@ -0,0 +1,174 @@ +/*=================================================================== + +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. + +===================================================================*/ +#ifndef mitkCLPolyToNrrd_cpp +#define mitkCLPolyToNrrd_cpp + +#include "time.h" +#include +#include + +#include +#include "mitkCommandLineParser.h" + +#include +#include +#include + +#include +#include +#include "QmitkRegisterClasses.h" +#include "QmitkRenderWindow.h" +#include "vtkRenderLargeImage.h" +#include "vtkPNGWriter.h" + +#include +#include + +typedef itk::Image< double, 3 > FloatImageType; +typedef itk::Image< unsigned char, 3 > MaskImageType; + + +template +static void +FindMostSampleSlice(itk::Image* mask, int & selectedSlice) +{ + int size = mask->GetLargestPossibleRegion().GetSize()[0]; + std::vector numberOfSamples; + numberOfSamples.resize(size,0); + + itk::ImageRegionIteratorWithIndex > mask1Iter(mask, mask->GetLargestPossibleRegion()); + while (!mask1Iter.IsAtEnd()) + { + if (mask1Iter.Value() > 0) + { + numberOfSamples[mask1Iter.GetIndex()[0]]+=1; + } + ++mask1Iter; + } + selectedSlice = 0; + for (int i = 0; i < numberOfSamples.size(); ++i) + { + if (numberOfSamples[selectedSlice] < numberOfSamples[i]) + selectedSlice = i; + } +} + +static +void SaveSliceOrImageAsPNG(mitk::Image::Pointer image, mitk::Image::Pointer mask, std::string path, int index) +{ + // Create a Standalone Datastorage for the single purpose of saving screenshots.. + mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); + QmitkRenderWindow renderWindow; + renderWindow.GetRenderer()->SetDataStorage(ds); + + auto nodeI = mitk::DataNode::New(); + nodeI->SetData(image); + auto nodeM = mitk::DataNode::New(); + nodeM->SetData(mask); + ds->Add(nodeI); + ds->Add(nodeM); + + mitk::TimeGeometry::Pointer geo = ds->ComputeBoundingGeometry3D(ds->GetAll()); + mitk::RenderingManager::GetInstance()->InitializeViews(geo); + + mitk::SliceNavigationController::Pointer sliceNaviController = renderWindow.GetSliceNavigationController(); + unsigned int numberOfSteps = 1; + if (sliceNaviController) + { + numberOfSteps = sliceNaviController->GetSlice()->GetSteps(); + sliceNaviController->GetSlice()->SetPos(0); + } + + renderWindow.show(); + renderWindow.resize(256, 256); + + if (sliceNaviController) + { + sliceNaviController->GetSlice()->SetPos(index); + } + renderWindow.GetRenderer()->PrepareRender(); + + vtkRenderWindow* renderWindow2 = renderWindow.GetVtkRenderWindow(); + mitk::BaseRenderer* baserenderer = mitk::BaseRenderer::GetInstance(renderWindow2); + auto vtkRender = baserenderer->GetVtkRenderer(); + vtkRender->GetRenderWindow()->WaitForCompletion(); + + vtkRenderLargeImage* magnifier = vtkRenderLargeImage::New(); + magnifier->SetInput(vtkRender); + magnifier->SetMagnification(3.0); + + std::stringstream ss; + ss << path <<".png"; + std::string tmpImageName; + ss >> tmpImageName; + auto fileWriter = vtkPNGWriter::New(); + fileWriter->SetInputConnection(magnifier->GetOutputPort()); + fileWriter->SetFileName(tmpImageName.c_str()); + fileWriter->Write(); + fileWriter->Delete(); +} + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + parser.setArgumentPrefix("--", "-"); + + parser.addArgument("image", "i", mitkCommandLineParser::InputImage, "Input Image", "", us::Any(),false); + parser.addArgument("mask", "m", mitkCommandLineParser::InputImage, "Input Image", "", us::Any(),false); + parser.addArgument("output", "o", mitkCommandLineParser::InputImage, "Output Image", "", us::Any(),false); + + // Miniapp Infos + parser.setCategory("Classification Tools"); + parser.setTitle("Image with Overlay Plotter"); + parser.setDescription("Plots "); + parser.setContributor("MBI"); + + std::map parsedArgs = parser.parseArguments(argc, argv); + + std::string imagePath = us::any_cast(parsedArgs["image"]); + std::string maskPath = us::any_cast(parsedArgs["mask"]); + std::string outputPath = us::any_cast(parsedArgs["output"]); + + if (parsedArgs.size()==0) + { + return EXIT_FAILURE; + } + if ( parsedArgs.count("help") || parsedArgs.count("h")) + { + return EXIT_SUCCESS; + } + + std::string version = "Version: 1.0"; + MITK_INFO << version; + + mitk::Image::Pointer image = mitk::IOUtil::LoadImage(imagePath); + mitk::Image::Pointer mask = mitk::IOUtil::LoadImage(maskPath); + + // Create a QTApplication and a Datastorage + // This is necessary in order to save screenshots of + // each image / slice. + QApplication qtapplication(argc, argv); + QmitkRegisterClasses(); + + int currentSlice = 0; + AccessByItk_1(mask, FindMostSampleSlice, currentSlice); + + SaveSliceOrImageAsPNG(image, mask, outputPath, currentSlice); + + return 0; +} + +#endif diff --git a/Modules/Classification/CLMiniApps/CLWeighting.cpp b/Modules/Classification/CLMiniApps/CLWeighting.cpp new file mode 100644 index 0000000000..b47bcc67e3 --- /dev/null +++ b/Modules/Classification/CLMiniApps/CLWeighting.cpp @@ -0,0 +1,217 @@ +/*=================================================================== + +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. + +===================================================================*/ +#ifndef mitkForest_cpp +#define mitkForest_cpp + +#include "time.h" +#include +#include +#include "mitkCommandLineParser.h" +#include +#include +#include + + +//#include +#include + +struct TrainingSet { + vnl_matrix feature; + vnl_vector label; + double ratio; +}; + + +const +vnl_matrix ReadMatrix(std::string path) +{ + std::fstream file(path); + std::vector > listOfRows; + + std::string line; + while (std::getline(file, line)) + { + auto current_row = mitk::cl::splitDouble(line, ','); + if (listOfRows.size() < 1) + { + listOfRows.push_back(current_row); + } + else if (current_row.size() == listOfRows[0].size()) + { + listOfRows.push_back(current_row); + } + } + file.close(); + + vnl_matrix result(listOfRows.size(), listOfRows[0].size()); + for (std::size_t i = 0; i < listOfRows.size(); ++i) + { + for (std::size_t j = 0; j < listOfRows[0].size(); ++j) + { + result(i, j) = listOfRows[i][j]; + } + } + return result; +} + +const +TrainingSet ReadBothMatrix(std::string train, std::string test) +{ + std::fstream file(train); + std::vector > listOfRows; + std::vector label; + + double trSamples = 0; + double teSamples = 0; + + std::string line; + while (std::getline(file, line)) + { + auto current_row = mitk::cl::splitDouble(line, ','); + if (listOfRows.size() < 1) + { + listOfRows.push_back(current_row); + label.push_back(0); + trSamples += 1; + } + else if (current_row.size() == listOfRows[0].size()) + { + listOfRows.push_back(current_row); + label.push_back(0); + trSamples += 1; + } + } + file.close(); + + std::fstream file2(test); + while (std::getline(file2, line)) + { + auto current_row = mitk::cl::splitDouble(line, ','); + if (listOfRows.size() < 1) + { + listOfRows.push_back(current_row); + label.push_back(1); + teSamples += 1; + } + else if (current_row.size() == listOfRows[0].size()) + { + listOfRows.push_back(current_row); + label.push_back(1); + teSamples += 1; + } + } + file2.close(); + + vnl_matrix resultMatrix(listOfRows.size(), listOfRows[0].size()); + vnl_vector resultLabel(listOfRows.size()); + for (std::size_t i = 0; i < listOfRows.size(); ++i) + { + for (std::size_t j = 0; j < listOfRows[0].size(); ++j) + { + resultMatrix(i, j) = listOfRows[i][j]; + } + resultLabel(i) = label[i]; + } + TrainingSet set; + set.feature = resultMatrix; + set.label = resultLabel; + set.ratio = trSamples / teSamples; + return set; +} + + +int main(int argc, char* argv[]) +{ + mitkCommandLineParser parser; + parser.setArgumentPrefix("--", "-"); + // required params + parser.addArgument("training", "t", mitkCommandLineParser::InputImage, "Input Image", "desc", us::Any(), false); + parser.addArgument("prediction", "p", mitkCommandLineParser::InputImage, "Input Image", "desc", us::Any(), false); + parser.addArgument("output", "o", mitkCommandLineParser::InputImage, "Normalisation mode", "desc", us::Any(), false); + //parser.addArgument("algorithm", "a", mitkCommandLineParser::InputImage, "Input Mask", "desc", us::Any(), false); + + // Miniapp Infos + parser.setCategory("Classification Tools"); + parser.setTitle("Importance weighting algorithm"); + parser.setDescription("Calculates the importance weighting of two input matrixes. "); + parser.setContributor("MBI"); + + MITK_INFO << "Extracting Parameters...."; + std::map parsedArgs = parser.parseArguments(argc, argv); + + std::string trainingPath = us::any_cast(parsedArgs["training"]); + std::string predictionPath = us::any_cast(parsedArgs["prediction"]); + std::string outputPath = us::any_cast(parsedArgs["output"]); + //std::string algorithm = us::any_cast(parsedArgs["algorithm"]); + + MITK_INFO << "Reading Data..."; + auto input = ReadBothMatrix(trainingPath, predictionPath); + + MITK_INFO << "Calculating Weights..."; + mitk::GeneralizedLinearModel glm(input.feature, input.label); + auto weights = glm.ExpMu(input.feature); + + MITK_INFO << "Writing Weights ..."; + MITK_INFO << outputPath; + std::ofstream file(outputPath); + for (unsigned int i = 0; i < input.label.size(); ++i) + { + if (input.label(i) < 0.5) + { + file << (input.ratio * weights(i)) << std::endl; + } + } + file.close(); + + + ////////////////////////////////////////////////////////////////////////////// + // Read Images + ////////////////////////////////////////////////////////////////////////////// + //mitk::DataCollection::Pointer col = mitk::DataCollection::New(); + + //MITK_INFO << "Arg 2 " << argv[2]; + //mitk::Image::Pointer sur=mitk::IOUtil::LoadImage(argv[2]); + //col->AddData(sur.GetPointer(),"sur"); + //MITK_INFO << "Arg 3 " << argv[3]; + //mitk::Image::Pointer mask=mitk::IOUtil::LoadImage(argv[3]); + //col->AddData(mask.GetPointer(),"mask"); + + //std::vector modalities; + //for (int i = 4; i < argc; ++i) + //{ + // MITK_INFO << "Img " << argv[i]; + // std::stringstream ss; + // ss << i; + // modalities.push_back(ss.str()); + // mitk::Image::Pointer img = mitk::IOUtil::LoadImage(argv[i]); + // col->AddData(img.GetPointer(),ss.str()); + //} + + //mitk::LRDensityEstimation est; + //est.SetCollection(col); + //est.SetTrainMask("sur"); + //est.SetTestMask("mask"); + //est.SetModalities(modalities); + //est.SetWeightName("weight"); + //est.Update(); + + //mitk::Image::Pointer w= col->GetMitkImage("weight"); + //mitk::IOUtil::SaveImage(w,argv[1]); + + return 0; +} + +#endif \ No newline at end of file diff --git a/Modules/Classification/CLMiniApps/CMakeLists.txt b/Modules/Classification/CLMiniApps/CMakeLists.txt index 655c5f0fb6..b1010950c0 100644 --- a/Modules/Classification/CLMiniApps/CMakeLists.txt +++ b/Modules/Classification/CLMiniApps/CMakeLists.txt @@ -1,138 +1,139 @@ option(BUILD_ClassificationMiniApps "Build commandline tools for classification" OFF) if(BUILD_ClassificationMiniApps OR MITK_BUILD_ALL_APPS) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) # list of miniapps # if an app requires additional dependencies # they are added after a "^^" and separated by "_" set( classificationminiapps RandomForestTraining^^MitkCLVigraRandomForest NativeHeadCTSegmentation^^MitkCLVigraRandomForest ManualSegmentationEvaluation^^MitkCLVigraRandomForest CLGlobalImageFeatures^^MitkCore_MitkCLUtilities_MitkQtWidgetsExt CLMRNormalization^^MitkCore_MitkCLUtilities_MitkCLMRUtilities CLStaple^^MitkCore_MitkCLUtilities CLVoxelFeatures^^MitkCore_MitkCLUtilities CLDicom2Nrrd^^MitkCore CLPolyToNrrd^^MitkCore CLImageTypeConverter^^MitkCore CLResampleImageToReference^^MitkCore CLRandomSampling^^MitkCore_MitkCLUtilities CLRemoveEmptyVoxels^^MitkCore CLN4^^MitkCore CLMultiForestPrediction^^MitkDataCollection_MitkCLVigraRandomForest CLNrrdToPoly^^MitkCore CL2Dto3DImage^^MitkCore CLWeighting^^MitkCore_MitkCLImportanceWeighting_MitkCLUtilities + CLOverlayRoiCenterOfMass^^MitkCore_MitkCLUtilities_MitkQtWidgetsExt # RandomForestPrediction^^MitkCLVigraRandomForest ) foreach(classificationminiapps ${classificationminiapps}) # extract mini app name and dependencies string(REPLACE "^^" "\\;" miniapp_info ${classificationminiapps}) set(miniapp_info_list ${miniapp_info}) list(GET miniapp_info_list 0 appname) list(GET miniapp_info_list 1 raw_dependencies) string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") set(dependencies_list ${dependencies}) mitk_create_executable(${appname} DEPENDS MitkCore MitkCLCore MitkCommandLine ${dependencies_list} PACKAGE_DEPENDS ITK Qt5|Core Vigra CPP_FILES ${appname}.cpp ) # CPP_FILES ${appname}.cpp mitkCommandLineParser.cpp if(EXECUTABLE_IS_ENABLED) # On Linux, create a shell script to start a relocatable application if(UNIX AND NOT APPLE) install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) endif() get_target_property(_is_bundle ${EXECUTABLE_TARGET} MACOSX_BUNDLE) if(APPLE) if(_is_bundle) set(_target_locations ${EXECUTABLE_TARGET}.app) set(${_target_locations}_qt_plugins_install_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_bundle_dest_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_qt_plugins_for_current_bundle ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_qt_conf_install_dirs ${EXECUTABLE_TARGET}.app/Contents/Resources) install(TARGETS ${EXECUTABLE_TARGET} BUNDLE DESTINATION . ) else() if(NOT MACOSX_BUNDLE_NAMES) set(_qt_conf_install_dirs bin) set(_target_locations bin/${EXECUTABLE_TARGET}) set(${_target_locations}_qt_plugins_install_dir bin) install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) else() foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) list(APPEND _qt_conf_install_dirs ${bundle_name}.app/Contents/Resources) set(_current_target_location ${bundle_name}.app/Contents/MacOS/${EXECUTABLE_TARGET}) list(APPEND _target_locations ${_current_target_location}) set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) message( " set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) ") install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION ${bundle_name}.app/Contents/MacOS/) endforeach() endif() endif() else() set(_target_locations bin/${EXECUTABLE_TARGET}${CMAKE_EXECUTABLE_SUFFIX}) set(${_target_locations}_qt_plugins_install_dir bin) set(_qt_conf_install_dirs bin) install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) endif() endif() endforeach() # This mini app does not depend on mitkDiffusionImaging at all #mitk_create_executable(CLGlobalImageFeatures # DEPENDS MitkCore MitkCLUtilities # CPP_FILES CLGlobalImageFeatures.cpp mitkCommandLineParser.cpp #) mitk_create_executable(CLSimpleVoxelClassification DEPENDS MitkCore MitkCLCore MitkDataCollection MitkCLVigraRandomForest MitkCommandLine CPP_FILES CLSimpleVoxelClassification.cpp ) # This mini app does not depend on mitkDiffusionImaging at all mitk_create_executable(CLVoxelClassification DEPENDS MitkCore MitkCLCore MitkDataCollection MitkCLImportanceWeighting MitkCLVigraRandomForest CPP_FILES CLVoxelClassification.cpp ) #mitk_create_executable(CLBrainMask # DEPENDS MitkCore MitkCLUtilities # CPP_FILES CLBrainMask.cpp mitkCommandLineParser.cpp #) #mitk_create_executable(CLImageConverter # DEPENDS MitkCore # CPP_FILES CLImageConverter.cpp mitkCommandLineParser.cpp #) #mitk_create_executable(CLSurWeighting # DEPENDS MitkCore MitkCLUtilities MitkDataCollection #MitkCLImportanceWeighting # CPP_FILES CLSurWeighting.cpp mitkCommandLineParser.cpp #) #mitk_create_executable(CLImageCropper # DEPENDS MitkCore MitkCLUtilities MitkAlgorithmsExt # CPP_FILES CLImageCropper.cpp mitkCommandLineParser.cpp #) # On Linux, create a shell script to start a relocatable application if(UNIX AND NOT APPLE) install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) endif() if(EXECUTABLE_IS_ENABLED) MITK_INSTALL_TARGETS(EXECUTABLES ${EXECUTABLE_TARGET}) endif() endif() diff --git a/Modules/Classification/CLUtilities/files.cmake b/Modules/Classification/CLUtilities/files.cmake index 6de46d38f8..27aeaf329d 100644 --- a/Modules/Classification/CLUtilities/files.cmake +++ b/Modules/Classification/CLUtilities/files.cmake @@ -1,30 +1,31 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkCLResultWritter.cpp Algorithms/itkLabelSampler.cpp Algorithms/itkSmoothedClassProbabilites.cpp Algorithms/mitkRandomImageSampler.cpp Features/itkNeighborhoodFunctorImageFilter.cpp Features/itkLineHistogramBasedMassImageFilter.cpp GlobalImageFeatures/mitkGIFCooccurenceMatrix.cpp GlobalImageFeatures/mitkGIFCooccurenceMatrix2.cpp GlobalImageFeatures/mitkGIFGrayLevelRunLength.cpp GlobalImageFeatures/mitkGIFGrayLevelSizeZone.cpp GlobalImageFeatures/mitkGIFFirstOrderStatistics.cpp GlobalImageFeatures/mitkGIFVolumetricStatistics.cpp GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp GlobalImageFeatures/mitkGIFNeighbourhoodGreyLevelDifference.cpp - + GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp + MiniAppUtils/mitkGlobalImageFeaturesParameter.cpp MiniAppUtils/mitkSplitParameterToVector.cpp mitkCLUtil.cpp ) set( TOOL_FILES ) diff --git a/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h b/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h new file mode 100644 index 0000000000..7c17edf408 --- /dev/null +++ b/Modules/Classification/CLUtilities/include/mitkGIFGreyLevelSizeZone.h @@ -0,0 +1,122 @@ +#ifndef mitkGIFGreyLevelSizeZone_h +#define mitkGIFGreyLevelSizeZone_h + +#include +#include +#include + +#include + +namespace mitk +{ + struct GreyLevelSizeZoneMatrixHolder + { + public: + GreyLevelSizeZoneMatrixHolder(double min, double max, int number, int maxSize); + + int IntensityToIndex(double intensity); + double IndexToMinIntensity(int index); + double IndexToMeanIntensity(int index); + double IndexToMaxIntensity(int index); + + double m_MinimumRange; + double m_MaximumRange; + double m_Stepsize; + int m_NumberOfBins; + int m_MaximumSize; + Eigen::MatrixXd m_Matrix; + + }; + + struct GreyLevelSizeZoneFeatures + { + GreyLevelSizeZoneFeatures() : + SmallZoneEmphasis(0), + LargeZoneEmphasis(0), + LowGreyLevelEmphasis(0), + HighGreyLevelEmphasis(0), + SmallZoneLowGreyLevelEmphasis(0), + SmallZoneHighGreyLevelEmphasis(0), + LargeZoneLowGreyLevelEmphasis(0), + LargeZoneHighGreyLevelEmphasis(0), + GreyLevelNonUniformity(0), + GreyLevelNonUniformityNormalized(0), + ZoneSizeNonUniformity(0), + ZoneSizeNoneUniformityNormalized(0), + ZonePercentage(0), + GreyLevelMean(0), + GreyLevelVariance(0), + ZoneSizeMean(0), + ZoneSizeVariance(0), + ZoneSizeEntropy(0) + { + } + + public: + double SmallZoneEmphasis; + double LargeZoneEmphasis; + double LowGreyLevelEmphasis; + double HighGreyLevelEmphasis; + double SmallZoneLowGreyLevelEmphasis; + double SmallZoneHighGreyLevelEmphasis; + double LargeZoneLowGreyLevelEmphasis; + double LargeZoneHighGreyLevelEmphasis; + double GreyLevelNonUniformity; + double GreyLevelNonUniformityNormalized; + double ZoneSizeNonUniformity; + double ZoneSizeNoneUniformityNormalized; + double ZonePercentage; + double GreyLevelMean; + double GreyLevelVariance; + double ZoneSizeMean; + double ZoneSizeVariance; + double ZoneSizeEntropy; + }; + + + class MITKCLUTILITIES_EXPORT GIFGreyLevelSizeZone : public AbstractGlobalImageFeature + { + public: + mitkClassMacro(GIFGreyLevelSizeZone, AbstractGlobalImageFeature); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + GIFGreyLevelSizeZone(); + + /** + * \brief Calculates the Cooccurence-Matrix based features for this class. + */ + virtual FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; + + /** + * \brief Returns a list of the names of all features that are calculated from this class + */ + virtual FeatureNameListType GetFeatureNames() override; + + virtual void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList); + virtual void AddArguments(mitkCommandLineParser &parser); + + itkGetConstMacro(Range,double); + itkSetMacro(Range, double); + itkGetConstMacro(Bins, int); + itkSetMacro(Bins, int); + + struct GIFGreyLevelSizeZoneConfiguration + { + double range; + unsigned int direction; + + double MinimumIntensity; + bool UseMinimumIntensity; + double MaximumIntensity; + bool UseMaximumIntensity; + int Bins; + }; + + private: + double m_Range; + int m_Bins; + }; + +} +#endif //mitkGIFGreyLevelSizeZone_h diff --git a/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h b/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h index cdc38d25c8..39004fd5d7 100644 --- a/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h +++ b/Modules/Classification/CLUtilities/include/mitkGIFNeighbouringGreyLevelDependenceFeatures.h @@ -1,146 +1,148 @@ #ifndef mitkGIFNeighbouringGreyLevelDependenceFeatures_h #define mitkGIFNeighbouringGreyLevelDependenceFeatures_h #include #include #include #include namespace mitk { struct NGLDMMatrixHolder { public: NGLDMMatrixHolder(double min, double max, int number, int depenence); int IntensityToIndex(double intensity); double IndexToMinIntensity(int index); double IndexToMeanIntensity(int index); double IndexToMaxIntensity(int index); double m_MinimumRange; double m_MaximumRange; double m_Stepsize; int m_NumberOfDependences; int m_NumberOfBins; Eigen::MatrixXd m_Matrix; int m_NeighbourhoodSize; unsigned long m_NumberOfNeighbourVoxels; unsigned long m_NumberOfDependenceNeighbourVoxels; unsigned long m_NumberOfNeighbourhoods; unsigned long m_NumberOfCompleteNeighbourhoods; }; struct NGLDMMatrixFeatures { NGLDMMatrixFeatures() : LowDependenceEmphasis(0), HighDependenceEmphasis(0), LowGreyLevelCountEmphasis(0), HighGreyLevelCountEmphasis(0), LowDependenceLowGreyLevelEmphasis(0), LowDependenceHighGreyLevelEmphasis(0), HighDependenceLowGreyLevelEmphasis(0), HighDependenceHighGreyLevelEmphasis(0), GreyLevelNonUniformity(0), GreyLevelNonUniformityNormalised(0), DependenceCountNonUniformity(0), DependenceCountNonUniformityNormalised(0), DependenceCountPercentage(0), GreyLevelVariance(0), DependenceCountVariance(0), DependenceCountEntropy(0), + DependenceCountEnergy(0), MeanGreyLevelCount(0), MeanDependenceCount(0), ExpectedNeighbourhoodSize(0), AverageNeighbourhoodSize(0), AverageIncompleteNeighbourhoodSize(0), PercentageOfCompleteNeighbourhoods(0), PercentageOfDependenceNeighbours(0) { } public: double LowDependenceEmphasis; double HighDependenceEmphasis; double LowGreyLevelCountEmphasis; double HighGreyLevelCountEmphasis; double LowDependenceLowGreyLevelEmphasis; double LowDependenceHighGreyLevelEmphasis; double HighDependenceLowGreyLevelEmphasis; double HighDependenceHighGreyLevelEmphasis; double GreyLevelNonUniformity; double GreyLevelNonUniformityNormalised; double DependenceCountNonUniformity; double DependenceCountNonUniformityNormalised; double DependenceCountPercentage; double GreyLevelVariance; double DependenceCountVariance; double DependenceCountEntropy; + double DependenceCountEnergy; double MeanGreyLevelCount; double MeanDependenceCount; double ExpectedNeighbourhoodSize; double AverageNeighbourhoodSize; double AverageIncompleteNeighbourhoodSize; double PercentageOfCompleteNeighbourhoods; double PercentageOfDependenceNeighbours; }; class MITKCLUTILITIES_EXPORT GIFNeighbouringGreyLevelDependenceFeature : public AbstractGlobalImageFeature { public: mitkClassMacro(GIFNeighbouringGreyLevelDependenceFeature, AbstractGlobalImageFeature) itkFactorylessNewMacro(Self) itkCloneMacro(Self) GIFNeighbouringGreyLevelDependenceFeature(); /** * \brief Calculates the Cooccurence-Matrix based features for this class. */ virtual FeatureListType CalculateFeatures(const Image::Pointer & image, const Image::Pointer &feature) override; /** * \brief Returns a list of the names of all features that are calculated from this class */ virtual FeatureNameListType GetFeatureNames() override; itkGetConstMacro(Range,double); itkSetMacro(Range, double); itkGetConstMacro(Alpha, int); itkSetMacro(Alpha, int); itkGetConstMacro(Bins, int); itkSetMacro(Bins, int); virtual void CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList); virtual void AddArguments(mitkCommandLineParser &parser); struct GIFNeighbouringGreyLevelDependenceFeatureConfiguration { double range; unsigned int direction; int alpha; double MinimumIntensity; bool UseMinimumIntensity; double MaximumIntensity; bool UseMaximumIntensity; int Bins; }; private: double m_Range; int m_Alpha; int m_Bins; }; } #endif //mitkGIFNeighbouringGreyLevelDependenceFeature_h diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp new file mode 100644 index 0000000000..0fc75ca2ea --- /dev/null +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFGreyLevelSizeZone.cpp @@ -0,0 +1,475 @@ +#include + +// MITK +#include +#include +#include + +// ITK + +#include +#include + +// STL +#include + +static +void MatrixFeaturesTo(mitk::GreyLevelSizeZoneMatrixHolder features, + std::string prefix, + mitk::GIFGreyLevelSizeZone::FeatureListType &featureList); +static +void CalculateMeanAndStdDevFeatures(std::vector featureList, + mitk::GreyLevelSizeZoneFeatures &meanFeature, + mitk::GreyLevelSizeZoneFeatures &stdFeature); +static +void NormalizeMatrixFeature(mitk::GreyLevelSizeZoneFeatures &features, + std::size_t number); + + + + +mitk::GreyLevelSizeZoneMatrixHolder::GreyLevelSizeZoneMatrixHolder(double min, double max, int number, int maxSize) : + m_MinimumRange(min), + m_MaximumRange(max), + m_NumberOfBins(number), + m_MaximumSize(maxSize) +{ + m_Matrix.resize(number, maxSize); + m_Matrix.fill(0); + m_Stepsize = (max - min) / (number); +} + +int mitk::GreyLevelSizeZoneMatrixHolder::IntensityToIndex(double intensity) +{ + return std::floor((intensity - m_MinimumRange) / m_Stepsize); +} + +double mitk::GreyLevelSizeZoneMatrixHolder::IndexToMinIntensity(int index) +{ + return m_MinimumRange + index * m_Stepsize; +} +double mitk::GreyLevelSizeZoneMatrixHolder::IndexToMeanIntensity(int index) +{ + return m_MinimumRange + (index+0.5) * m_Stepsize; +} +double mitk::GreyLevelSizeZoneMatrixHolder::IndexToMaxIntensity(int index) +{ + return m_MinimumRange + (index + 1) * m_Stepsize; +} + +template +void +CalculateGlSZMatrix(itk::Image* itkImage, + itk::Image* mask, + std::vector > offsets, + int range, + mitk::GreyLevelSizeZoneMatrixHolder &holder) +{ + typedef itk::Image ImageType; + typedef itk::Image MaskImageType; + typedef ImageType::IndexType IndexType; + + typedef itk::ImageRegionIteratorWithIndex ConstIterType; + typedef itk::ImageRegionIteratorWithIndex ConstMaskIterType; + + auto region = mask->GetLargestPossibleRegion(); + MaskImageType::RegionType newRegion; + newRegion.SetSize(region.GetSize()); + newRegion.SetIndex(region.GetIndex()); + + ConstIterType imageIter(itkImage, itkImage->GetLargestPossibleRegion()); + ConstMaskIterType maskIter(mask, mask->GetLargestPossibleRegion()); + + MaskImageType::Pointer visitedImage = MaskImageType::New(); + visitedImage->SetRegions(newRegion); + visitedImage->Allocate(); + visitedImage->FillBuffer(0); + + + while (!maskIter.IsAtEnd()) + { + if (maskIter.Value() > 0 ) + { + auto startIntensityIndex = holder.IntensityToIndex(imageIter.Value()); + std::vector indices; + indices.push_back(maskIter.GetIndex()); + unsigned int steps = 0; + + while (indices.size() > 0) + { + auto currentIndex = indices.back(); + indices.pop_back(); + + if (!region.IsInside(currentIndex)) + { + continue; + } + + auto wasVisited = visitedImage->GetPixel(currentIndex); + auto newIntensityIndex = holder.IntensityToIndex(itkImage->GetPixel(currentIndex)); + auto isInMask = mask->GetPixel(currentIndex); + + if ((isInMask > 0) && + (newIntensityIndex == startIntensityIndex) && + (wasVisited < 1)) + { + ++steps; + visitedImage->SetPixel(currentIndex, 1); + for (auto offset : offsets) + { + auto newIndex = currentIndex + offset; + indices.push_back(newIndex); + newIndex = currentIndex - offset; + indices.push_back(newIndex); + } + + } + } + if (steps > 0) + { + steps = std::min(steps, holder.m_MaximumSize); + holder.m_Matrix(startIntensityIndex, steps-1) += 1; + } + } + ++imageIter; + ++maskIter; + } +} + +void CalculateFeatures( + mitk::GreyLevelSizeZoneMatrixHolder &holder, + mitk::GreyLevelSizeZoneFeatures & results + ) +{ + auto SgzMatrix = holder.m_Matrix; + auto pgzMatrix = holder.m_Matrix; + auto pgMatrix = holder.m_Matrix; + auto pzMatrix = holder.m_Matrix; + + double Ns = pgzMatrix.sum(); + pgzMatrix /= Ns; + pgMatrix.rowwise().normalize(); + pzMatrix.colwise().normalize(); + + for (int i = 0; i < holder.m_NumberOfBins; ++i) + for (int j = 0; j < holder.m_NumberOfBins; ++j) + { + if (pgzMatrix(i, j) != pgzMatrix(i, j)) + pgzMatrix(i, j) = 0; + if (pgMatrix(i, j) != pgMatrix(i, j)) + pgMatrix(i, j) = 0; + if (pzMatrix(i, j) != pzMatrix(i, j)) + pzMatrix(i, j) = 0; + } + + Eigen::VectorXd SgVector = SgzMatrix.rowwise().sum(); + Eigen::VectorXd SzVector = SgzMatrix.colwise().sum(); + + for (int j = 0; j < SzVector.size(); ++j) + { + results.SmallZoneEmphasis += SzVector(j) / (j + 1) / (j + 1); + results.LargeZoneEmphasis += SzVector(j) * (j + 1) * (j + 1); + results.ZoneSizeNonUniformity += SzVector(j) * SzVector(j); + results.ZoneSizeNoneUniformityNormalized += SzVector(j) * SzVector(j); + } + for (int i = 0; i < SgVector.size(); ++i) + { + results.LowGreyLevelEmphasis += SgVector(i) / (i + 1) / (i + 1); + results.HighGreyLevelEmphasis += SgVector(i) * (i + 1) * (i + 1); + results.GreyLevelNonUniformity += SgVector(i)*SgVector(i); + results.GreyLevelNonUniformityNormalized += SgVector(i)*SgVector(i); + } + + for (int i = 0; i < SgzMatrix.rows(); ++i) + { + for (int j = 0; j < SgzMatrix.cols(); ++j) + { + results.SmallZoneLowGreyLevelEmphasis += SgzMatrix(i, j) / (i + 1) / (i + 1) / (j + 1) / (j + 1); + results.SmallZoneHighGreyLevelEmphasis += SgzMatrix(i, j) * (i + 1) * (i + 1) / (j + 1) / (j + 1); + results.LargeZoneLowGreyLevelEmphasis += SgzMatrix(i, j) / (i + 1) / (i + 1) * (j + 1.0) * (j + 1.0); + results.LargeZoneHighGreyLevelEmphasis += SgzMatrix(i, j) * (i + 1) * (i + 1) * (j + 1.0) * (j + 1.0); + results.ZonePercentage += SgzMatrix(i, j)*(j + 1); + + results.GreyLevelMean += (i + 1)*pgzMatrix(i, j); + results.ZoneSizeMean += (j + 1)*pgzMatrix(i, j); + if (pgzMatrix(i, j) > 0) + results.ZoneSizeEntropy -= pgzMatrix(i, j) * std::log(pgzMatrix(i, j)) / std::log(2); + } + } + + for (int i = 0; i < SgzMatrix.rows(); ++i) + { + for (int j = 0; j < SgzMatrix.cols(); ++j) + { + results.GreyLevelVariance += (i + 1 - results.GreyLevelMean)*(i + 1 - results.GreyLevelMean)*pgzMatrix(i, j); + results.ZoneSizeVariance += (j + 1 - results.ZoneSizeMean)*(j + 1 - results.ZoneSizeMean)*pgzMatrix(i, j); + } + } + + results.SmallZoneEmphasis /= Ns; + results.LargeZoneEmphasis /= Ns; + results.LowGreyLevelEmphasis /= Ns; + results.HighGreyLevelEmphasis /= Ns; + + results.SmallZoneLowGreyLevelEmphasis /= Ns; + results.SmallZoneHighGreyLevelEmphasis /= Ns; + results.LargeZoneLowGreyLevelEmphasis /= Ns; + results.LargeZoneHighGreyLevelEmphasis /= Ns; + results.GreyLevelNonUniformity /= Ns; + results.GreyLevelNonUniformityNormalized /= Ns*Ns; + results.ZoneSizeNonUniformity /= Ns; + results.ZoneSizeNoneUniformityNormalized /= Ns*Ns; + + results.ZonePercentage = Ns / results.ZonePercentage; +} + +template +void +CalculateGreyLevelSizeZoneFeatures(itk::Image* itkImage, mitk::Image::Pointer mask, mitk::GIFGreyLevelSizeZone::FeatureListType & featureList, mitk::GIFGreyLevelSizeZone::GIFGreyLevelSizeZoneConfiguration config) +{ + typedef itk::Image ImageType; + typedef itk::Image MaskType; + typedef itk::MinimumMaximumImageCalculator MinMaxComputerType; + typedef itk::Neighborhood NeighborhoodType; + typedef itk::Offset OffsetType; + + /////////////////////////////////////////////////////////////////////////////////////////////// + + typename MinMaxComputerType::Pointer minMaxComputer = MinMaxComputerType::New(); + minMaxComputer->SetImage(itkImage); + minMaxComputer->Compute(); + + double rangeMin = -0.5 + minMaxComputer->GetMinimum(); + double rangeMax = 0.5 + minMaxComputer->GetMaximum(); + + if (config.UseMinimumIntensity) + rangeMin = config.MinimumIntensity; + if (config.UseMaximumIntensity) + rangeMax = config.MaximumIntensity; + + // Define Range + int numberOfBins = config.Bins; + + typename MaskType::Pointer maskImage = MaskType::New(); + mitk::CastToItkImage(mask, maskImage); + + //Find possible directions + std::vector < itk::Offset > offsetVector; + NeighborhoodType hood; + hood.SetRadius(1); + unsigned int centerIndex = hood.GetCenterNeighborhoodIndex(); + OffsetType offset; + for (unsigned int d = 0; d < centerIndex; d++) + { + offset = hood.GetOffset(d); + bool useOffset = true; + for (unsigned int i = 0; i < VImageDimension; ++i) + { + offset[i] *= config.range; + if ((config.direction == i + 2) && offset[i] != 0) + { + useOffset = false; + } + } + if (useOffset) + { + offsetVector.push_back(offset); + MITK_INFO << offset; + } + } + if (config.direction == 1) + { + offsetVector.clear(); + offset[0] = 0; + offset[1] = 0; + offset[2] = 1; + offsetVector.push_back(offset); + } + + std::vector resultVector; + mitk::GreyLevelSizeZoneMatrixHolder holderOverall(rangeMin, rangeMax, numberOfBins,100); + mitk::GreyLevelSizeZoneFeatures overallFeature; + CalculateGlSZMatrix(itkImage, maskImage, offsetVector, config.range, holderOverall); + CalculateFeatures(holderOverall, overallFeature); + + std::stringstream ss; + ss << config.range; + std::string strRange = ss.str(); + MatrixFeaturesTo(overallFeature, "Grey Level Size Zone (" + strRange + ")", featureList); +} + + +static +void MatrixFeaturesTo(mitk::GreyLevelSizeZoneFeatures features, + std::string prefix, + mitk::GIFGreyLevelSizeZone::FeatureListType &featureList) +{ + featureList.push_back(std::make_pair(prefix + " Small Zone Emphasis", features.SmallZoneEmphasis)); + featureList.push_back(std::make_pair(prefix + " Large Zone Emphasis", features.LargeZoneEmphasis)); + featureList.push_back(std::make_pair(prefix + " Low Grey Level Emphasis", features.LowGreyLevelEmphasis)); + featureList.push_back(std::make_pair(prefix + " High Grey Level Emphasis", features.HighGreyLevelEmphasis)); + featureList.push_back(std::make_pair(prefix + " Small Zone Low Grey LEvel Emphasis", features.SmallZoneLowGreyLevelEmphasis)); + featureList.push_back(std::make_pair(prefix + " Small Zone High Grey LEvel Emphasis", features.SmallZoneHighGreyLevelEmphasis)); + featureList.push_back(std::make_pair(prefix + " Large Zone Low Grey Level Emphasis", features.LargeZoneLowGreyLevelEmphasis)); + featureList.push_back(std::make_pair(prefix + " Large Zone High Grey Level Emphasis", features.LargeZoneHighGreyLevelEmphasis)); + featureList.push_back(std::make_pair(prefix + " Grey Level Non-Uniformity", features.GreyLevelNonUniformity)); + featureList.push_back(std::make_pair(prefix + " Grey Level Non-Uniformity Normalized", features.GreyLevelNonUniformityNormalized)); + featureList.push_back(std::make_pair(prefix + " Zone Size Non-Uniformity", features.ZoneSizeNonUniformity)); + featureList.push_back(std::make_pair(prefix + " Zone Size Non-Uniformity Normalized", features.ZoneSizeNoneUniformityNormalized)); + featureList.push_back(std::make_pair(prefix + " Zone Percentage", features.ZonePercentage)); + featureList.push_back(std::make_pair(prefix + " Grey Level Mean", features.GreyLevelMean)); + featureList.push_back(std::make_pair(prefix + " Grey Level Variance", features.GreyLevelVariance)); + featureList.push_back(std::make_pair(prefix + " Zone Size Mean", features.ZoneSizeMean)); + featureList.push_back(std::make_pair(prefix + " Zone Size Variance", features.ZoneSizeVariance)); + featureList.push_back(std::make_pair(prefix + " Zone Size Entropy", features.ZoneSizeEntropy)); +} + +static +void CalculateMeanAndStdDevFeatures(std::vector featureList, + mitk::GreyLevelSizeZoneFeatures &meanFeature, + mitk::GreyLevelSizeZoneFeatures &stdFeature) +{ +#define ADDFEATURE(a) meanFeature.a += featureList[i].a;stdFeature.a += featureList[i].a*featureList[i].a +#define CALCVARIANCE(a) stdFeature.a =sqrt(stdFeature.a - meanFeature.a*meanFeature.a) + + for (std::size_t i = 0; i < featureList.size(); ++i) + { + ADDFEATURE(SmallZoneEmphasis); + ADDFEATURE(LargeZoneEmphasis); + ADDFEATURE(LowGreyLevelEmphasis); + ADDFEATURE(HighGreyLevelEmphasis); + ADDFEATURE(SmallZoneLowGreyLevelEmphasis); + ADDFEATURE(SmallZoneHighGreyLevelEmphasis); + ADDFEATURE(LargeZoneHighGreyLevelEmphasis); + ADDFEATURE(GreyLevelNonUniformity); + ADDFEATURE(GreyLevelNonUniformityNormalized); + ADDFEATURE(ZoneSizeNoneUniformityNormalized); + ADDFEATURE(ZonePercentage); + ADDFEATURE(GreyLevelVariance); + ADDFEATURE(ZoneSizeVariance); + ADDFEATURE(ZoneSizeEntropy); + } + NormalizeMatrixFeature(meanFeature, featureList.size()); + NormalizeMatrixFeature(stdFeature, featureList.size()); + + CALCVARIANCE(SmallZoneEmphasis); + CALCVARIANCE(LargeZoneEmphasis); + CALCVARIANCE(LowGreyLevelEmphasis); + CALCVARIANCE(HighGreyLevelEmphasis); + CALCVARIANCE(SmallZoneLowGreyLevelEmphasis); + CALCVARIANCE(SmallZoneHighGreyLevelEmphasis); + CALCVARIANCE(LargeZoneHighGreyLevelEmphasis); + CALCVARIANCE(GreyLevelNonUniformity); + CALCVARIANCE(GreyLevelNonUniformityNormalized); + CALCVARIANCE(ZoneSizeNonUniformity); + CALCVARIANCE(ZoneSizeNoneUniformityNormalized); + CALCVARIANCE(ZonePercentage); + CALCVARIANCE(GreyLevelVariance); + CALCVARIANCE(ZoneSizeVariance); + CALCVARIANCE(ZoneSizeEntropy); + +#undef ADDFEATURE +#undef CALCVARIANCE +} + +static +void NormalizeMatrixFeature(mitk::GreyLevelSizeZoneFeatures &features, +std::size_t number) +{ + features.SmallZoneEmphasis = features.SmallZoneEmphasis / number; + features.LargeZoneEmphasis = features.LargeZoneEmphasis / number; + features.LowGreyLevelEmphasis = features.LowGreyLevelEmphasis / number; + features.HighGreyLevelEmphasis = features.HighGreyLevelEmphasis / number; + features.SmallZoneLowGreyLevelEmphasis = features.SmallZoneLowGreyLevelEmphasis / number; + features.SmallZoneHighGreyLevelEmphasis = features.SmallZoneHighGreyLevelEmphasis / number; + features.LargeZoneLowGreyLevelEmphasis = features.LargeZoneLowGreyLevelEmphasis / number; + features.LargeZoneHighGreyLevelEmphasis = features.LargeZoneHighGreyLevelEmphasis / number; + features.GreyLevelNonUniformity = features.GreyLevelNonUniformity / number; + features.GreyLevelNonUniformityNormalized = features.GreyLevelNonUniformityNormalized / number; + features.ZoneSizeNonUniformity = features.ZoneSizeNonUniformity / number; + features.ZoneSizeNoneUniformityNormalized = features.ZoneSizeNoneUniformityNormalized / number; + features.ZonePercentage = features.ZonePercentage / number; + features.GreyLevelVariance = features.GreyLevelVariance / number; + features.ZoneSizeVariance = features.ZoneSizeVariance / number; + features.ZoneSizeEntropy = features.ZoneSizeEntropy / number; +} + + mitk::GIFGreyLevelSizeZone::GIFGreyLevelSizeZone() : + m_Range(1.0), m_Bins(128) +{ + SetShortName("glsz"); + SetLongName("sizezone"); +} + +mitk::GIFGreyLevelSizeZone::FeatureListType mitk::GIFGreyLevelSizeZone::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) +{ + FeatureListType featureList; + + GIFGreyLevelSizeZoneConfiguration config; + config.direction = GetDirection(); + config.range = m_Range; + + config.MinimumIntensity = GetMinimumIntensity(); + config.MaximumIntensity = GetMaximumIntensity(); + config.UseMinimumIntensity = GetUseMinimumIntensity(); + config.UseMaximumIntensity = GetUseMaximumIntensity(); + config.Bins = GetBins(); + + AccessByItk_3(image, CalculateGreyLevelSizeZoneFeatures, mask, featureList, config); + + return featureList; +} + +mitk::GIFGreyLevelSizeZone::FeatureNameListType mitk::GIFGreyLevelSizeZone::GetFeatureNames() +{ + FeatureNameListType featureList; + return featureList; +} + + + + +void mitk::GIFGreyLevelSizeZone::AddArguments(mitkCommandLineParser &parser) +{ + std::string name = GetOptionPrefix(); + + parser.addArgument(GetLongName(), name, mitkCommandLineParser::String, "Use Grey Level Size Zone", "Calculates the size zone based features.", us::Any()); + parser.addArgument(name+"::range", name+"::range", mitkCommandLineParser::String, "Cooc 2 Range", "Define the range that is used (Semicolon-separated)", us::Any()); + parser.addArgument(name + "::bins", name + "::bins", mitkCommandLineParser::String, "Cooc 2 Number of Bins", "Define the number of bins that is used ", us::Any()); +} + +void +mitk::GIFGreyLevelSizeZone::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &, const Image::Pointer &maskNoNAN, FeatureListType &featureList) +{ + auto parsedArgs = GetParameter(); + std::string name = GetOptionPrefix(); + + if (parsedArgs.count(GetLongName())) + { + std::vector ranges; + if (parsedArgs.count(name + "::range")) + { + ranges = SplitDouble(parsedArgs[name + "::range"].ToString(), ';'); + } + else + { + ranges.push_back(1); + } + if (parsedArgs.count(name + "::bins")) + { + auto bins = SplitDouble(parsedArgs[name + "::bins"].ToString(), ';')[0]; + this->SetBins(bins); + } + + for (std::size_t i = 0; i < ranges.size(); ++i) + { + MITK_INFO << "Start calculating coocurence with range " << ranges[i] << "...."; + this->SetRange(ranges[i]); + auto localResults = this->CalculateFeatures(feature, maskNoNAN); + featureList.insert(featureList.end(), localResults.begin(), localResults.end()); + MITK_INFO << "Finished calculating coocurence with range " << ranges[i] << "...."; + } + } + +} + diff --git a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp index 9c39868704..6d9a30f047 100644 --- a/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp +++ b/Modules/Classification/CLUtilities/src/GlobalImageFeatures/mitkGIFNeighbouringGreyLevelDependenceFeatures.cpp @@ -1,404 +1,408 @@ #include // MITK #include #include #include // ITK #include #include #include #include // STL #include static void MatrixFeaturesTo(mitk::NGLDMMatrixFeatures features, std::string prefix, mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType &featureList); mitk::NGLDMMatrixHolder::NGLDMMatrixHolder(double min, double max, int number, int depenence) : m_MinimumRange(min), m_MaximumRange(max), m_Stepsize(0), m_NumberOfDependences(depenence), m_NumberOfBins(number), m_NeighbourhoodSize(1), m_NumberOfNeighbourVoxels(0), m_NumberOfDependenceNeighbourVoxels(0), m_NumberOfNeighbourhoods(0), m_NumberOfCompleteNeighbourhoods(0) { m_Matrix.resize(number, depenence); m_Matrix.fill(0); m_Stepsize = (max - min) / (number); } int mitk::NGLDMMatrixHolder::IntensityToIndex(double intensity) { return std::floor((intensity - m_MinimumRange) / m_Stepsize); } double mitk::NGLDMMatrixHolder::IndexToMinIntensity(int index) { return m_MinimumRange + index * m_Stepsize; } double mitk::NGLDMMatrixHolder::IndexToMeanIntensity(int index) { return m_MinimumRange + (index+0.5) * m_Stepsize; } double mitk::NGLDMMatrixHolder::IndexToMaxIntensity(int index) { return m_MinimumRange + (index + 1) * m_Stepsize; } template void CalculateNGLDMMatrix(itk::Image* itkImage, itk::Image* mask, int alpha, int range, unsigned int direction, mitk::NGLDMMatrixHolder &holder) { typedef itk::Image ImageType; typedef itk::Image MaskImageType; typedef itk::NeighborhoodIterator ShapeIterType; typedef itk::NeighborhoodIterator ShapeMaskIterType; holder.m_NumberOfCompleteNeighbourhoods = 0; holder.m_NumberOfNeighbourhoods = 0; holder.m_NumberOfNeighbourVoxels = 0; holder.m_NumberOfDependenceNeighbourVoxels = 0; itk::Size radius; radius.Fill(range); - if ((direction > 1) && (direction +2 1) && (direction - 2 GetLargestPossibleRegion()); ShapeMaskIterType maskIter(radius, mask, mask->GetLargestPossibleRegion()); auto region = mask->GetLargestPossibleRegion(); auto center = imageIter.Size() / 2; auto iterSize = imageIter.Size(); holder.m_NeighbourhoodSize = iterSize-1; while (!maskIter.IsAtEnd()) { int sameValues = 0; bool completeNeighbourhood = true; int i = holder.IntensityToIndex(imageIter.GetCenterPixel()); - if (imageIter.GetCenterPixel() != imageIter.GetCenterPixel()) + if ((imageIter.GetCenterPixel() != imageIter.GetCenterPixel()) || + (maskIter.GetCenterPixel() < 1)) { ++imageIter; ++maskIter; continue; } for (unsigned int position = 0; position < iterSize; ++position) { - if ((position == center) || - ( ! region.IsInside(maskIter.GetIndex(position)))) + if (position == center) + { + continue; + } + if ( ! region.IsInside(maskIter.GetIndex(position))) { completeNeighbourhood = false; continue; } bool isInBounds; auto jIntensity = imageIter.GetPixel(position, isInBounds); auto jMask = maskIter.GetPixel(position, isInBounds); - if (jMask < 0 || (jIntensity != jIntensity) || ( ! isInBounds)) + if (jMask < 1 || (jIntensity != jIntensity) || ( ! isInBounds)) { completeNeighbourhood = false; continue; } int j = holder.IntensityToIndex(jIntensity); holder.m_NumberOfNeighbourVoxels += 1; if (std::abs(i - j) <= alpha) { holder.m_NumberOfDependenceNeighbourVoxels += 1; ++sameValues; } } holder.m_Matrix(i, sameValues) += 1; holder.m_NumberOfNeighbourhoods += 1; if (completeNeighbourhood) { holder.m_NumberOfCompleteNeighbourhoods += 1; } ++imageIter; ++maskIter; } } void LocalCalculateFeatures( mitk::NGLDMMatrixHolder &holder, mitk::NGLDMMatrixFeatures & results ) { auto sijMatrix = holder.m_Matrix; auto piMatrix = holder.m_Matrix; auto pjMatrix = holder.m_Matrix; // double Ng = holder.m_NumberOfBins; // int NgSize = holder.m_NumberOfBins; double Ns = sijMatrix.sum(); piMatrix.rowwise().normalize(); pjMatrix.colwise().normalize(); for (int i = 0; i < holder.m_NumberOfBins; ++i) { double sj = 0; for (int j = 0; j < holder.m_NumberOfDependences; ++j) { double iInt = holder.IndexToMeanIntensity(i); double sij = sijMatrix(i, j); double k = j+1; double pij = sij / Ns; results.LowDependenceEmphasis += sij / k / k; results.HighDependenceEmphasis += sij * k*k; if (iInt != 0) { results.LowGreyLevelCountEmphasis += sij / iInt / iInt; } results.HighGreyLevelCountEmphasis += sij * iInt*iInt; if (iInt != 0) { results.LowDependenceLowGreyLevelEmphasis += sij / k / k / iInt / iInt; } results.LowDependenceHighGreyLevelEmphasis += sij * iInt*iInt / k / k; if (iInt != 0) { results.HighDependenceLowGreyLevelEmphasis += sij *k * k / iInt / iInt; } results.HighDependenceHighGreyLevelEmphasis += sij * k*k*iInt*iInt; results.MeanGreyLevelCount += iInt * pij; results.MeanDependenceCount += k * pij; if (pij > 0) { results.DependenceCountEntropy -= pij * std::log(pij) / std::log(2); } + results.DependenceCountEnergy += pij*pij; sj += sij; } results.GreyLevelNonUniformity += sj*sj; results.GreyLevelNonUniformityNormalised += sj*sj; } for (int j = 0; j < holder.m_NumberOfDependences; ++j) { double si = 0; for (int i = 0; i < holder.m_NumberOfBins; ++i) { double sij = sijMatrix(i, j); si += sij; } results.DependenceCountNonUniformity += si*si; results.DependenceCountNonUniformityNormalised += si*si; } for (int i = 0; i < holder.m_NumberOfBins; ++i) { for (int j = 0; j < holder.m_NumberOfDependences; ++j) { double iInt = holder.IndexToMeanIntensity(i); double sij = sijMatrix(i, j); double k = j + 1; double pij = sij / Ns; results.GreyLevelVariance += (iInt - results.MeanGreyLevelCount)* (iInt - results.MeanGreyLevelCount) * pij; results.DependenceCountVariance += (k - results.MeanDependenceCount)* (k - results.MeanDependenceCount) * pij; } } results.LowDependenceEmphasis /= Ns; results.HighDependenceEmphasis /= Ns; results.LowGreyLevelCountEmphasis /= Ns; results.HighGreyLevelCountEmphasis /= Ns; results.LowDependenceLowGreyLevelEmphasis /= Ns; results.LowDependenceHighGreyLevelEmphasis /= Ns; results.HighDependenceLowGreyLevelEmphasis /= Ns; results.HighDependenceHighGreyLevelEmphasis /= Ns; results.GreyLevelNonUniformity /= Ns; results.GreyLevelNonUniformityNormalised /= (Ns*Ns); results.DependenceCountNonUniformity /= Ns; results.DependenceCountNonUniformityNormalised /= (Ns*Ns); results.DependenceCountPercentage = 1; results.ExpectedNeighbourhoodSize = holder.m_NeighbourhoodSize; results.AverageNeighbourhoodSize = holder.m_NumberOfNeighbourVoxels / (1.0 * holder.m_NumberOfNeighbourhoods); results.AverageIncompleteNeighbourhoodSize = (holder.m_NumberOfNeighbourVoxels - holder.m_NumberOfCompleteNeighbourhoods* holder.m_NeighbourhoodSize) / (1.0 * (holder.m_NumberOfNeighbourhoods - holder.m_NumberOfCompleteNeighbourhoods)); - results.PercentageOfCompleteNeighbourhoods = holder.m_NumberOfCompleteNeighbourhoods / (1.0 * holder.m_NumberOfNeighbourhoods); + results.PercentageOfCompleteNeighbourhoods = (1.0*holder.m_NumberOfCompleteNeighbourhoods) / (1.0 * holder.m_NumberOfNeighbourhoods); results.PercentageOfDependenceNeighbours = holder.m_NumberOfDependenceNeighbourVoxels / (1.0 * holder.m_NumberOfNeighbourVoxels); } template void CalculateCoocurenceFeatures(itk::Image* itkImage, mitk::Image::Pointer mask, mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType & featureList, mitk::GIFNeighbouringGreyLevelDependenceFeature::GIFNeighbouringGreyLevelDependenceFeatureConfiguration config) { typedef itk::Image ImageType; typedef itk::Image MaskType; typedef itk::MinimumMaximumImageCalculator MinMaxComputerType; /////////////////////////////////////////////////////////////////////////////////////////////// typename MinMaxComputerType::Pointer minMaxComputer = MinMaxComputerType::New(); minMaxComputer->SetImage(itkImage); minMaxComputer->Compute(); double rangeMin = -0.5 + minMaxComputer->GetMinimum(); double rangeMax = 0.5 + minMaxComputer->GetMaximum(); if (config.UseMinimumIntensity) rangeMin = config.MinimumIntensity; if (config.UseMaximumIntensity) rangeMax = config.MaximumIntensity; // Define Range int numberOfBins = config.Bins; typename MaskType::Pointer maskImage = MaskType::New(); mitk::CastToItkImage(mask, maskImage); std::vector resultVector; mitk::NGLDMMatrixHolder holderOverall(rangeMin, rangeMax, numberOfBins,37); mitk::NGLDMMatrixFeatures overallFeature; CalculateNGLDMMatrix(itkImage, maskImage, config.alpha, config.range, config.direction, holderOverall); LocalCalculateFeatures(holderOverall, overallFeature); std::ostringstream ss; ss << config.range; std::string strRange = ss.str(); MatrixFeaturesTo(overallFeature, "NGLDM (" + strRange + ") overall", featureList); } static void MatrixFeaturesTo(mitk::NGLDMMatrixFeatures features, std::string prefix, mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType &featureList) { featureList.push_back(std::make_pair(prefix + " Low Dependence Emphasis", features.LowDependenceEmphasis)); featureList.push_back(std::make_pair(prefix + " High Dependence Emphasis", features.HighDependenceEmphasis)); featureList.push_back(std::make_pair(prefix + " Low Grey Level Count Emphasis", features.LowGreyLevelCountEmphasis)); featureList.push_back(std::make_pair(prefix + " High Grey Level Count Emphasis", features.HighGreyLevelCountEmphasis)); featureList.push_back(std::make_pair(prefix + " Low Dependence Low Grey Level Emphasis", features.LowDependenceLowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + " Low Dependence High Grey Level Emphasis", features.LowDependenceHighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + " High Dependence Low Grey Level Emphasis", features.HighDependenceLowGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + " High Dependence High Grey Level Emphasis", features.HighDependenceHighGreyLevelEmphasis)); featureList.push_back(std::make_pair(prefix + " Grey Level Non-Uniformity", features.GreyLevelNonUniformity)); featureList.push_back(std::make_pair(prefix + " Grey Level Non-Uniformity Normalised", features.GreyLevelNonUniformityNormalised)); featureList.push_back(std::make_pair(prefix + " Dependence Count Non-Uniformity", features.DependenceCountNonUniformity)); featureList.push_back(std::make_pair(prefix + " Dependence Count Non-Uniformtiy Normalised", features.DependenceCountNonUniformityNormalised)); featureList.push_back(std::make_pair(prefix + " Dependence Count Percentage", features.DependenceCountPercentage)); featureList.push_back(std::make_pair(prefix + " Grey Level Mean", features.MeanGreyLevelCount)); featureList.push_back(std::make_pair(prefix + " Grey Level Variance", features.GreyLevelVariance)); featureList.push_back(std::make_pair(prefix + " Dependence Count Mean", features.MeanDependenceCount)); featureList.push_back(std::make_pair(prefix + " Dependence Count Variance", features.DependenceCountVariance)); featureList.push_back(std::make_pair(prefix + " Dependence Count Entropy", features.DependenceCountEntropy)); + featureList.push_back(std::make_pair(prefix + " Dependence Count Energy", features.DependenceCountEnergy)); featureList.push_back(std::make_pair(prefix + " Expected Neighbourhood Size", features.ExpectedNeighbourhoodSize)); featureList.push_back(std::make_pair(prefix + " Average Neighbourhood Size", features.AverageNeighbourhoodSize)); featureList.push_back(std::make_pair(prefix + " Average Incomplete Neighbourhood Size", features.AverageIncompleteNeighbourhoodSize)); featureList.push_back(std::make_pair(prefix + " Percentage of complete Neighbourhoods", features.PercentageOfCompleteNeighbourhoods)); featureList.push_back(std::make_pair(prefix + " Percentage of Dependence Neighbour Voxels", features.PercentageOfDependenceNeighbours)); } mitk::GIFNeighbouringGreyLevelDependenceFeature::GIFNeighbouringGreyLevelDependenceFeature() : m_Range(1.0), m_Bins(6) { SetShortName("ngldm"); SetLongName("ngldm"); } mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureListType mitk::GIFNeighbouringGreyLevelDependenceFeature::CalculateFeatures(const Image::Pointer & image, const Image::Pointer &mask) { FeatureListType featureList; GIFNeighbouringGreyLevelDependenceFeatureConfiguration config; config.direction = GetDirection(); config.range = m_Range; config.alpha = 0; config.MinimumIntensity = GetMinimumIntensity(); config.MaximumIntensity = GetMaximumIntensity(); config.UseMinimumIntensity = GetUseMinimumIntensity(); config.UseMaximumIntensity = GetUseMaximumIntensity(); config.Bins = GetBins(); AccessByItk_3(image, CalculateCoocurenceFeatures, mask, featureList,config); return featureList; } mitk::GIFNeighbouringGreyLevelDependenceFeature::FeatureNameListType mitk::GIFNeighbouringGreyLevelDependenceFeature::GetFeatureNames() { FeatureNameListType featureList; - featureList.push_back("co-occ. Energy Means"); - featureList.push_back("co-occ. Energy Std."); return featureList; } void mitk::GIFNeighbouringGreyLevelDependenceFeature::AddArguments(mitkCommandLineParser &parser) { std::string name = GetOptionPrefix(); parser.addArgument(GetLongName(), name, mitkCommandLineParser::String, "Calculate Neighbouring grey level dependence based features", "Calculate Neighbouring grey level dependence based features", us::Any()); parser.addArgument(name + "::range", name + "::range", mitkCommandLineParser::String, "NGLD Range", "Define the range that is used (Semicolon-separated)", us::Any()); parser.addArgument(name + "::bins", name + "::bins", mitkCommandLineParser::String, "NGLD Number of Bins", "Define the number of bins that is used ", us::Any()); } void mitk::GIFNeighbouringGreyLevelDependenceFeature::CalculateFeaturesUsingParameters(const Image::Pointer & feature, const Image::Pointer &, const Image::Pointer &maskNoNAN, FeatureListType &featureList) { auto parsedArgs = GetParameter(); std::string name = GetOptionPrefix(); if (parsedArgs.count(GetLongName())) { std::vector ranges; if (parsedArgs.count(name + "::range")) { ranges = SplitDouble(parsedArgs[name + "::range"].ToString(), ';'); } else { ranges.push_back(1); } if (parsedArgs.count(name + "::bins")) { auto bins = SplitDouble(parsedArgs[name + "::bins"].ToString(), ';')[0]; this->SetBins(bins); } for (std::size_t i = 0; i < ranges.size(); ++i) { - MITK_INFO << "Start calculating coocurence with range " << ranges[i] << "...."; + MITK_INFO << "Start calculating NGLDM with range " << ranges[i] << "...."; this->SetRange(ranges[i]); auto localResults = this->CalculateFeatures(feature, maskNoNAN); featureList.insert(featureList.end(), localResults.begin(), localResults.end()); - MITK_INFO << "Finished calculating coocurence with range " << ranges[i] << "...."; + MITK_INFO << "Finished calculating NGLDM with range " << ranges[i] << "...."; } } }