1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #ifndef itkLevelSetDomainMapImageFilter_hxx
20 #define itkLevelSetDomainMapImageFilter_hxx
21 
22 #include "itkLevelSetDomainMapImageFilter.h"
23 
24 namespace itk
25 {
26 template < typename TInputImage, typename TOutputImage >
27 LevelSetDomainMapImageFilter< TInputImage, TOutputImage >
LevelSetDomainMapImageFilter()28 ::LevelSetDomainMapImageFilter()
29 {
30   this->Superclass::SetNumberOfRequiredInputs ( 1 );
31   this->Superclass::SetNumberOfRequiredOutputs ( 1 );
32   this->m_InputImage = nullptr;
33   this->m_OutputImage = nullptr;
34 }
35 
36 template < typename TInputImage, typename TOutputImage >
37 const typename LevelSetDomainMapImageFilter< TInputImage, TOutputImage >::DomainMapType &
38 LevelSetDomainMapImageFilter< TInputImage, TOutputImage >
GetDomainMap() const39 ::GetDomainMap() const
40 {
41   return this->m_DomainMap;
42 }
43 
44 template < typename TInputImage, typename TOutputImage >
45 typename LevelSetDomainMapImageFilter< TInputImage, TOutputImage >::InputImageRegionType
46 LevelSetDomainMapImageFilter< TInputImage, TOutputImage >
ComputeConsistentRegion(const InputImageRegionType & inputRegion) const47 ::ComputeConsistentRegion( const InputImageRegionType & inputRegion ) const
48 {
49   bool regionWasModified = false;
50 
51   InputImageRegionType subRegion = inputRegion;
52 
53   do
54     {
55     regionWasModified = false;
56 
57     InputConstIteratorType  iIt( this->m_InputImage, subRegion );
58     OutputConstIteratorType oIt( this->m_OutputImage, subRegion );
59 
60     iIt.GoToBegin();
61     oIt.GoToBegin();
62 
63     const InputImagePixelType firstCornerPixelValue = iIt.Get();
64     const InputImageIndexType & firstCornerIndex = iIt.GetIndex();
65 
66     while( !iIt.IsAtEnd() )
67       {
68       const OutputImagePixelType segmentPixel = oIt.Get();
69       const InputImagePixelType nextPixel = iIt.Get();
70 
71       if ( ( nextPixel != firstCornerPixelValue ) ||
72            ( segmentPixel != NumericTraits< OutputImagePixelType >::ZeroValue() ) )
73         {
74         const InputImageIndexType & stopIdx = iIt.GetIndex();
75         InputImageSizeType sizeOfRegion;
76         for( unsigned int i = 0; i < ImageDimension; i++ )
77           {
78           sizeOfRegion[i] = stopIdx[i] - firstCornerIndex[i] + 1;
79           }
80         subRegion.SetSize(sizeOfRegion);
81 
82         regionWasModified = true;
83         break;
84         }
85 
86       ++iIt;
87       ++oIt;
88       }
89     }
90   while( regionWasModified );
91 
92   return subRegion;
93 }
94 
95 
96 template < typename TInputImage, typename TOutputImage >
97 void
98 LevelSetDomainMapImageFilter< TInputImage, TOutputImage >::
GenerateData()99 GenerateData()
100 {
101   // Clear any prior contents.
102   this->m_DomainMap.clear();
103 
104   this->m_InputImage =  this->GetInput();
105   const InputImageRegionType & region = this->m_InputImage->GetLargestPossibleRegion();
106   const InputImageSizeType size = region.GetSize();
107 
108   this->m_OutputImage = this->GetOutput();
109   this->m_OutputImage->SetBufferedRegion( region );
110   this->m_OutputImage->Allocate();
111   this->m_OutputImage->FillBuffer( NumericTraits< OutputImagePixelType >::ZeroValue() );
112 
113   InputImageIndexType end;
114 
115   for( unsigned int i = 0; i < ImageDimension; i++ )
116     {
117     end[i] = size[i] - 1;
118     }
119 
120   IdentifierType segmentId = NumericTraits<IdentifierType>::OneValue();
121 
122   InputConstIteratorType iIt( this->m_InputImage, region );
123   OutputIndexIteratorType oIt( this->m_OutputImage, region );
124 
125   iIt.GoToBegin();
126   oIt.GoToBegin();
127 
128   while( !iIt.IsAtEnd() )
129     {
130     const InputImageIndexType & startIdx     = iIt.GetIndex();
131     InputImageIndexType stopIdx              = startIdx;
132     const InputImagePixelType & inputPixel   = iIt.Get();
133     const OutputImagePixelType & outputPixel = oIt.Get();
134 
135     // outputPixel is null when it has not been processed yet,
136     // or there is nothing to be processed
137     if ( ( !inputPixel.empty() ) && ( outputPixel == NumericTraits<OutputImagePixelType>::ZeroValue() ) )
138       {
139       InputImageRegionType subRegion;
140       InputImageSizeType sizeOfRegion;
141 
142       for( unsigned int i = 0; i < ImageDimension; i++ )
143         {
144         bool sameOverlappingLevelSetIds = true;
145         stopIdx = startIdx;
146         while ( ( sameOverlappingLevelSetIds ) && ( stopIdx[i] <= end[i] ) )
147           {
148           const InputImagePixelType & nextPixel = this->m_InputImage->GetPixel( stopIdx );
149           const OutputImagePixelType & currentOutputPixel = this->m_OutputImage->GetPixel( stopIdx );
150 
151           // Check if the input list pixels are different, or
152           // the output image already has been assigned to another region
153           if ( ( nextPixel != inputPixel ) ||
154                ( currentOutputPixel != NumericTraits< OutputImagePixelType >::ZeroValue() ) )
155             {
156             sameOverlappingLevelSetIds = false;
157             }
158           else
159             {
160             ++stopIdx[i];
161             }
162           }
163         sizeOfRegion[i] = stopIdx[i] - startIdx[i];
164         }
165 
166       subRegion.SetSize( sizeOfRegion );
167       subRegion.SetIndex( startIdx );
168 
169       // Compute the consistent subregion
170       subRegion = this->ComputeConsistentRegion( subRegion );
171 
172       this->m_DomainMap[segmentId] = LevelSetDomain( subRegion, inputPixel );
173 
174       OutputIndexIteratorType ooIt( this->m_OutputImage, subRegion );
175       ooIt.GoToBegin();
176 
177       while( !ooIt.IsAtEnd() )
178         {
179         ooIt.Set( segmentId );
180         ++ooIt;
181         }
182       ++segmentId;
183       }
184     ++iIt;
185     ++oIt;
186     }
187 }
188 
189 template < typename TInputImage, typename TOutputImage >
190 void
191 LevelSetDomainMapImageFilter< TInputImage, TOutputImage >::
PrintSelf(std::ostream & os,Indent indent) const192 PrintSelf ( std::ostream& os, Indent indent ) const
193 {
194   Superclass::PrintSelf ( os,indent );
195   os << indent << "DomainMap size: " << this->m_DomainMap.size() << std::endl;
196 }
197 
198 } /* end namespace itk */
199 
200 #endif
201