ANIMA  4.0
animaDiceMeasure.cxx
Go to the documentation of this file.
2 #include <itkImageRegionConstIterator.h>
3 #include <tclap/CmdLine.h>
4 #include <fstream>
5 
6 int main(int argc, char * *argv)
7 {
8  TCLAP::CmdLine cmd("INRIA / IRISA - VisAGeS/Empenn Team", ' ', ANIMA_VERSION);
9 
10  TCLAP::ValueArg <std::string> refArg("r", "reffile", "Reference segmentations", true, "", "reference image", cmd);
11  TCLAP::ValueArg <std::string> testArg("t", "testfile", "Test segmentations", true, "", "test image", cmd);
12 
13  TCLAP::ValueArg <unsigned int> minNumPixelsRefArg("m", "min-card", "Minimal number of pixels in each reference label area", false, 0, "minimal label size", cmd);
14  TCLAP::SwitchArg totalOverlapArg("T", "total-overlap", "Compute total overlap measure as in Klein et al 2009", cmd, false);
15  TCLAP::SwitchArg jacArg("J", "jaccard", "Compute Jaccard similarity instead of Dice", cmd, false);
16  TCLAP::SwitchArg xlsArg("X", "xlsmode", "Output formatted to be include in a Excel readable text file", cmd, false);
17 
18  TCLAP::ValueArg <std::string> fileArg("o", "out-txt", "Output stored into a file", false, "", "Output file", cmd);
19 
20  try
21  {
22  cmd.parse(argc, argv);
23  }
24  catch (TCLAP::ArgException& e)
25  {
26  std::cerr << "Error: " << e.error() << "for argument " << e.argId() << std::endl;
27  return EXIT_FAILURE;
28  }
29 
30  typedef itk::Image <unsigned short, 3> ImageType;
31  typedef itk::ImageFileReader <ImageType> ImageReaderType;
32  typedef itk::ImageRegionConstIterator <ImageType> ImageIteratorType;
33 
34  ImageType::Pointer refImage = anima::readImage <ImageType> (refArg.getValue());
35 
36  ImageIteratorType refIt (refImage, refImage->GetLargestPossibleRegion());
37 
38  std::vector <unsigned int> usefulLabels;
39 
40  while (!refIt.IsAtEnd())
41  {
42  if (refIt.Get() != 0)
43  {
44  bool isAlreadyIn = false;
45  for (unsigned int i = 0; i < usefulLabels.size(); ++i)
46  {
47  if (refIt.Get() == usefulLabels[i])
48  {
49  isAlreadyIn = true;
50  break;
51  }
52  }
53 
54  if (!isAlreadyIn)
55  usefulLabels.push_back(refIt.Get());
56  }
57 
58  ++refIt;
59  }
60 
61  std::sort(usefulLabels.begin(), usefulLabels.end());
62 
63  std::map <unsigned int, unsigned int> labelBackMap;
64 
65  labelBackMap[0] = 0;
66  for (unsigned int i = 0; i < usefulLabels.size(); ++i)
67  {
68  labelBackMap[usefulLabels[i]] = i+1;
69  }
70 
71  refIt.GoToBegin();
72 
73  ImageType::Pointer testImage = anima::readImage <ImageType> (testArg.getValue());
74  ImageIteratorType testIt (testImage, testImage->GetLargestPossibleRegion());
75 
76  unsigned int numLabels = usefulLabels.size();
77  std::vector <double> cardRef(numLabels+1, 0), cardTest(numLabels+1, 0), cardInter(numLabels+1, 0);
78 
79  while(!testIt.IsAtEnd())
80  {
81  unsigned int testVal = testIt.Get();
82  unsigned int refVal = refIt.Get();
83 
84  cardTest[labelBackMap[testVal]]++;
85  cardRef[labelBackMap[refVal]]++;
86 
87  if (testVal == refVal)
88  cardInter[labelBackMap[testVal]]++;
89 
90  ++testIt;
91  ++refIt;
92  }
93 
94 
96  // Select and open output
97  std::fstream oStremFileOut;
98  std::ostream *poOutStreamForResults = &std::cout;
99  bool bFileResFailed = false;
100 
101  if (fileArg.getValue() != "")
102  {
103  oStremFileOut.open(fileArg.getValue().c_str(), std::ios::out | std::ios::trunc);
104  if(!oStremFileOut.is_open())
105  {
106  std::cerr << "Can not open file: " << fileArg.getValue() << "to store score" << std::endl;
107  bFileResFailed = true;
108  }
109  else
110  {
111  poOutStreamForResults = &oStremFileOut;
112  }
113  }
114  std::ostream &roOutStreamForResults = *poOutStreamForResults;
115 
117  // Computation
118  if (totalOverlapArg.isSet())
119  {
120  double score = 0;
121 
122  unsigned int numUsedLabels = 0;
123  for (unsigned int i = 1; i <= numLabels; ++i)
124  {
125  if (cardRef[i] > minNumPixelsRefArg.getValue())
126  {
127  score += cardInter[i] / cardRef[i];
128  ++numUsedLabels;
129  }
130  }
131 
132  if (numUsedLabels > 0)
133  score /= numUsedLabels;
134 
135 
136  if (xlsArg.isSet())
137  roOutStreamForResults << score << std::endl;
138  else
139  roOutStreamForResults << "Total overlap score: " << score << std::endl;
140  }
141  else
142  {
143  for (unsigned int i = 1; i <= numLabels; ++i)
144  {
145  if (cardRef[i] <= minNumPixelsRefArg.getValue())
146  continue;
147 
148  double score = 2*cardInter[i]/(cardRef[i] + cardTest[i]);
149 
150  if (jacArg.isSet())
151  score = score/(2.0 - score);
152 
153  if (xlsArg.isSet())
154  {
155  roOutStreamForResults << score;
156  if (i < numLabels)
157  roOutStreamForResults << ", " << std::flush;
158  else
159  roOutStreamForResults << std::endl;
160  }
161  else
162  roOutStreamForResults << "Label " << usefulLabels[i-1] << ": " << score << std::endl;
163  }
164  }
165 
166 
168  // Close output
169  if (oStremFileOut.is_open())
170  oStremFileOut.close();
171 
172  if (bFileResFailed)
173  return EXIT_FAILURE;
174 
175  return EXIT_SUCCESS;
176 }
177 
int main(int argc, char **argv)