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
itkIntelligentBinaryClosingFilter.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 #ifndef _itkIntelligentBinaryClosingFilter_txx
17 #define _itkIntelligentBinaryClosingFilter_txx
18 
19 #include "itkIntelligentBinaryClosingFilter.h"
20 #include <vector>
21 
22 namespace itk
23 {
24  template <class TInputImage, class TOutputImage>
25  IntelligentBinaryClosingFilter<TInputImage, TOutputImage>::IntelligentBinaryClosingFilter()
26  {
27  m_ErodeImageFilter = BinaryErodeImageFilterType::New();
28  m_DilateImageFilter = BinaryDilateImageFilterType::New();
29  m_SubtractImageFilter = SubtractImageFilterType::New();
30  m_ConnectedComponentImageFilter = ConnectedComponentImageFilterType::New();
31  m_RelabelComponentImageFilter = RelabelComponentImageFilterType::New();
32  m_RelabelComponentImageFilter->SetInPlace(true);
33  m_BorderDetectionDilateFilter = DilateComponentImageFilterType::New();
34  m_ClosingRadius = 4.0;
35  m_SurfaceRatio = 70;
36  }
37 
38  template <class TInputImage, class TOutputImage>
39  void IntelligentBinaryClosingFilter<TInputImage, TOutputImage>::GenerateData()
40  {
41  const InputImageType *input = this->GetInput();
42  // Allocate the output image.
43  typename OutputImageType::Pointer output = this->GetOutput();
44  output->SetRequestedRegion(input->GetRequestedRegion());
45  output->SetBufferedRegion(input->GetBufferedRegion());
46  output->SetLargestPossibleRegion(input->GetLargestPossibleRegion());
47  output->Allocate();
48 
49  // set up structuring element for closing
50  StructuringElementType seClosing;
51  unsigned long radius[ImageDimension];
52  const typename InputImageType::SpacingType spacing = input->GetSpacing();
53  for (unsigned int d = 0; d < ImageDimension; d++)
54  { // closing works in voxel coordinates, so use spacing (and add 0.5 for correct rounding - cast just truncates)
55  radius[d] = (unsigned long)(m_ClosingRadius / spacing[d] + 0.5);
56  }
57  MITK_INFO << " Closing kernel size = [" << radius[0] << ", " << radius[1] << ", " << radius[2] << "]"
58  << std::endl;
59  seClosing.SetRadius(radius);
60  seClosing.CreateStructuringElement();
61 
62  // closing
63  m_DilateImageFilter->SetInput(this->GetInput());
64  m_DilateImageFilter->SetKernel(seClosing);
65  m_DilateImageFilter->SetDilateValue(1);
66  m_ErodeImageFilter->SetInput(m_DilateImageFilter->GetOutput());
67  m_ErodeImageFilter->SetKernel(seClosing);
68  m_ErodeImageFilter->SetErodeValue(1);
69 
70  // subtraction
71  m_SubtractImageFilter->SetInput1(m_ErodeImageFilter->GetOutput());
72  m_SubtractImageFilter->SetInput2(this->GetInput());
73 
74  // connected components
75  m_ConnectedComponentImageFilter->SetInput(m_SubtractImageFilter->GetOutput());
76  m_RelabelComponentImageFilter->SetInput(m_ConnectedComponentImageFilter->GetOutput());
77  m_RelabelComponentImageFilter->Update();
78 
79  // set up structuring element for border voxel detection
80  StructuringElementType seBorder;
81  for (auto &radiu : radius)
82  {
83  radiu = 1;
84  }
85  seBorder.SetRadius(radius);
86  seBorder.CreateStructuringElement();
87 
88  // dilate all components to detect border voxels
89  m_BorderDetectionDilateFilter->SetInput(m_RelabelComponentImageFilter->GetOutput());
90  m_BorderDetectionDilateFilter->SetKernel(seBorder);
91  m_BorderDetectionDilateFilter->Update();
92 
93  // count volumes and border voxels for all components
94  OutputIteratorType itComp(m_RelabelComponentImageFilter->GetOutput(),
95  m_RelabelComponentImageFilter->GetOutput()->GetLargestPossibleRegion());
96  OutputIteratorType itBorder(m_BorderDetectionDilateFilter->GetOutput(),
97  m_BorderDetectionDilateFilter->GetOutput()->GetLargestPossibleRegion());
98  ConstInputIteratorType itIn(input, input->GetLargestPossibleRegion());
99 
100  std::vector<unsigned int> volume(m_RelabelComponentImageFilter->GetNumberOfObjects() + 1, 0);
101  std::vector<unsigned int> border(m_RelabelComponentImageFilter->GetNumberOfObjects() + 1, 0);
102  std::vector<unsigned int> adjacent(m_RelabelComponentImageFilter->GetNumberOfObjects() + 1, 0);
103  typename OutputImageType::ValueType borderId, compId;
104  for (itComp.GoToBegin(), itBorder.GoToBegin(), itIn.GoToBegin(); !itComp.IsAtEnd(); ++itComp, ++itBorder, ++itIn)
105  {
106  borderId = itBorder.Get();
107  if (borderId != 0)
108  {
109  compId = itComp.Get();
110  if (compId != 0)
111  {
112  volume[compId]++;
113  }
114  else
115  {
116  // this is border country
117  border[borderId]++;
118  if (itIn.Get() != 0)
119  adjacent[borderId]++;
120  }
121  }
122  }
123 
124  // calculate ratios
125  std::vector<float> ratio(m_RelabelComponentImageFilter->GetNumberOfObjects() + 1, 0);
126  MITK_INFO << " " << m_RelabelComponentImageFilter->GetNumberOfObjects() << " components found" << std::endl;
127  for (unsigned int i = 0; i < ratio.size(); i++)
128  {
129  if (border[i] != 0)
130  ratio[i] = 100.0 * (float)(adjacent[i]) / (float)(border[i]);
131  }
132 
133  // fill output
134  OutputIteratorType itOut(output, output->GetLargestPossibleRegion());
135  for (itOut.GoToBegin(), itIn.GoToBegin(), itComp.GoToBegin(); !itOut.IsAtEnd(); ++itOut, ++itIn, ++itComp)
136  {
137  if (itIn.Get() != 0)
138  {
139  itOut.Set(1);
140  }
141  else
142  {
143  compId = itComp.Get();
144  if (ratio[compId] > m_SurfaceRatio)
145  itOut.Set(1);
146  else
147  itOut.Set(0);
148  }
149  }
150  }
151 
152  template <class TInputImage, class TOutputImage>
153  void IntelligentBinaryClosingFilter<TInputImage, TOutputImage>::PrintSelf(std::ostream &os, Indent indent) const
154  {
155  Superclass::PrintSelf(os, indent);
156  }
157 
158 } // end namespace itk
159 
160 #endif