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;
}
示例#3
0
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();
}