static ImageList LoadPreprocessedFiles(FileList files) { ImageList images; for (unsigned int i=0; i < files.size() ; ++i) { images.push_back(mitk::IOUtil::LoadImage(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("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("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<string, us::Any> 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<string> (parsedArgs["input"]) + "/"; } if (parsedArgs.count("output") || parsedArgs.count("o") ) { outputFile = us::any_cast<string> (parsedArgs["output"]); } int skip = 0; int interval = 1; float opacity = .3; if (parsedArgs.count("skip") || parsedArgs.count("k") ) { skip = us::any_cast<int>(parsedArgs["skip"]); } if (parsedArgs.count("interval") || parsedArgs.count("n") ) { interval = us::any_cast<int>(parsedArgs["interval"]); } if (parsedArgs.count("opacity") || parsedArgs.count("c") ) { opacity = us::any_cast<float>(parsedArgs["opacity"]); } FileList morphFiles; FileList segFiles; std::string refPattern; std::string segPattern; if (parsedArgs.count("morphology") || parsedArgs.count("m") ) { refPattern = us::any_cast<std::string>(parsedArgs["morphology"]); } else return EXIT_FAILURE; if (parsedArgs.count("segmentation") || parsedArgs.count("s") ) { segPattern = us::any_cast<std::string>(parsedArgs["segmentation"]); } bool blank = false; if (parsedArgs.count("blanked") || parsedArgs.count("b")) { blank = true; } /// END Parsing CL Options typedef itk::Image<RGBPixelType, 2> OutputImageType; typedef itk::Image<RGBPixelType, 3> 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<OutputImageType, OutputImageType>::Pointer tileFilter = itk::TileImageFilter<OutputImageType, OutputImageType>::New(); itk::FixedArray< unsigned int, 2 > 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<string>(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 = NULL; 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<InputPixelType,3> 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 != NULL) { 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< InputImageType > DuplicatorType; DuplicatorType::Pointer duplicator = DuplicatorType::New(); duplicator->SetInputImage(itkImage); duplicator->Update(); itkImage2 = duplicator->GetOutput(); itk::Image<RGBPixelType,2>::Pointer extractedSlice = itk::Image<RGBPixelType,2>::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< OutputImageType > 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; }
void IsisMain() { // Get the list of cubes to process FileList imageList; UserInterface &ui = Application::GetUserInterface(); imageList.Read(ui.GetFilename("FROMLIST")); // Read to list if one was entered FileList outList; if (ui.WasEntered("TOLIST")) { outList.Read(ui.GetFilename("TOLIST")); } // Check for user input errors and return the file list sorted by CCD numbers ErrorCheck(imageList, outList); // Adds statistics for whole and side regions of every cube for (int img=0; img<(int)imageList.size(); img++) { g_s.Reset(); g_sl.Reset(); g_sr.Reset(); iString maxCube ((int)imageList.size()); iString curCube (img+1); ProcessByLine p; p.Progress()->SetText("Gathering Statistics for Cube " + curCube + " of " + maxCube); CubeAttributeInput att; const std::string inp = imageList[img]; p.SetInputCube(inp, att); p.StartProcess(GatherStatistics); p.EndProcess(); g_allStats.push_back(g_s); g_leftStats.push_back(g_sl); g_rightStats.push_back(g_sr); } // Initialize the object that will calculate the gains and offsets g_oNorm = new OverlapNormalization(g_allStats); // Add the known overlaps between two cubes, and apply a weight to each // overlap equal the number of pixels in the overlapping area for (int i=0; i<(int)imageList.size()-1; i++) { int j = i+1; g_oNorm->AddOverlap(g_rightStats[i], i, g_leftStats[j], j, g_rightStats[i].ValidPixels()); } // Read in and then set the holdlist FileList holdList; holdList.Read(ui.GetFilename("HOLD")); for (unsigned i=0; i<holdList.size(); i++) { int index = -1; for (unsigned j=0; j<imageList.size(); j++) { std::string curName = imageList.at(j); if (curName.compare(holdList[i]) == 0) { index = j; g_oNorm->AddHold(index); } } } // Attempt to solve the least squares equation g_oNorm->Solve(OverlapNormalization::Both); // Apply correction to the cubes if desired bool applyopt = ui.GetBoolean("APPLY"); if (applyopt) { // Loop through correcting the gains and offsets by line for every cube for (int img=0; img<(int)imageList.size(); img++) { g_imageNum = img; ProcessByLine p; iString max_cube ((int)imageList.size()); iString cur_cube (img+1); p.Progress()->SetText("Equalizing Cube " + cur_cube + " of " + max_cube); CubeAttributeInput att; const std::string inp = imageList[img]; Cube *icube = p.SetInputCube(inp, att); Filename file = imageList[img]; // Establish the output file depending upon whether or not a to list // was entered std::string out; if (ui.WasEntered("TOLIST")) { out = outList[img]; } else { Filename file = imageList[img]; out = file.Path() + "/" + file.Basename() + ".equ." + file.Extension(); } CubeAttributeOutput outAtt; p.SetOutputCube(out,outAtt,icube->Samples(),icube->Lines(),icube->Bands()); p.StartProcess(Apply); p.EndProcess(); } } // Setup the output text file if the user requested one if (ui.WasEntered("OUTSTATS")) { std::string out = Filename(ui.GetFilename("OUTSTATS")).Expanded(); std::ofstream os; os.open(out.c_str(),std::ios::app); // Get statistics for each cube with PVL Pvl p; PvlObject equ("EqualizationInformation"); for (int img=0; img<(int)imageList.size(); img++) { std::string cur = imageList[img]; PvlGroup a("Adjustment"); a += PvlKeyword("FileName", cur); a += PvlKeyword("Average", g_oNorm->Average(img)); a += PvlKeyword("Base", g_oNorm->Offset(img)); a += PvlKeyword("Multiplier", g_oNorm->Gain(img)); equ.AddGroup(a); } p.AddObject(equ); os << p << std::endl; } PvlGroup results ("Results"); for (int img=0; img<(int)imageList.size(); img++) { results += PvlKeyword("FileName", imageList[img]); results += PvlKeyword("Average", g_oNorm->Average(img)); results += PvlKeyword("Base", g_oNorm->Offset(img)); results += PvlKeyword("Multiplier", g_oNorm->Gain(img)); } Application::Log(results); // Clean-up for batch list runs delete g_oNorm; g_oNorm = NULL; g_allStats.clear(); g_leftStats.clear(); g_rightStats.clear(); }