1 /*===================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 See LICENSE.txt or http://www.mitk.org for details.
15 ===================================================================*/
17 #ifndef _itkConnectedAdaptiveThresholdImageFilter_txx
18 #define _itkConnectedAdaptiveThresholdImageFilter_txx
20 #include "itkAdaptiveThresholdIterator.h"
21 #include "itkBinaryThresholdImageFunction.h"
22 #include "itkConnectedAdaptiveThresholdImageFilter.h"
23 #include "itkMinimumMaximumImageFilter.h"
24 #include "itkThresholdImageFilter.h"
31 template <class TInputImage, class TOutputImage>
32 ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::ConnectedAdaptiveThresholdImageFilter()
33 : m_FineDetectionMode(false)
37 template <class TInputImage, class TOutputImage>
38 void ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::GenerateData()
40 typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput();
41 typename ConnectedAdaptiveThresholdImageFilter::OutputImagePointer outputImage = this->GetOutput();
43 typename Superclass::InputPixelObjectType::Pointer lowerThreshold = this->GetLowerInput();
44 typename Superclass::InputPixelObjectType::Pointer upperThreshold = this->GetUpperInput();
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;
52 int initValue = IteratorType::CalculateInitializeValue((int)Superclass::m_Lower, (int)Superclass::m_Upper);
54 // Initialize the output according to the segmentation (fine or raw)
55 if (m_FineDetectionMode)
57 outputImage = this->m_OutoutImageMaskFineSegmentation;
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);
68 typename FunctionType::Pointer function = FunctionType::New();
69 function->SetInputImage(inputImage);
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);
78 this->m_SeedpointValue = it.GetSeedPointValue();
80 if (Superclass::m_Lower > this->m_SeedpointValue || this->m_SeedpointValue > Superclass::m_Upper)
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;
88 // iterate through image until
91 // make iterator go one step further (calls method DoFloodStep())
94 this->m_DetectedLeakagePoint = it.GetLeakagePoint();
95 this->m_SegmentationCancelled = false;
98 template <class TInputImage, class TOutputImage>
99 TOutputImage *itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::GetResultImage()
101 return m_OutoutImageMaskFineSegmentation;
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)
109 typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput();
110 typedef typename TInputImage::IndexType IndexType;
111 IndexType itkIntelligentSeedIndex;
113 int seedPixelValue = inputImage->GetPixel(m_SeedPointIndex);
115 // set new seed index to the voxel with the darkest value and shortest distance to original seed
116 if (seedPixelValue > upperTh || seedPixelValue < lowerTh)
118 // MITK_INFO << "seed pixel value [BEFORE] = " << seedPixelValue;
120 itk::Index<3> workindex;
121 for (int i = 0; i < 3; i++)
123 workindex[i] = m_SeedPointIndex[i] - sizeOfVolume / 2;
124 if (workindex[i] < 0)
127 itk::Size<3> worksize;
128 for (int i = 0; i < 3; i++)
130 worksize[i] = sizeOfVolume;
133 itk::ImageRegion<3> workregion(workindex, worksize);
134 itk::ImageRegionIterator<TInputImage> regionIt(const_cast<TInputImage *>(inputImage.GetPointer()), workregion);
136 // int darkestGrayValue=seedPixelValue;
137 int currentGrayValue;
139 float distance = (float)(sizeOfVolume / 2);
140 float relativeDistance = 1; // between 0 and 1
142 mitk::Vector3D seedVector, currentVector;
143 mitk::FillVector3D(seedVector, m_SeedPointIndex[0], m_SeedPointIndex[1], m_SeedPointIndex[2]);
144 currentVector = seedVector;
146 float costValue = 0; // beware, Depending on seeking upper or lower value...
148 for (regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt)
150 // get current gray value
151 currentGrayValue = regionIt.Value();
152 // get current seed index
153 m_SeedPointIndex = regionIt.GetIndex();
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);
162 // calculate "cost function"
163 float currentCostValue = (1 - relativeDistance) * currentGrayValue;
165 if (currentCostValue < costValue && currentGrayValue < upperTh)
167 itkIntelligentSeedIndex = regionIt.GetIndex();
168 costValue = currentCostValue;
170 // MITK_INFO <<"cost value="<< costValue;
171 // MITK_INFO <<"darkest and closest Voxel ="<< currentGrayValue;
172 // MITK_INFO <<"m_UPPER="<< upperTh;
175 // MITK_INFO<< "seed pixel value [AFTER] =" << inputImage->GetPixel(itkIntelligentSeedIndex) <<"\n";
178 { // no correction of the seed point is needed, just pass the original seed
179 itkIntelligentSeedIndex = m_SeedPointIndex;
182 return itkIntelligentSeedIndex;
185 template <class TInputImage, class TOutputImage>
186 void itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::CropMask(unsigned int croppingSize)
188 // initialize center point of the working region
189 itk::Index<3> workindex;
190 for (int i = 0; i < 3; i++)
192 workindex[i] = m_SeedPointIndex[i] - croppingSize / 2;
193 if (workindex[i] < 0)
196 // initialize working volume
197 itk::Size<3> worksize;
198 for (int i = 0; i < 3; i++)
200 worksize[i] = croppingSize;
202 // set working region
203 itk::ImageRegion<3> workregion(workindex, worksize);
205 // check if the entire region is inside the image
206 if (!(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion().IsInside(workregion)))
208 // if not then crop to the intersection of the image (gemeinsame Schnittmenge Bild und workingRegion)
209 if (!(workregion.Crop(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion())))
211 MITK_ERROR << "Cropping working region failed!";
216 // initialize region iterator
217 itk::ImageRegionIterator<TOutputImage> regionIt(m_OutoutImageMaskFineSegmentation, workregion);
218 for (regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt)
220 // and set all voxel inside the working region to zero
225 template <class TInputImage, class TOutputImage>
226 unsigned int itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::AdjustIteratorMask()
228 typedef itk::ThresholdImageFilter<TOutputImage> ThresholdFilterType;
229 typedef itk::MinimumMaximumImageFilter<TOutputImage> MaxFilterType;
231 typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
232 typename MaxFilterType::Pointer maxFilter = MaxFilterType::New();
234 unsigned int maxValue;
236 if (!m_DiscardLastPreview)
238 // get the biggest value of the image
239 maxFilter->SetInput(m_OutoutImageMaskFineSegmentation);
240 maxFilter->UpdateLargestPossibleRegion();
241 maxValue = maxFilter->GetMaximum();
244 { // use the last biggest value in the preview. This was set in SetParameterForFineSegmentation(...adjLowerTh...) []
245 maxValue = m_AdjLowerTh;
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();
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();
260 m_OutoutImageMaskFineSegmentation = thresholdFilter->GetOutput();
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)
273 // just to make sure we´re in the right mode and the mask exsits
274 if (m_FineDetectionMode && iteratorMaskForFineSegmentation)
276 m_OutoutImageMaskFineSegmentation = iteratorMaskForFineSegmentation;
277 m_AdjLowerTh = adjLowerTh;
278 m_AdjUpperTh = adjUpperTh; // still needed?
279 m_SeedPointIndex = seedPoint;
280 m_DiscardLastPreview = discardLeafSegmentation;
284 if (!m_FineDetectionMode)
286 MITK_ERROR << "Fine-detection-segmentation mode not set!";
290 MITK_ERROR << "Iterator-mask-image not set!";
295 } // end namespace itk