1 /*============================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center (DKFZ)
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
11 ============================================================================*/
13 #ifndef _itkConnectedAdaptiveThresholdImageFilter_txx
14 #define _itkConnectedAdaptiveThresholdImageFilter_txx
16 #include "itkAdaptiveThresholdIterator.h"
17 #include "itkBinaryThresholdImageFunction.h"
18 #include "itkConnectedAdaptiveThresholdImageFilter.h"
19 #include "itkMinimumMaximumImageFilter.h"
20 #include "itkThresholdImageFilter.h"
27 template <class TInputImage, class TOutputImage>
28 ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::ConnectedAdaptiveThresholdImageFilter()
29 : m_OutoutImageMaskFineSegmentation(nullptr),
30 m_GrowingDirectionIsUpwards(true),
32 m_DetectedLeakagePoint(0),
36 m_FineDetectionMode(false),
37 m_DiscardLastPreview(false),
38 m_SegmentationCancelled(false)
42 template <class TInputImage, class TOutputImage>
43 void ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::GenerateData()
45 typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput();
46 typename ConnectedAdaptiveThresholdImageFilter::OutputImagePointer outputImage = this->GetOutput();
48 typename Superclass::InputPixelObjectType::Pointer lowerThreshold = this->GetLowerInput();
49 typename Superclass::InputPixelObjectType::Pointer upperThreshold = this->GetUpperInput();
51 // kommt drauf, wie wir hier die Pipeline aufbauen
52 this->SetLower(lowerThreshold->Get());
53 this->SetUpper(upperThreshold->Get());
54 typedef BinaryThresholdImageFunction<InputImageType> FunctionType;
55 typedef AdaptiveThresholdIterator<OutputImageType, FunctionType> IteratorType;
57 int initValue = IteratorType::CalculateInitializeValue((int)(this->GetLower()), (int)(this->GetUpper()));
59 // Initialize the output according to the segmentation (fine or raw)
60 if (m_FineDetectionMode)
62 outputImage = this->m_OutoutImageMaskFineSegmentation;
65 typename ConnectedAdaptiveThresholdImageFilter::OutputImageRegionType region = outputImage->GetRequestedRegion();
66 outputImage->SetBufferedRegion(region);
67 outputImage->Allocate();
68 if (!m_FineDetectionMode)
69 { // only initalize the output image if we are using the raw segmentation mode
70 outputImage->FillBuffer((typename ConnectedAdaptiveThresholdImageFilter::OutputImagePixelType)initValue);
73 typename FunctionType::Pointer function = FunctionType::New();
74 function->SetInputImage(inputImage);
76 typename Superclass::SeedContainerType seeds;
77 seeds = this->GetSeeds();
79 // pass parameters needed for region growing to iterator
80 IteratorType it(outputImage, function, seeds);
81 it.SetFineDetectionMode(m_FineDetectionMode);
82 it.SetExpansionDirection(m_GrowingDirectionIsUpwards);
83 it.SetMinTH((int)(this->GetLower()));
84 it.SetMaxTH((int)(this->GetUpper()));
86 this->m_SeedpointValue = it.GetSeedPointValue();
88 if ((this->GetLower()) > this->m_SeedpointValue || this->m_SeedpointValue > (this->GetUpper()))
90 // set m_SegmentationCancelled to true, so if it doesn't reach the point where it is set back to false
91 // we can asssume that there was an error
92 this->m_SegmentationCancelled = true;
96 // iterate through image until
99 // make iterator go one step further (calls method DoFloodStep())
102 this->m_DetectedLeakagePoint = it.GetLeakagePoint();
103 this->m_SegmentationCancelled = false;
106 template <class TInputImage, class TOutputImage>
107 TOutputImage *itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::GetResultImage()
109 return m_OutoutImageMaskFineSegmentation;
112 template <class TInputImage, class TOutputImage>
113 typename ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::IndexType
114 itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::CorrectSeedPointPosition(
115 unsigned int sizeOfVolume, int lowerTh, int upperTh)
117 typename ConnectedAdaptiveThresholdImageFilter::InputImageConstPointer inputImage = this->GetInput();
118 typedef typename TInputImage::IndexType IndexType;
119 IndexType itkIntelligentSeedIndex;
121 int seedPixelValue = inputImage->GetPixel(m_SeedPointIndex);
123 // set new seed index to the voxel with the darkest value and shortest distance to original seed
124 if (seedPixelValue > upperTh || seedPixelValue < lowerTh)
126 // MITK_INFO << "seed pixel value [BEFORE] = " << seedPixelValue;
128 itk::Index<3> workindex;
129 for (int i = 0; i < 3; i++)
131 workindex[i] = m_SeedPointIndex[i] - sizeOfVolume / 2;
132 if (workindex[i] < 0)
135 itk::Size<3> worksize;
136 for (int i = 0; i < 3; i++)
138 worksize[i] = sizeOfVolume;
141 itk::ImageRegion<3> workregion(workindex, worksize);
142 itk::ImageRegionIterator<TInputImage> regionIt(const_cast<TInputImage *>(inputImage.GetPointer()), workregion);
144 // int darkestGrayValue=seedPixelValue;
145 int currentGrayValue;
147 float distance = (float)(sizeOfVolume / 2);
148 float relativeDistance = 1; // between 0 and 1
150 mitk::Vector3D seedVector, currentVector;
151 mitk::FillVector3D(seedVector, m_SeedPointIndex[0], m_SeedPointIndex[1], m_SeedPointIndex[2]);
152 currentVector = seedVector;
154 float costValue = 0; // beware, Depending on seeking upper or lower value...
156 for (regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt)
158 // get current gray value
159 currentGrayValue = regionIt.Value();
160 // get current seed index
161 m_SeedPointIndex = regionIt.GetIndex();
163 // fill current vector
164 mitk::FillVector3D(currentVector, m_SeedPointIndex[0], m_SeedPointIndex[1], m_SeedPointIndex[2]);
165 // calculate distance from original seed to new seed
166 mitk::Vector3D distVector = currentVector - seedVector;
167 distance = fabs(distVector.GetSquaredNorm());
168 relativeDistance = distance / (sizeOfVolume / 2);
170 // calculate "cost function"
171 float currentCostValue = (1 - relativeDistance) * currentGrayValue;
173 if (currentCostValue < costValue && currentGrayValue < upperTh)
175 itkIntelligentSeedIndex = regionIt.GetIndex();
176 costValue = currentCostValue;
178 // MITK_INFO <<"cost value="<< costValue;
179 // MITK_INFO <<"darkest and closest Voxel ="<< currentGrayValue;
180 // MITK_INFO <<"m_UPPER="<< upperTh;
183 // MITK_INFO<< "seed pixel value [AFTER] =" << inputImage->GetPixel(itkIntelligentSeedIndex) <<"\n";
186 { // no correction of the seed point is needed, just pass the original seed
187 itkIntelligentSeedIndex = m_SeedPointIndex;
190 return itkIntelligentSeedIndex;
193 template <class TInputImage, class TOutputImage>
194 void itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::CropMask(unsigned int croppingSize)
196 // initialize center point of the working region
197 itk::Index<3> workindex;
198 for (int i = 0; i < 3; i++)
200 workindex[i] = m_SeedPointIndex[i] - croppingSize / 2;
201 if (workindex[i] < 0)
204 // initialize working volume
205 itk::Size<3> worksize;
206 for (int i = 0; i < 3; i++)
208 worksize[i] = croppingSize;
210 // set working region
211 itk::ImageRegion<3> workregion(workindex, worksize);
213 // check if the entire region is inside the image
214 if (!(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion().IsInside(workregion)))
216 // if not then crop to the intersection of the image (gemeinsame Schnittmenge Bild und workingRegion)
217 if (!(workregion.Crop(m_OutoutImageMaskFineSegmentation->GetLargestPossibleRegion())))
219 MITK_ERROR << "Cropping working region failed!";
224 // initialize region iterator
225 itk::ImageRegionIterator<TOutputImage> regionIt(m_OutoutImageMaskFineSegmentation, workregion);
226 for (regionIt.GoToBegin(); !regionIt.IsAtEnd(); ++regionIt)
228 // and set all voxel inside the working region to zero
233 template <class TInputImage, class TOutputImage>
234 unsigned int itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::AdjustIteratorMask()
236 typedef itk::ThresholdImageFilter<TOutputImage> ThresholdFilterType;
237 typedef itk::MinimumMaximumImageFilter<TOutputImage> MaxFilterType;
239 typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New();
240 typename MaxFilterType::Pointer maxFilter = MaxFilterType::New();
242 unsigned int maxValue;
244 if (!m_DiscardLastPreview)
246 // get the biggest value of the image
247 maxFilter->SetInput(m_OutoutImageMaskFineSegmentation);
248 maxFilter->UpdateLargestPossibleRegion();
249 maxValue = maxFilter->GetMaximum();
252 { // use the last biggest value in the preview. This was set in SetParameterForFineSegmentation(...adjLowerTh...) []
253 maxValue = m_AdjLowerTh;
256 // set all values <lower && >upper to zero (thresouldOutside uses < and > NOT <= and >=)
257 thresholdFilter->SetInput(m_OutoutImageMaskFineSegmentation);
258 thresholdFilter->SetOutsideValue(0);
259 thresholdFilter->ThresholdOutside(m_AdjLowerTh, maxValue);
260 thresholdFilter->UpdateLargestPossibleRegion();
262 // set all values in between lower and upper (>=lower && <=upper) to the highest value in the image
263 thresholdFilter->SetInput(thresholdFilter->GetOutput());
264 thresholdFilter->SetOutsideValue(maxValue);
265 thresholdFilter->ThresholdOutside(0, m_AdjLowerTh - 1);
266 thresholdFilter->UpdateLargestPossibleRegion();
268 m_OutoutImageMaskFineSegmentation = thresholdFilter->GetOutput();
273 template <class TInputImage, class TOutputImage>
274 void itk::ConnectedAdaptiveThresholdImageFilter<TInputImage, TOutputImage>::SetParameterForFineSegmentation(
275 TOutputImage *iteratorMaskForFineSegmentation,
276 unsigned int adjLowerTh,
277 unsigned int adjUpperTh,
278 itk::Index<3> seedPoint,
279 bool discardLeafSegmentation)
281 // just to make sure we´re in the right mode and the mask exsits
282 if (m_FineDetectionMode && iteratorMaskForFineSegmentation)
284 m_OutoutImageMaskFineSegmentation = iteratorMaskForFineSegmentation;
285 m_AdjLowerTh = adjLowerTh;
286 m_AdjUpperTh = adjUpperTh; // still needed?
287 m_SeedPointIndex = seedPoint;
288 m_DiscardLastPreview = discardLeafSegmentation;
292 if (!m_FineDetectionMode)
294 MITK_ERROR << "Fine-detection-segmentation mode not set!";
298 MITK_ERROR << "Iterator-mask-image not set!";
303 } // end namespace itk