Medical Imaging Interaction Toolkit  2018.4.99-b585543d
Medical Imaging Interaction Toolkit
mitkFeatureBasedEdgeDetectionFilter.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 
16 #include <mitkITKImageImport.h>
17 #include <mitkImage.h>
18 #include <mitkImageAccessByItk.h>
21 #include <mitkProgressBar.h>
22 #include <mitkUnstructuredGrid.h>
24 #include <mitkImageMaskGenerator.h>
26 
27 #include <itkBinaryBallStructuringElement.h>
28 #include <itkBinaryContourImageFilter.h>
29 #include <itkBinaryThresholdImageFilter.h>
30 #include <itkDilateObjectMorphologyImageFilter.h>
31 #include <itkErodeObjectMorphologyImageFilter.h>
32 #include <itkImage.h>
33 
35 {
36  this->SetNumberOfRequiredInputs(1);
37 
38  this->SetNumberOfIndexedOutputs(1);
39 }
40 
42 {
43 }
44 
46 {
48 
49  if (m_SegmentationMask.IsNull())
50  {
51  MITK_WARN << "Please set a segmentation mask first" << std::endl;
52  return;
53  }
54  // First create a threshold segmentation of the image. The threshold is determined
55  // by the mean +/- stddev of the pixel values that are covered by the segmentation mask
56 
57  // Compute mean and stdDev based on the current segmentation
59  statCalc->SetInputImage(image);
60 
62  imgMask->SetImageMask(m_SegmentationMask);
63 
64  auto stats = statCalc->GetStatistics()->GetStatisticsForTimeStep(0);
65  double mean = stats.GetValueConverted<double>(mitk::ImageStatisticsConstants::MEAN());
66  double stdDev = stats.GetValueConverted<double>(mitk::ImageStatisticsConstants::STANDARDDEVIATION());
67 
68  double upperThreshold = mean + stdDev;
69  double lowerThreshold = mean - stdDev;
70 
71  // Perform thresholding
72  mitk::Image::Pointer thresholdImage = mitk::Image::New();
73  AccessByItk_3(image.GetPointer(), ITKThresholding, lowerThreshold, upperThreshold, thresholdImage)
74 
76  ->Progress(2);
77 
78  // Postprocess threshold segmentation
79  // First a closing will be executed
80  mitk::Image::Pointer closedImage = mitk::Image::New();
81  AccessByItk_1(thresholdImage, ThreadedClosing, closedImage);
82 
83  // Then we will holes that might exist
85 
87 
88  // Extract the binary edges of the resulting segmentation
90  AccessByItk_1(closedImage, ContourSearch, edgeImage);
91 
92  // Convert the edge image into an unstructured grid
94  i2UFilter->SetInput(edgeImage);
95  i2UFilter->SetThreshold(1.0);
96  i2UFilter->Update();
97 
98  m_PointGrid = this->GetOutput();
99  if (m_PointGrid.IsNull())
100  m_PointGrid = mitk::UnstructuredGrid::New();
101 
102  m_PointGrid->SetVtkUnstructuredGrid(i2UFilter->GetOutput()->GetVtkUnstructuredGrid());
103 
105 }
106 
107 template <typename TPixel, unsigned int VImageDimension>
108 void mitk::FeatureBasedEdgeDetectionFilter::ThreadedClosing(itk::Image<TPixel, VImageDimension> *originalImage,
109  mitk::Image::Pointer &result)
110 {
111  typedef itk::BinaryBallStructuringElement<TPixel, VImageDimension> myKernelType;
112 
113  myKernelType ball;
114  ball.SetRadius(1);
115  ball.CreateStructuringElement();
116 
117  typedef typename itk::Image<TPixel, VImageDimension> ImageType;
118 
119  typename itk::DilateObjectMorphologyImageFilter<ImageType, ImageType, myKernelType>::Pointer dilationFilter =
120  itk::DilateObjectMorphologyImageFilter<ImageType, ImageType, myKernelType>::New();
121  dilationFilter->SetInput(originalImage);
122  dilationFilter->SetKernel(ball);
123  dilationFilter->Update();
124 
125  typename itk::Image<TPixel, VImageDimension>::Pointer dilatedImage = dilationFilter->GetOutput();
126 
127  typename itk::ErodeObjectMorphologyImageFilter<ImageType, ImageType, myKernelType>::Pointer erodeFilter =
128  itk::ErodeObjectMorphologyImageFilter<ImageType, ImageType, myKernelType>::New();
129  erodeFilter->SetInput(dilatedImage);
130  erodeFilter->SetKernel(ball);
131  erodeFilter->Update();
132 
133  mitk::GrabItkImageMemory(erodeFilter->GetOutput(), result);
134 }
135 
136 template <typename TPixel, unsigned int VImageDimension>
137 void mitk::FeatureBasedEdgeDetectionFilter::ContourSearch(itk::Image<TPixel, VImageDimension> *originalImage,
138  mitk::Image::Pointer &result)
139 {
140  typedef itk::Image<TPixel, VImageDimension> ImageType;
141  typedef itk::BinaryContourImageFilter<ImageType, ImageType> binaryContourImageFilterType;
142 
143  typename binaryContourImageFilterType::Pointer binaryContourFilter = binaryContourImageFilterType::New();
144  binaryContourFilter->SetInput(originalImage);
145  binaryContourFilter->SetForegroundValue(1);
146  binaryContourFilter->SetBackgroundValue(0);
147  binaryContourFilter->Update();
148 
149  typename itk::Image<TPixel, VImageDimension>::Pointer itkImage = itk::Image<TPixel, VImageDimension>::New();
150  itkImage->Graft(binaryContourFilter->GetOutput());
151 
152  mitk::GrabItkImageMemory(itkImage, result);
153 }
154 
155 template <typename TPixel, unsigned int VImageDimension>
156 void mitk::FeatureBasedEdgeDetectionFilter::ITKThresholding(const itk::Image<TPixel, VImageDimension> *originalImage,
157  double lower,
158  double upper,
159  mitk::Image::Pointer &result)
160 {
161  typedef itk::Image<TPixel, VImageDimension> ImageType;
162  typedef itk::Image<unsigned short, VImageDimension> SegmentationType;
163  typedef itk::BinaryThresholdImageFilter<ImageType, SegmentationType> ThresholdFilterType;
164 
165  if (typeid(TPixel) != typeid(float) && typeid(TPixel) != typeid(double))
166  {
167  // round the thresholds if we have nor a float or double image
168  lower = std::floor(lower + 0.5);
169  upper = std::floor(upper - 0.5);
170  }
171  if (lower >= upper)
172  {
173  upper = lower;
174  }
175 
176  typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New();
177  filter->SetInput(originalImage);
178  filter->SetLowerThreshold(lower);
179  filter->SetUpperThreshold(upper);
180  filter->SetInsideValue(1);
181  filter->SetOutsideValue(0);
182  filter->Update();
183 
184  mitk::GrabItkImageMemory(filter->GetOutput(), result);
185 }
186 
188 {
189  this->m_SegmentationMask = segmentation;
190 }
191 
193 {
194  Superclass::GenerateOutputInformation();
195 }
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
#define AccessByItk_3(mitkImage, itkImageTypeFunction, arg1, arg2, arg3)
void ContourSearch(itk::Image< TPixel, VImageDimension > *originalImage, mitk::Image::Pointer &result)
itk::Image< unsigned char, 3 > ImageType
static Pointer New()
OutputType * GetOutput()
void ThreadedClosing(itk::Image< TPixel, VImageDimension > *originalImage, mitk::Image::Pointer &result)
#define AccessByItk_1(mitkImage, itkImageTypeFunction, arg1)
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
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.
static Pointer New()
#define MITK_WARN
Definition: mitkLogMacros.h:19
void ITKThresholding(const itk::Image< TPixel, VImageDimension > *originalImage, double lower, double upper, mitk::Image::Pointer &result)
mitk::Image::Pointer image
static Pointer New()
static const std::string STANDARDDEVIATION()
static void FillHoles(mitk::Image::Pointer &image)
Perform morphological operation on 2D, 3D or 3D+t segmentation.