Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
itkConnectedAdaptiveThresholdImageFilter.txx
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #ifndef _itkConnectedAdaptiveThresholdImageFilter_txx
18 #define _itkConnectedAdaptiveThresholdImageFilter_txx
19 
20 #include "itkAdaptiveThresholdIterator.h"
21 #include "itkBinaryThresholdImageFunction.h"
22 #include "itkConnectedAdaptiveThresholdImageFilter.h"
23 #include "itkMinimumMaximumImageFilter.h"
24 #include "itkThresholdImageFilter.h"
25 
26 namespace itk
27 {
28  /**
29  * Constructor
30  */
31  template <class TInputImage, class TOutputImage>
32  ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::ConnectedAdaptiveThresholdImageFilter()
33  : m_FineDetectionMode(false)
34  {
35  }
36 
37  template <class TInputImage, class TOutputImage>
38  void ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::GenerateData()
39  {
40  typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput();
41  typename ConnectedAdaptiveThresholdImageFilter::OutputImagePointer outputImage = this->GetOutput();
42 
43  typename Superclass::InputPixelObjectType::Pointer lowerThreshold = this->GetLowerInput();
44  typename Superclass::InputPixelObjectType::Pointer upperThreshold = this->GetUpperInput();
45 
46  // kommt drauf, wie wir hier die Pipeline aufbauen
47  Superclass::m_Lower = lowerThreshold->Get();
48  Superclass::m_Upper = upperThreshold->Get();
49  typedef BinaryThresholdImageFunction<InputImageType> FunctionType;
50  typedef AdaptiveThresholdIterator<OutputImageType, FunctionType> IteratorType;
51 
52  int initValue = IteratorType::CalculateInitializeValue((int)Superclass::m_Lower, (int)Superclass::m_Upper);
53 
54  // Initialize the output according to the segmentation (fine or raw)
55  if (m_FineDetectionMode)
56  {
57  outputImage = this->m_OutoutImageMaskFineSegmentation;
58  }
59 
60  typename ConnectedAdaptiveThresholdImageFilter::OutputImageRegionType region = outputImage->GetRequestedRegion();
61  outputImage->SetBufferedRegion(region);
62  outputImage->Allocate();
63  if (!m_FineDetectionMode)
64  { // only initalize the output image if we are using the raw segmentation mode
65  outputImage->FillBuffer((typename ConnectedAdaptiveThresholdImageFilter::OutputImagePixelType)initValue);
66  }
67 
68  typename FunctionType::Pointer function = FunctionType::New();
69  function->SetInputImage(inputImage);
70 
71  // pass parameters needed for region growing to iterator
72  IteratorType it(outputImage, function, this->m_Seeds);
73  it.SetFineDetectionMode(m_FineDetectionMode);
74  it.SetExpansionDirection(m_GrowingDirectionIsUpwards);
75  it.SetMinTH((int)Superclass::m_Lower);
76  it.SetMaxTH((int)Superclass::m_Upper);
77  it.GoToBegin();
78  this->m_SeedpointValue = it.GetSeedPointValue();
79 
80  if (Superclass::m_Lower > this->m_SeedpointValue || this->m_SeedpointValue > Superclass::m_Upper)
81  {
82  // set m_SegmentationCancelled to true, so if it doesn't reach the point where it is set back to false
83  // we can asssume that there was an error
84  this->m_SegmentationCancelled = true;
85  return;
86  }
87 
88  // iterate through image until
89  while (!it.IsAtEnd())
90  {
91  // make iterator go one step further (calls method DoFloodStep())
92  ++it;
93  }
94  this->m_DetectedLeakagePoint = it.GetLeakagePoint();
95  this->m_SegmentationCancelled = false;
96  }
97 
98  template <class TInputImage, class TOutputImage>
99  TOutputImage *itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::GetResultImage()
100  {
101  return m_OutoutImageMaskFineSegmentation;
102  }
103 
104  template <class TInputImage, class TOutputImage>
105  typename ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::IndexType
106  itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::CorrectSeedPointPosition(
107  unsigned int sizeOfVolume, int lowerTh, int upperTh)
108  {
109  typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput();
110  typedef typename TInputImage::IndexType IndexType;
111  IndexType itkIntelligentSeedIndex;
112 
113  int seedPixelValue = inputImage->GetPixel(m_SeedPointIndex);
114 
115  // set new seed index to the voxel with the darkest value and shortest distance to original seed
116  if (seedPixelValue > upperTh || seedPixelValue < lowerTh)
117  {
118  // MITK_INFO << "seed pixel value [BEFORE] = " << seedPixelValue;
119  // ToDo crop region
120  itk::Index<3> workindex;
121  for (int i = 0; i < 3; i++)
122  {
123  workindex[i] = m_SeedPointIndex[i] - sizeOfVolume / 2;
124  if (workindex[i] < 0)
125  workindex[i] = 0;
126  }
127  itk::Size<3> worksize;
128  for (int i = 0; i < 3; i++)
129  {
130  worksize[i] = sizeOfVolume;
131  }
132 
133  itk::ImageRegion<3> workregion(workindex, worksize);
134  itk::ImageRegionIterator<TInputImage> regionIt(const_cast<TInputImage *>(inputImage.GetPointer()), workregion);
135 
136  // int darkestGrayValue=seedPixelValue;
137  int currentGrayValue;
138 
139  float distance = (float)(sizeOfVolume / 2);
140  float relativeDistance = 1; // between 0 and 1
141 
142  mitk::Vector3D seedVector, currentVector;
143  mitk::FillVector3D(seedVector, m_SeedPointIndex[0], m_SeedPointIndex[1], m_SeedPointIndex[2]);
144  currentVector = seedVector;
145 
146  float costValue = 0; // beware, Depending on seeking upper or lower value...
147 
148  for (regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt)
149  {
150  // get current gray value
151  currentGrayValue = regionIt.Value();
152  // get current seed index
153  m_SeedPointIndex = regionIt.GetIndex();
154 
155  // fill current vector
156  mitk::FillVector3D(currentVector, m_SeedPointIndex[0], m_SeedPointIndex[1], m_SeedPointIndex[2]);
157  // calculate distance from original seed to new seed
158  mitk::Vector3D distVector = currentVector - seedVector;
159  distance = fabs(distVector.GetSquaredNorm());
160  relativeDistance = distance / (sizeOfVolume / 2);
161 
162  // calculate "cost function"
163  float currentCostValue = (1 - relativeDistance) * currentGrayValue;
164 
165  if (currentCostValue < costValue && currentGrayValue < upperTh)
166  {
167  itkIntelligentSeedIndex = regionIt.GetIndex();
168  costValue = currentCostValue;
169 
170  // MITK_INFO <<"cost value="<< costValue;
171  // MITK_INFO <<"darkest and closest Voxel ="<< currentGrayValue;
172  // MITK_INFO <<"m_UPPER="<< upperTh;
173  }
174  }
175  // MITK_INFO<< "seed pixel value [AFTER] =" << inputImage->GetPixel(itkIntelligentSeedIndex) <<"\n";
176  }
177  else
178  { // no correction of the seed point is needed, just pass the original seed
179  itkIntelligentSeedIndex = m_SeedPointIndex;
180  }
181 
182  return itkIntelligentSeedIndex;
183  }
184 
185  template <class TInputImage, class TOutputImage>
186  void itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::CropMask(unsigned int croppingSize)
187  {
188  // initialize center point of the working region
189  itk::Index<3> workindex;
190  for (int i = 0; i < 3; i++)
191  {
192  workindex[i] = m_SeedPointIndex[i] - croppingSize / 2;
193  if (workindex[i] < 0)
194  workindex[i] = 0;
195  }
196  // initialize working volume
197  itk::Size<3> worksize;
198  for (int i = 0; i < 3; i++)
199  {
200  worksize[i] = croppingSize;
201  }
202  // set working region
203  itk::ImageRegion<3> workregion(workindex, worksize);
204 
205  // check if the entire region is inside the image
206  if (!(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion().IsInside(workregion)))
207  {
208  // if not then crop to the intersection of the image (gemeinsame Schnittmenge Bild und workingRegion)
209  if (!(workregion.Crop(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion())))
210  {
211  MITK_ERROR << "Cropping working region failed!";
212  return;
213  }
214  }
215 
216  // initialize region iterator
217  itk::ImageRegionIterator<TOutputImage> regionIt(m_OutoutImageMaskFineSegmentation, workregion);
218  for (regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt)
219  {
220  // and set all voxel inside the working region to zero
221  regionIt.Set(0);
222  }
223  }
224 
225  template <class TInputImage, class TOutputImage>
226  unsigned int itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::AdjustIteratorMask()
227  {
228  typedef itk::ThresholdImageFilter<TOutputImage> ThresholdFilterType;
229  typedef itk::MinimumMaximumImageFilter<TOutputImage> MaxFilterType;
230 
231  typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
232  typename MaxFilterType::Pointer maxFilter = MaxFilterType::New();
233 
234  unsigned int maxValue;
235 
236  if (!m_DiscardLastPreview)
237  {
238  // get the biggest value of the image
239  maxFilter->SetInput(m_OutoutImageMaskFineSegmentation);
240  maxFilter->UpdateLargestPossibleRegion();
241  maxValue = maxFilter->GetMaximum();
242  }
243  else
244  { // use the last biggest value in the preview. This was set in SetParameterForFineSegmentation(...adjLowerTh...) []
245  maxValue = m_AdjLowerTh;
246  }
247 
248  // set all values <lower && >upper to zero (thresouldOutside uses < and > NOT <= and >=)
249  thresholdFilter->SetInput(m_OutoutImageMaskFineSegmentation);
250  thresholdFilter->SetOutsideValue(0);
251  thresholdFilter->ThresholdOutside(m_AdjLowerTh, maxValue);
252  thresholdFilter->UpdateLargestPossibleRegion();
253 
254  // set all values in between lower and upper (>=lower && <=upper) to the highest value in the image
255  thresholdFilter->SetInput(thresholdFilter->GetOutput());
256  thresholdFilter->SetOutsideValue(maxValue);
257  thresholdFilter->ThresholdOutside(0, m_AdjLowerTh - 1);
258  thresholdFilter->UpdateLargestPossibleRegion();
259 
260  m_OutoutImageMaskFineSegmentation = thresholdFilter->GetOutput();
261 
262  return maxValue;
263  }
264 
265  template <class TInputImage, class TOutputImage>
266  void itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::SetParameterForFineSegmentation(
267  TOutputImage *iteratorMaskForFineSegmentation,
268  unsigned int adjLowerTh,
269  unsigned int adjUpperTh,
270  itk::Index<3> seedPoint,
271  bool discardLeafSegmentation)
272  {
273  // just to make sure we�re in the right mode and the mask exsits
274  if (m_FineDetectionMode && iteratorMaskForFineSegmentation)
275  {
276  m_OutoutImageMaskFineSegmentation = iteratorMaskForFineSegmentation;
277  m_AdjLowerTh = adjLowerTh;
278  m_AdjUpperTh = adjUpperTh; // still needed?
279  m_SeedPointIndex = seedPoint;
280  m_DiscardLastPreview = discardLeafSegmentation;
281  }
282  else
283  {
284  if (!m_FineDetectionMode)
285  {
286  MITK_ERROR << "Fine-detection-segmentation mode not set!";
287  }
288  else
289  {
290  MITK_ERROR << "Iterator-mask-image not set!";
291  }
292  }
293  }
294 
295 } // end namespace itk
296 
297 #endif