1 /*===================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 See LICENSE.txt or http://www.mitk.org for details.
15 ===================================================================*/
16 #ifndef _itkIntelligentBinaryClosingFilter_txx
17 #define _itkIntelligentBinaryClosingFilter_txx
19 #include "itkIntelligentBinaryClosingFilter.h"
24 template <class TInputImage, class TOutputImage>
25 IntelligentBinaryClosingFilter<TInputImage, TOutputImage>::IntelligentBinaryClosingFilter()
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;
38 template <class TInputImage, class TOutputImage>
39 void IntelligentBinaryClosingFilter<TInputImage, TOutputImage>::GenerateData()
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());
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);
57 MITK_INFO << " Closing kernel size = [" << radius[0] << ", " << radius[1] << ", " << radius[2] << "]"
59 seClosing.SetRadius(radius);
60 seClosing.CreateStructuringElement();
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);
71 m_SubtractImageFilter->SetInput1(m_ErodeImageFilter->GetOutput());
72 m_SubtractImageFilter->SetInput2(this->GetInput());
74 // connected components
75 m_ConnectedComponentImageFilter->SetInput(m_SubtractImageFilter->GetOutput());
76 m_RelabelComponentImageFilter->SetInput(m_ConnectedComponentImageFilter->GetOutput());
77 m_RelabelComponentImageFilter->Update();
79 // set up structuring element for border voxel detection
80 StructuringElementType seBorder;
81 for (auto &radiu : radius)
85 seBorder.SetRadius(radius);
86 seBorder.CreateStructuringElement();
88 // dilate all components to detect border voxels
89 m_BorderDetectionDilateFilter->SetInput(m_RelabelComponentImageFilter->GetOutput());
90 m_BorderDetectionDilateFilter->SetKernel(seBorder);
91 m_BorderDetectionDilateFilter->Update();
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());
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)
106 borderId = itBorder.Get();
109 compId = itComp.Get();
116 // this is border country
119 adjacent[borderId]++;
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++)
130 ratio[i] = 100.0 * (float)(adjacent[i]) / (float)(border[i]);
134 OutputIteratorType itOut(output, output->GetLargestPossibleRegion());
135 for (itOut.GoToBegin(), itIn.GoToBegin(), itComp.GoToBegin(); !itOut.IsAtEnd(); ++itOut, ++itIn, ++itComp)
143 compId = itComp.Get();
144 if (ratio[compId] > m_SurfaceRatio)
152 template <class TInputImage, class TOutputImage>
153 void IntelligentBinaryClosingFilter<TInputImage, TOutputImage>::PrintSelf(std::ostream &os, Indent indent) const
155 Superclass::PrintSelf(os, indent);
158 } // end namespace itk