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 #ifndef itkMergeLabelMapFilter_hxx
19 #define itkMergeLabelMapFilter_hxx
20
21 #include "itkMergeLabelMapFilter.h"
22 #include "itkProgressReporter.h"
23 #include <deque>
24
25 namespace itk
26 {
27 template< typename TImage >
28 MergeLabelMapFilter< TImage >
MergeLabelMapFilter()29 ::MergeLabelMapFilter()
30 {
31 this->m_Method = KEEP;
32 }
33
34 template< typename TImage >
35 void
36 MergeLabelMapFilter< TImage >
GenerateData()37 ::GenerateData()
38 {
39 // Allocate the output
40 this->AllocateOutputs();
41
42 switch ( this->m_Method )
43 {
44 case KEEP:
45 {
46 this->MergeWithKeep();
47 break;
48 }
49 case AGGREGATE:
50 {
51 this->MergeWithAggregate();
52 break;
53 }
54 case PACK:
55 {
56 this->MergeWithPack();
57 break;
58 }
59 case STRICT:
60 {
61 this->MergeWithStrict();
62 break;
63 }
64 default:
65 {
66 itkExceptionMacro(<< "No such method: " << this->m_Method);
67 }
68 }
69 }
70
71 template< typename TImage >
72 void
73 MergeLabelMapFilter< TImage >
MergeWithKeep()74 ::MergeWithKeep()
75 {
76 ImageType *output = this->GetOutput();
77
78 using VectorType = std::deque< LabelObjectPointer >;
79 VectorType labelObjects;
80
81 ProgressReporter progress(this, 0, 1);
82
83 for ( unsigned int i = 1; i < this->GetNumberOfIndexedInputs(); i++ )
84 {
85 typename ImageType::ConstIterator it2( this->GetInput(i) );
86 while ( ! it2.IsAtEnd() )
87 {
88 const LabelObjectType *lo = it2.GetLabelObject();
89 LabelObjectPointer newLo = LabelObjectType::New();
90 newLo->template CopyAllFrom<LabelObjectType>(lo);
91
92 if( ( output->GetBackgroundValue() != newLo->GetLabel() ) &&
93 ( !output->HasLabel( newLo->GetLabel() ) ) )
94 {
95 // we can keep the label
96 output->AddLabelObject(newLo);
97 }
98 else
99 {
100 // store the label object to read it later with another label
101 labelObjects.push_back(newLo);
102 }
103
104 // go to the next label
105 progress.CompletedPixel();
106 ++it2;
107 }
108
109 // add the other label objects, with a different label
110 auto it = labelObjects.begin();
111 while ( it != labelObjects.end() )
112 {
113 output->PushLabelObject(*it);
114 ++it;
115 }
116 }
117 }
118
119 template< typename TImage >
120 void
121 MergeLabelMapFilter< TImage >
MergeWithStrict()122 ::MergeWithStrict()
123 {
124 ImageType *output = this->GetOutput();
125
126 ProgressReporter progress(this, 0, 1);
127
128 for ( unsigned int i = 1; i < this->GetNumberOfIndexedInputs(); i++ )
129 {
130 typename ImageType::ConstIterator it2( this->GetInput(i) );
131 while ( ! it2.IsAtEnd() )
132 {
133 const LabelObjectType *lo = it2.GetLabelObject();
134 LabelObjectPointer newLo = LabelObjectType::New();
135 newLo->template CopyAllFrom<LabelObjectType>(lo);
136
137 if ( output->GetBackgroundValue() != newLo->GetLabel() )
138 {
139 if ( !output->HasLabel( newLo->GetLabel() ) )
140 {
141 // we can keep the label
142 output->AddLabelObject(newLo);
143 }
144 else
145 {
146 itkExceptionMacro(<< "Label "
147 << static_cast< typename itk::NumericTraits< PixelType >::PrintType >( newLo->GetLabel() )
148 << " from input " << i
149 << " is already in use.");
150 }
151 }
152 else
153 {
154 itkGenericExceptionMacro(<<"Label "
155 << static_cast< typename itk::NumericTraits< PixelType >::PrintType >( newLo->GetLabel() )
156 << " from input " << i
157 << " is output background value.");
158 }
159
160 // go to the next label
161 progress.CompletedPixel();
162 ++it2;
163 }
164 }
165 }
166
167 template< typename TImage >
168 void
169 MergeLabelMapFilter< TImage >
MergeWithAggregate()170 ::MergeWithAggregate()
171 {
172 ImageType *output = this->GetOutput();
173
174 ProgressReporter progress(this, 0, 1);
175
176 for ( unsigned int i = 1; i < this->GetNumberOfIndexedInputs(); i++ )
177 {
178 typename ImageType::ConstIterator it2( this->GetInput(i) );
179 while ( ! it2.IsAtEnd() )
180 {
181 const LabelObjectType *lo = it2.GetLabelObject();
182
183 bool hasLabel = output->HasLabel( lo->GetLabel() );
184 if ( !hasLabel && ( lo->GetLabel() != output->GetBackgroundValue() ) )
185 {
186 // we can keep the label
187 LabelObjectPointer newLo = LabelObjectType::New();
188 newLo->template CopyAllFrom<LabelObjectType>(lo);
189 output->AddLabelObject(newLo);
190 }
191 else
192 {
193 if ( hasLabel )
194 {
195 // add the lines of that object to the one already in the output
196 LabelObjectType * mainLo = output->GetLabelObject( lo->GetLabel() );
197 typename LabelObjectType::ConstLineIterator lit( lo );
198 while ( ! lit.IsAtEnd() )
199 {
200 mainLo->AddLine( lit.GetLine() );
201 ++lit;
202 }
203
204 // be sure to have the lines well organized
205 mainLo->Optimize();
206 }
207 }
208
209 // go to the next label
210 progress.CompletedPixel();
211 ++it2;
212 }
213 }
214 }
215
216 template< typename TImage >
217 void
218 MergeLabelMapFilter< TImage >
MergeWithPack()219 ::MergeWithPack()
220 {
221 ProgressReporter progress(this, 0, 1);
222
223 ImageType *output = this->GetOutput();
224
225 // get the label objects of the first input
226 typename ImageType::LabelObjectVectorType labelObjects = output->GetLabelObjects();
227
228 // and put back the objects in the map
229 output->ClearLabels();
230
231 auto it = labelObjects.begin();
232
233 while ( it != labelObjects.end() )
234 {
235 output->PushLabelObject(*it);
236
237 // go to the next label
238 progress.CompletedPixel();
239 it++;
240 }
241
242 // now, the next images
243 for ( unsigned int i = 1; i < this->GetNumberOfIndexedInputs(); i++ )
244 {
245 typename ImageType::ConstIterator it2( this->GetInput(i) );
246 while ( ! it2.IsAtEnd() )
247 {
248 const LabelObjectType *lo = it2.GetLabelObject();
249 LabelObjectPointer newLo = LabelObjectType::New();
250 newLo->template CopyAllFrom<LabelObjectType>(lo);
251 output->PushLabelObject(newLo);
252
253 // go to the next label
254 progress.CompletedPixel();
255 ++it2;
256 }
257 }
258 }
259
260 template< typename TImage >
261 void
262 MergeLabelMapFilter< TImage >
PrintSelf(std::ostream & os,Indent indent) const263 ::PrintSelf(std::ostream & os, Indent indent) const
264 {
265 Superclass::PrintSelf(os, indent);
266
267 os << indent << "Method: " << this->m_Method << std::endl;
268 }
269 } // end namespace itk
270 #endif
271