Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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