Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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