Medical Imaging Interaction Toolkit  2018.4.99-1640525a
Medical Imaging Interaction Toolkit
mitkAbstractGlobalImageFeature.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 
15 #include <mitkImageCast.h>
16 #include <mitkITKImageImport.h>
17 #include <iterator>
18 
19 static void
21  int direction,
22  std::vector<mitk::Image::Pointer> &imageVector,
23  std::vector<mitk::Image::Pointer> &maskVector)
24 {
25  typedef itk::Image< double, 2 > FloatImage2DType;
26  typedef itk::Image< unsigned short, 2 > MaskImage2DType;
27  typedef itk::Image< double, 3 > FloatImageType;
28  typedef itk::Image< unsigned short, 3 > MaskImageType;
29 
30  FloatImageType::Pointer itkFloat = FloatImageType::New();
31  MaskImageType::Pointer itkMask = MaskImageType::New();
32  mitk::CastToItkImage(mask, itkMask);
33  mitk::CastToItkImage(image, itkFloat);
34 
35  int idxA, idxB, idxC;
36  switch (direction)
37  {
38  case 0:
39  idxA = 1; idxB = 2; idxC = 0;
40  break;
41  case 1:
42  idxA = 0; idxB = 2; idxC = 1;
43  break;
44  case 2:
45  idxA = 0; idxB = 1; idxC = 2;
46  break;
47  default:
48  idxA = 1; idxB = 2; idxC = 0;
49  break;
50  }
51 
52  auto imageSize = image->GetLargestPossibleRegion().GetSize();
53  FloatImageType::IndexType index3D;
54  FloatImage2DType::IndexType index2D;
55  FloatImage2DType::SpacingType spacing2D;
56  spacing2D[0] = itkFloat->GetSpacing()[idxA];
57  spacing2D[1] = itkFloat->GetSpacing()[idxB];
58 
59  for (unsigned int i = 0; i < imageSize[idxC]; ++i)
60  {
61  FloatImage2DType::RegionType region;
62  FloatImage2DType::IndexType start;
63  FloatImage2DType::SizeType size;
64  start[0] = 0; start[1] = 0;
65  size[0] = imageSize[idxA];
66  size[1] = imageSize[idxB];
67  region.SetIndex(start);
68  region.SetSize(size);
69 
70  FloatImage2DType::Pointer image2D = FloatImage2DType::New();
71  image2D->SetRegions(region);
72  image2D->Allocate();
73 
74  MaskImage2DType::Pointer mask2D = MaskImage2DType::New();
75  mask2D->SetRegions(region);
76  mask2D->Allocate();
77 
78  unsigned long voxelsInMask = 0;
79 
80  for (unsigned int a = 0; a < imageSize[idxA]; ++a)
81  {
82  for (unsigned int b = 0; b < imageSize[idxB]; ++b)
83  {
84  index3D[idxA] = a;
85  index3D[idxB] = b;
86  index3D[idxC] = i;
87  index2D[0] = a;
88  index2D[1] = b;
89  image2D->SetPixel(index2D, itkFloat->GetPixel(index3D));
90  mask2D->SetPixel(index2D, itkMask->GetPixel(index3D));
91  voxelsInMask += (itkMask->GetPixel(index3D) > 0) ? 1 : 0;
92 
93  }
94  }
95 
96  image2D->SetSpacing(spacing2D);
97  mask2D->SetSpacing(spacing2D);
98 
99  mitk::Image::Pointer tmpFloatImage = mitk::Image::New();
100  tmpFloatImage->InitializeByItk(image2D.GetPointer());
101  mitk::GrabItkImageMemory(image2D, tmpFloatImage);
102 
103  mitk::Image::Pointer tmpMaskImage = mitk::Image::New();
104  tmpMaskImage->InitializeByItk(mask2D.GetPointer());
105  mitk::GrabItkImageMemory(mask2D, tmpMaskImage);
106 
107  if (voxelsInMask > 0)
108  {
109  imageVector.push_back(tmpFloatImage);
110  maskVector.push_back(tmpMaskImage);
111  }
112  }
113 }
114 
115 
116 
117 
118 std::vector<double> mitk::AbstractGlobalImageFeature::SplitDouble(std::string str, char delimiter) {
119  std::vector<double> internal;
120  std::stringstream ss(str); // Turn the string into a stream.
121  std::string tok;
122  double val;
123  while (std::getline(ss, tok, delimiter)) {
124  std::stringstream s2(tok);
125  s2 >> val;
126  internal.push_back(val);
127  }
128 
129  return internal;
130 }
131 
133 {
134  std::string name = GetOptionPrefix();
135 
136  parser.addArgument(name + "::minimum", name + "::min", mitkCommandLineParser::Float, "Minium Intensity for Quantification", "Defines the minimum Intensity used for Quantification", us::Any());
137  parser.addArgument(name + "::maximum", name + "::max", mitkCommandLineParser::Float, "Maximum Intensity for Quantification", "Defines the maximum Intensity used for Quantification", us::Any());
138  parser.addArgument(name + "::bins", name + "::bins", mitkCommandLineParser::Int, "Number of Bins", "Define the number of bins that is used ", us::Any());
139  parser.addArgument(name + "::binsize", name + "::binsize", mitkCommandLineParser::Float, "Binsize", "Define the size of the used bins", us::Any());
140  parser.addArgument(name + "::ignore-global-histogram", name + "::ignore-global-histogram", mitkCommandLineParser::Bool, "Ignore the global histogram Parameters", "Ignores the global histogram parameters", us::Any());
141  parser.addArgument(name + "::ignore-mask-for-histogram", name + "::ignore-mask", mitkCommandLineParser::Bool, "Ignore the global histogram Parameters", "Ignores the global histogram parameters", us::Any());
142 
143 }
144 
146 {
147  unsigned int bins = 0;
148  double binsize = 0;
149  double minimum = 0;
150  double maximum = 0;
151 
152  auto parsedArgs = GetParameter();
153  std::string name = GetOptionPrefix();
154 
155  bool useGlobal = true;
156  if (parsedArgs.count(name + "::ignore-global-histogram"))
157  {
158  useGlobal = false;
159  SetUseMinimumIntensity(false);
160  SetUseMaximumIntensity(false);
161  SetUseBinsize(false);
162  SetUseBins(false);
163  }
164 
165  if (useGlobal)
166  {
167  if (parsedArgs.count("ignore-mask-for-histogram"))
168  {
169  bool tmp = us::any_cast<bool>(parsedArgs["ignore-mask-for-histogram"]);
170  SetIgnoreMask(tmp);
171  }
172  if (parsedArgs.count("minimum-intensity"))
173  {
174  minimum = us::any_cast<float>(parsedArgs["minimum-intensity"]);
175  SetMinimumIntensity(minimum);
177  }
178  if (parsedArgs.count("maximum-intensity"))
179  {
180  maximum = us::any_cast<float>(parsedArgs["maximum-intensity"]);
181  SetMaximumIntensity(maximum);
183  }
184  if (parsedArgs.count("bins"))
185  {
186  bins = us::any_cast<int>(parsedArgs["bins"]);
187  SetBins(bins);
188  SetUseBins(true);
189  }
190  if (parsedArgs.count("binsize"))
191  {
192  binsize = us::any_cast<float>(parsedArgs["binsize"]);
193  SetBinsize(binsize);
194  SetUseBinsize(true);
195  }
196  }
197  if (parsedArgs.count(name+"::ignore-mask-for-histogram"))
198  {
199  bool tmp = us::any_cast<bool>(parsedArgs[name+"::ignore-mask-for-histogram"]);
200  SetIgnoreMask(tmp);
201  }
202  if (parsedArgs.count(name + "::minimum"))
203  {
204  minimum = us::any_cast<float>(parsedArgs[name + "::minimum"]);
205  SetMinimumIntensity(minimum);
207  }
208  if (parsedArgs.count(name + "::maximum"))
209  {
210  maximum = us::any_cast<float>(parsedArgs[name + "::maximum"]);
211  SetMaximumIntensity(maximum);
213  }
214  if (parsedArgs.count(name + "::bins"))
215  {
216  bins = us::any_cast<int>(parsedArgs[name + "::bins"]);
217  SetBins(bins);
218  }
219  if (parsedArgs.count(name + "::binsize"))
220  {
221  binsize = us::any_cast<float>(parsedArgs[name + "::binsize"]);
222  SetBinsize(binsize);
223  SetUseBinsize(true);
224  }
225  InitializeQuantifier(feature, mask, defaultBins);
226 }
227 
228 void mitk::AbstractGlobalImageFeature::InitializeQuantifier(const Image::Pointer & feature, const Image::Pointer &mask, unsigned int defaultBins)
229 {
230  m_Quantifier = IntensityQuantifier::New();
232  m_Quantifier->InitializeByBinsizeAndMaximum(GetMinimumIntensity(), GetMaximumIntensity(), GetBinsize());
233  else if (GetUseMinimumIntensity() && GetUseBins() && GetUseBinsize())
234  m_Quantifier->InitializeByBinsizeAndBins(GetMinimumIntensity(), GetBins(), GetBinsize());
236  m_Quantifier->InitializeByMinimumMaximum(GetMinimumIntensity(), GetMaximumIntensity(), GetBins());
237  // Intialize from Image and Binsize
239  m_Quantifier->InitializeByImageAndBinsizeAndMinimum(feature, GetMinimumIntensity(), GetBinsize());
241  m_Quantifier->InitializeByImageAndBinsizeAndMaximum(feature, GetMaximumIntensity(), GetBinsize());
242  else if (GetUseBinsize() && GetIgnoreMask())
243  m_Quantifier->InitializeByImageAndBinsize(feature, GetBinsize());
244  // Initialize form Image, Mask and Binsize
245  else if (GetUseBinsize() && GetUseMinimumIntensity())
246  m_Quantifier->InitializeByImageRegionAndBinsizeAndMinimum(feature, mask, GetMinimumIntensity(), GetBinsize());
247  else if (GetUseBinsize() && GetUseMaximumIntensity())
248  m_Quantifier->InitializeByImageRegionAndBinsizeAndMaximum(feature, mask, GetMaximumIntensity(), GetBinsize());
249  else if (GetUseBinsize())
250  m_Quantifier->InitializeByImageRegionAndBinsize(feature, mask, GetBinsize());
251  // Intialize from Image and Bins
252  else if (GetUseBins() && GetIgnoreMask() && GetUseMinimumIntensity())
253  m_Quantifier->InitializeByImageAndMinimum(feature, GetMinimumIntensity(), GetBins());
254  else if (GetUseBins() && GetIgnoreMask() && GetUseMaximumIntensity())
255  m_Quantifier->InitializeByImageAndMaximum(feature, GetMaximumIntensity(), GetBins());
256  else if (GetUseBins())
257  m_Quantifier->InitializeByImage(feature, GetBins());
258  // Intialize from Image, Mask and Bins
259  else if (GetUseBins() && GetUseMinimumIntensity())
260  m_Quantifier->InitializeByImageRegionAndMinimum(feature, mask, GetMinimumIntensity(), GetBins());
261  else if (GetUseBins() && GetUseMaximumIntensity())
262  m_Quantifier->InitializeByImageRegionAndMaximum(feature, mask, GetMaximumIntensity(), GetBins());
263  else if (GetUseBins())
264  m_Quantifier->InitializeByImageRegion(feature, mask, GetBins());
265  // Default
266  else if (GetIgnoreMask())
267  m_Quantifier->InitializeByImage(feature, GetBins());
268  else
269  m_Quantifier->InitializeByImageRegion(feature, mask, defaultBins);
270 }
271 
273 {
274  return "";
275 }
276 
278 {
279  std::string output;
280  output = m_FeatureClassName + "::";
281  if (m_EncodeParameters)
282  {
283  output += GetCurrentFeatureEncoding() + "::";
284  }
285  return output;
286 }
287 
289 {
290  std::stringstream ss;
292  ss << "Min-" << GetMinimumIntensity() << "_Max-" << GetMaximumIntensity() << "_BS-" << GetBinsize();
293  else if (GetUseMinimumIntensity() && GetUseBins() && GetUseBinsize())
294  ss << "Min-" << GetMinimumIntensity() << "_Bins-" << GetBins() << "_BS-" << GetBinsize();
296  ss << "Min-" << GetMinimumIntensity() << "_Max-" << GetMaximumIntensity() << "_Bins-" << GetBins();
297  // Intialize from Image and Binsize
299  ss << "Min-" << GetMinimumIntensity() << "_BS-" << GetBinsize() << "_FullImage";
301  ss << "Max-" << GetMaximumIntensity() << "_BS-" << GetBinsize() << "_FullImage";
302  else if (GetUseBinsize() && GetIgnoreMask())
303  ss << "BS-" << GetBinsize() << "_FullImage";
304  // Initialize form Image, Mask and Binsize
305  else if (GetUseBinsize() && GetUseMinimumIntensity())
306  ss << "Min-" << GetMinimumIntensity() << "_BS-" << GetBinsize();
307  else if (GetUseBinsize() && GetUseMaximumIntensity())
308  ss << "Max-" << GetMaximumIntensity() << "_BS-" << GetBinsize();
309  else if (GetUseBinsize())
310  ss << "BS-" << GetBinsize();
311  // Intialize from Image and Bins
312  else if (GetUseBins() && GetIgnoreMask() && GetUseMinimumIntensity())
313  ss << "Min-" << GetMinimumIntensity() << "_Bins-" << GetBins() << "_FullImage";
314  else if (GetUseBins() && GetIgnoreMask() && GetUseMaximumIntensity())
315  ss << "Max-" << GetMaximumIntensity() << "_Bins-" << GetBins() << "_FullImage";
316  else if (GetUseBins())
317  ss << "Bins-" << GetBins() << "_FullImage";
318  // Intialize from Image, Mask and Bins
319  else if (GetUseBins() && GetUseMinimumIntensity())
320  ss << "Min-" << GetMinimumIntensity() << "_Bins-" << GetBins();
321  else if (GetUseBins() && GetUseMaximumIntensity())
322  ss << "Max-" << GetMaximumIntensity() << "_Bins-" << GetBins();
323  else if (GetUseBins())
324  ss << "Bins-" << GetBins();
325  // Default
326  else if (GetIgnoreMask())
327  ss << "Bins-" << GetBins() << "_FullImage";
328  else
329  ss << "Bins-" << GetBins();
330  return ss.str();
331 }
332 
333 
335 {
336  m_CalculateWithParameter = true;
337  auto result = CalculateFeaturesSlicewise(feature, mask, sliceID);
338  featureList.insert(featureList.end(), result.begin(), result.end());
339 }
340 
342 {
343  std::vector<mitk::Image::Pointer> imageVector;
344  std::vector<mitk::Image::Pointer> maskVector;
345 
346  ExtractSlicesFromImages(feature, mask,sliceID, imageVector, maskVector);
347  std::vector<mitk::AbstractGlobalImageFeature::FeatureListType> statVector;
348 
349  for (std::size_t index = 0; index < imageVector.size(); ++index)
350  {
351  if (m_CalculateWithParameter)
352  {
353  FeatureListType stat;
354  this->CalculateFeaturesUsingParameters(imageVector[index], maskVector[index], maskVector[index], stat);
355  statVector.push_back(stat);
356  }
357  else
358  {
359  auto stat = this->CalculateFeatures(imageVector[index], maskVector[index]);
360  statVector.push_back(stat);
361  }
362  }
363 
364  if (statVector.size() < 1)
365  return FeatureListType();
366 
367  FeatureListType statMean, statStd, result;
368  for (std::size_t i = 0; i < statVector[0].size(); ++i)
369  {
370  auto cElement1 = statVector[0][i];
371  cElement1.first = "SliceWise Mean " + cElement1.first;
372  cElement1.second = 0.0;
373  auto cElement2 = statVector[0][i];
374  cElement2.first = "SliceWise Var. " + cElement2.first;
375  cElement2.second = 0.0;
376  statMean.push_back(cElement1);
377  statStd.push_back(cElement2);
378  }
379  for (auto cStat : statVector)
380  {
381  for (std::size_t i = 0; i < cStat.size(); ++i)
382  {
383  statMean[i].second += cStat[i].second / (1.0*statVector.size());
384  }
385  }
386 
387  for (auto cStat : statVector)
388  {
389  for (std::size_t i = 0; i < cStat.size(); ++i)
390  {
391  statStd[i].second += (cStat[i].second - statMean[i].second)*(cStat[i].second - statMean[i].second) / (1.0*statVector.size());
392  }
393  }
394 
395  for (auto cStat : statVector)
396  {
397  std::copy(cStat.begin(), cStat.end(), std::back_inserter(result));
398  }
399  std::copy(statMean.begin(), statMean.end(), std::back_inserter(result));
400  std::copy(statStd.begin(), statStd.end(), std::back_inserter(result));
401  return result;
402 }
virtual void SetBins(int _arg)
virtual void SetMaximumIntensity(double _arg)
virtual double GetBinsize() const
virtual std::string GetCurrentFeatureEncoding()
Adds an additional Separator to the name of the feature, which encodes the used parameters.
static void ExtractSlicesFromImages(mitk::Image::Pointer image, mitk::Image::Pointer mask, int direction, std::vector< mitk::Image::Pointer > &imageVector, std::vector< mitk::Image::Pointer > &maskVector)
static Pointer New()
virtual bool GetIgnoreMask() const
virtual void SetUseBins(bool _arg)
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
itk::Image< double, 3 > FloatImageType
Definition: CLBrainMask.cpp:31
virtual void SetUseBinsize(bool _arg)
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false, mitkCommandLineParser::Channel channel=mitkCommandLineParser::Channel::None)
virtual bool GetUseMaximumIntensity() const
virtual void SetMinimumIntensity(double _arg)
Image::Pointer GrabItkImageMemory(itk::SmartPointer< ItkOutputImageType > &itkimage, mitk::Image *mitkImage=nullptr, const BaseGeometry *geometry=nullptr, bool update=true)
Grabs the memory of an itk::Image (with a specific type) and puts it into an mitk::Image.The memory is managed by the mitk::Image after calling this function. The itk::Image remains valid until the mitk::Image decides to free the memory.
virtual double GetMinimumIntensity() const
std::vector< std::pair< std::string, double > > FeatureListType
std::string FeatureDescriptionPrefix()
Returns a string that encodes the feature class name.
virtual bool GetUseBins() const
virtual bool GetUseBinsize() const
virtual FeatureListType CalculateFeatures(const Image::Pointer &feature, const Image::Pointer &mask)=0
Calculates the feature of this abstact interface. Does not necessarily considers the parameter settin...
Definition: usAny.h:163
itk::Image< unsigned char, 3 > MaskImageType
Definition: CLBrainMask.cpp:32
virtual void SetUseMinimumIntensity(bool _arg)
virtual void CalculateFeaturesUsingParameters(const Image::Pointer &feature, const Image::Pointer &mask, const Image::Pointer &maskNoNAN, FeatureListType &featureList)=0
Calculates the feature of this abstact interface. Does not necessarily considers the parameter settin...
virtual void SetUseMaximumIntensity(bool _arg)
mitk::Image::Pointer image
static Pointer New()
virtual void SetIgnoreMask(bool _arg)
void AddQuantifierArguments(mitkCommandLineParser &parser)
FeatureListType CalculateFeaturesSlicewise(const Image::Pointer &feature, const Image::Pointer &mask, int sliceID)
Calculates the given feature Slice-wise. Might not be availble for an individual filter! ...
std::vector< double > SplitDouble(std::string str, char delimiter)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
virtual bool GetUseMinimumIntensity() const
mitk::Image::Pointer mask
virtual void CalculateFeaturesSliceWiseUsingParameters(const Image::Pointer &feature, const Image::Pointer &mask, int sliceID, FeatureListType &featureList)
Calculates the feature of this abstact interface. Does not necessarily considers the parameter settin...
void InitializeQuantifierFromParameters(const Image::Pointer &feature, const Image::Pointer &mask, unsigned int defaultBins=256)
virtual void SetBinsize(double _arg)
virtual double GetMaximumIntensity() const
void InitializeQuantifier(const Image::Pointer &feature, const Image::Pointer &mask, unsigned int defaultBins=256)
virtual ParameterTypes GetParameter() const