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
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,
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 
18 
20 #include <mitkITKImageImport.h>
21 #include <mitkImage.h>
22 #include <mitkImageAccessByItk.h>
23 #include <mitkImageStatisticsCalculator.h>
25 #include <mitkProgressBar.h>
26 #include <mitkUnstructuredGrid.h>
28 #include <mitkImageMaskGenerator.h>
29 
30 #include <itkBinaryBallStructuringElement.h>
31 #include <itkBinaryContourImageFilter.h>
32 #include <itkBinaryThresholdImageFilter.h>
33 #include <itkDilateObjectMorphologyImageFilter.h>
34 #include <itkErodeObjectMorphologyImageFilter.h>
35 #include <itkImage.h>
36 
38 {
39  this->SetNumberOfRequiredInputs(1);
40 
41  this->SetNumberOfIndexedOutputs(1);
42 }
43 
45 {
46 }
47 
49 {
51 
52  if (m_SegmentationMask.IsNull())
53  {
54  MITK_WARN << "Please set a segmentation mask first" << std::endl;
55  return;
56  }
57  // First create a threshold segmentation of the image. The threshold is determined
58  // by the mean +/- stddev of the pixel values that are covered by the segmentation mask
59 
60  // Compute mean and stdDev based on the current segmentation
62  statCalc->SetInputImage(image);
63 
65  imgMask->SetImageMask(m_SegmentationMask);
66 
67  mitk::ImageStatisticsCalculator::StatisticsContainer::Pointer stats = statCalc->GetStatistics();
68  double mean = stats->GetMean();
69  double stdDev = stats->GetStd();
70 
71  double upperThreshold = mean + stdDev;
72  double lowerThreshold = mean - stdDev;
73 
74  // Perform thresholding
75  mitk::Image::Pointer thresholdImage = mitk::Image::New();
76  AccessByItk_3(image.GetPointer(), ITKThresholding, lowerThreshold, upperThreshold, thresholdImage)
77 
79  ->Progress(2);
80 
81  // Postprocess threshold segmentation
82  // First a closing will be executed
83  mitk::Image::Pointer closedImage = mitk::Image::New();
84  AccessByItk_1(thresholdImage, ThreadedClosing, closedImage);
85 
86  // Then we will holes that might exist
88 
90 
91  // Extract the binary edges of the resulting segmentation
93  AccessByItk_1(closedImage, ContourSearch, edgeImage);
94 
95  // Convert the edge image into an unstructured grid
97  i2UFilter->SetInput(edgeImage);
98  i2UFilter->SetThreshold(1.0);
99  i2UFilter->Update();
100 
101  m_PointGrid = this->GetOutput();
102  if (m_PointGrid.IsNull())
103  m_PointGrid = mitk::UnstructuredGrid::New();
104 
105  m_PointGrid->SetVtkUnstructuredGrid(i2UFilter->GetOutput()->GetVtkUnstructuredGrid());
106 
108 }
109 
110 template <typename TPixel, unsigned int VImageDimension>
111 void mitk::FeatureBasedEdgeDetectionFilter::ThreadedClosing(itk::Image<TPixel, VImageDimension> *originalImage,
112  mitk::Image::Pointer &result)
113 {
114  typedef itk::BinaryBallStructuringElement<TPixel, VImageDimension> myKernelType;
115 
116  myKernelType ball;
117  ball.SetRadius(1);
118  ball.CreateStructuringElement();
119 
120  typedef typename itk::Image<TPixel, VImageDimension> ImageType;
121 
124  dilationFilter->SetInput(originalImage);
125  dilationFilter->SetKernel(ball);
126  dilationFilter->Update();
127 
128  typename itk::Image<TPixel, VImageDimension>::Pointer dilatedImage = dilationFilter->GetOutput();
129 
132  erodeFilter->SetInput(dilatedImage);
133  erodeFilter->SetKernel(ball);
134  erodeFilter->Update();
135 
136  mitk::GrabItkImageMemory(erodeFilter->GetOutput(), result);
137 }
138 
139 template <typename TPixel, unsigned int VImageDimension>
140 void mitk::FeatureBasedEdgeDetectionFilter::ContourSearch(itk::Image<TPixel, VImageDimension> *originalImage,
141  mitk::Image::Pointer &result)
142 {
143  typedef itk::Image<TPixel, VImageDimension> ImageType;
144  typedef itk::BinaryContourImageFilter<ImageType, ImageType> binaryContourImageFilterType;
145  typedef unsigned short OutputPixelType;
146  typedef itk::Image<OutputPixelType, VImageDimension> OutputImageType;
147 
149  binaryContourFilter->SetInput(originalImage);
150  binaryContourFilter->SetForegroundValue(1);
151  binaryContourFilter->SetBackgroundValue(0);
152  binaryContourFilter->Update();
153 
155  itkImage->Graft(binaryContourFilter->GetOutput());
156 
157  mitk::GrabItkImageMemory(itkImage, result);
158 }
159 
160 template <typename TPixel, unsigned int VImageDimension>
161 void mitk::FeatureBasedEdgeDetectionFilter::ITKThresholding(itk::Image<TPixel, VImageDimension> *originalImage,
162  double lower,
163  double upper,
164  mitk::Image::Pointer &result)
165 {
166  typedef itk::Image<TPixel, VImageDimension> ImageType;
167  typedef itk::Image<unsigned short, VImageDimension> SegmentationType;
168  typedef itk::BinaryThresholdImageFilter<ImageType, SegmentationType> ThresholdFilterType;
169 
170  if (typeid(TPixel) != typeid(float) && typeid(TPixel) != typeid(double))
171  {
172  // round the thresholds if we have nor a float or double image
173  lower = std::floor(lower + 0.5);
174  upper = std::floor(upper - 0.5);
175  }
176  if (lower >= upper)
177  {
178  upper = lower;
179  }
180 
182  filter->SetInput(originalImage);
183  filter->SetLowerThreshold(lower);
184  filter->SetUpperThreshold(upper);
185  filter->SetInsideValue(1);
186  filter->SetOutsideValue(0);
187  filter->Update();
188 
189  mitk::GrabItkImageMemory(filter->GetOutput(), result);
190 }
191 
193 {
194  this->m_SegmentationMask = segmentation;
195 }
196 
198 {
199  Superclass::GenerateOutputInformation();
200 }
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
#define AccessByItk_3(mitkImage, itkImageTypeFunction, arg1, arg2, arg3)
itk::SmartPointer< Self > Pointer
void ContourSearch(itk::Image< TPixel, VImageDimension > *originalImage, mitk::Image::Pointer &result)
void ITKThresholding(itk::Image< TPixel, VImageDimension > *originalImage, double lower, double upper, mitk::Image::Pointer &result)
static Pointer New()
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()
map::core::discrete::Elements< 3 >::InternalImageType ImageType
#define MITK_WARN
Definition: mitkLogMacros.h:23
static Pointer New()
static void ITKThresholding(itk::Image< TPixel, VImageDimension > *originalImage, mitk::Image *segmentation, double lower, double upper, unsigned int timeStep)
static Pointer New()
static void FillHoles(mitk::Image::Pointer &image)
Perform morphological operation on 2D, 3D or 3D+t segmentation.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.