1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: itkLabelOverlapMeasuresImageFilter.txx,v $
9 Copyright (c) Insight Software Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #ifndef _itkLabelOverlapMeasuresImageFilter_txx
18 #define _itkLabelOverlapMeasuresImageFilter_txx
20 #include "itkLabelOverlapMeasuresImageFilter.h"
22 #include "itkImageRegionConstIterator.h"
23 #include "itkProgressReporter.h"
27 #if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95
28 /** Used for mutex locking */
29 #define LOCK_HASHMAP this->m_Mutex.Lock()
30 #define UNLOCK_HASHMAP this->m_Mutex.Unlock()
33 #define UNLOCK_HASHMAP
36 template<class TLabelImage>
37 LabelOverlapMeasuresImageFilter<TLabelImage>
38 ::LabelOverlapMeasuresImageFilter()
40 // this filter requires two input images
41 this->SetNumberOfRequiredInputs( 2 );
44 template<class TLabelImage>
46 LabelOverlapMeasuresImageFilter<TLabelImage>
47 ::GenerateInputRequestedRegion()
49 Superclass::GenerateInputRequestedRegion();
50 if( this->GetSourceImage() )
52 LabelImagePointer source = const_cast
53 <LabelImageType *>( this->GetSourceImage() );
54 source->SetRequestedRegionToLargestPossibleRegion();
56 if( this->GetTargetImage() )
58 LabelImagePointer target = const_cast
59 <LabelImageType *>( this->GetTargetImage() );
60 target->SetRequestedRegionToLargestPossibleRegion();
64 template<class TLabelImage>
66 LabelOverlapMeasuresImageFilter<TLabelImage>
67 ::EnlargeOutputRequestedRegion( DataObject *data )
69 Superclass::EnlargeOutputRequestedRegion( data );
70 data->SetRequestedRegionToLargestPossibleRegion();
74 template<class TLabelImage>
76 LabelOverlapMeasuresImageFilter<TLabelImage>
79 // Pass the source through as the output
80 LabelImagePointer image =
81 const_cast<TLabelImage *>( this->GetSourceImage() );
82 this->SetNthOutput( 0, image );
84 // Nothing that needs to be allocated for the remaining outputs
87 template<class TLabelImage>
89 LabelOverlapMeasuresImageFilter<TLabelImage>
90 ::BeforeThreadedGenerateData()
92 int numberOfThreads = this->GetNumberOfThreads();
94 // Resize the thread temporaries
95 this->m_LabelSetMeasuresPerThread.resize( numberOfThreads );
97 // Initialize the temporaries
98 for( int n = 0; n < numberOfThreads; n++ )
100 this->m_LabelSetMeasuresPerThread[n].clear();
103 // Initialize the final map
104 this->m_LabelSetMeasures.clear();
107 template<class TLabelImage>
109 LabelOverlapMeasuresImageFilter<TLabelImage>
110 ::AfterThreadedGenerateData()
112 // Run through the map for each thread and accumulate the set measures.
113 for( int n = 0; n < this->GetNumberOfThreads(); n++ )
115 // iterate over the map for this thread
116 for( MapConstIterator threadIt = this->m_LabelSetMeasuresPerThread[n].begin();
117 threadIt != this->m_LabelSetMeasuresPerThread[n].end();
120 // does this label exist in the cumulative stucture yet?
121 MapIterator mapIt = this->m_LabelSetMeasures.find( ( *threadIt ).first );
122 if( mapIt == this->m_LabelSetMeasures.end() )
124 // create a new entry
125 typedef typename MapType::value_type MapValueType;
126 mapIt = this->m_LabelSetMeasures.insert( MapValueType(
127 (*threadIt).first, LabelSetMeasures() ) ).first;
130 // accumulate the information from this thread
131 (*mapIt).second.m_Source += (*threadIt).second.m_Source;
132 (*mapIt).second.m_Target += (*threadIt).second.m_Target;
133 (*mapIt).second.m_Union += (*threadIt).second.m_Union;
134 (*mapIt).second.m_Intersection +=
135 (*threadIt).second.m_Intersection;
136 (*mapIt).second.m_SourceComplement +=
137 (*threadIt).second.m_SourceComplement;
138 (*mapIt).second.m_TargetComplement +=
139 (*threadIt).second.m_TargetComplement;
140 } // end of thread map iterator loop
141 } // end of thread loop
144 template<class TLabelImage>
146 LabelOverlapMeasuresImageFilter<TLabelImage>
147 ::ThreadedGenerateData( const RegionType& outputRegionForThread,
150 ImageRegionConstIterator<LabelImageType> ItS( this->GetSourceImage(),
151 outputRegionForThread );
152 ImageRegionConstIterator<LabelImageType> ItT( this->GetTargetImage(),
153 outputRegionForThread );
155 // support progress methods/callbacks
156 ProgressReporter progress( this, threadId,
157 2*outputRegionForThread.GetNumberOfPixels() );
159 for( ItS.GoToBegin(), ItT.GoToBegin(); !ItS.IsAtEnd(); ++ItS, ++ItT )
161 LabelType sourceLabel = ItS.Get();
162 LabelType targetLabel = ItT.Get();
164 // is the label already in this thread?
166 this->m_LabelSetMeasuresPerThread[threadId].find( sourceLabel );
168 this->m_LabelSetMeasuresPerThread[threadId].find( targetLabel );
170 if( mapItS == this->m_LabelSetMeasuresPerThread[threadId].end() )
172 // create a new label set measures object
173 typedef typename MapType::value_type MapValueType;
175 mapItS = this->m_LabelSetMeasuresPerThread[threadId].insert(
176 MapValueType( sourceLabel, LabelSetMeasures() ) ).first;
180 if( mapItT == this->m_LabelSetMeasuresPerThread[threadId].end() )
182 // create a new label set measures object
183 typedef typename MapType::value_type MapValueType;
185 mapItT = this->m_LabelSetMeasuresPerThread[threadId].insert(
186 MapValueType( targetLabel, LabelSetMeasures() ) ).first;
190 (*mapItS).second.m_Source++;
191 (*mapItT).second.m_Target++;
193 if( sourceLabel == targetLabel )
195 (*mapItS).second.m_Intersection++;
196 (*mapItS).second.m_Union++;
200 (*mapItS).second.m_Union++;
201 (*mapItT).second.m_Union++;
203 (*mapItS).second.m_SourceComplement++;
204 (*mapItT).second.m_TargetComplement++;
207 progress.CompletedPixel();
214 template<class TLabelImage>
215 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
216 LabelOverlapMeasuresImageFilter<TLabelImage>
219 RealType numerator = 0.0;
220 RealType denominator = 0.0;
221 for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
222 mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
224 // Do not include the background in the final value.
225 if( (*mapIt).first == NumericTraits<LabelType>::Zero )
229 numerator += static_cast<RealType>( (*mapIt).second.m_Intersection );
230 denominator += static_cast<RealType>( (*mapIt).second.m_Target );
232 return ( numerator / denominator );
235 template<class TLabelImage>
236 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
237 LabelOverlapMeasuresImageFilter<TLabelImage>
238 ::GetTargetOverlap( LabelType label )
240 MapIterator mapIt = this->m_LabelSetMeasures.find( label );
241 if( mapIt == this->m_LabelSetMeasures.end() )
243 itkWarningMacro( "Label " << label << " not found." );
247 static_cast<RealType>( (*mapIt).second.m_Intersection ) /
248 static_cast<RealType>( (*mapIt).second.m_Target );
252 template<class TLabelImage>
253 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
254 LabelOverlapMeasuresImageFilter<TLabelImage>
257 RealType numerator = 0.0;
258 RealType denominator = 0.0;
259 for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
260 mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
262 // Do not include the background in the final value.
263 if( (*mapIt).first == NumericTraits<LabelType>::Zero )
267 numerator += static_cast<RealType>( (*mapIt).second.m_Intersection );
268 denominator += static_cast<RealType>( (*mapIt).second.m_Union );
270 return ( numerator / denominator );
273 template<class TLabelImage>
274 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
275 LabelOverlapMeasuresImageFilter<TLabelImage>
276 ::GetUnionOverlap( LabelType label )
278 MapIterator mapIt = this->m_LabelSetMeasures.find( label );
279 if( mapIt == this->m_LabelSetMeasures.end() )
281 itkWarningMacro( "Label " << label << " not found." );
285 static_cast<RealType>( (*mapIt).second.m_Intersection ) /
286 static_cast<RealType>( (*mapIt).second.m_Union );
290 template<class TLabelImage>
291 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
292 LabelOverlapMeasuresImageFilter<TLabelImage>
295 RealType uo = this->GetUnionOverlap();
296 return ( 2.0 * uo / ( 1.0 + uo ) );
299 template<class TLabelImage>
300 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
301 LabelOverlapMeasuresImageFilter<TLabelImage>
302 ::GetMeanOverlap( LabelType label )
304 RealType uo = this->GetUnionOverlap( label );
305 return ( 2.0 * uo / ( 1.0 + uo ) );
308 template<class TLabelImage>
309 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
310 LabelOverlapMeasuresImageFilter<TLabelImage>
311 ::GetVolumeSimilarity()
313 RealType numerator = 0.0;
314 RealType denominator = 0.0;
315 for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
316 mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
318 // Do not include the background in the final value.
319 if( (*mapIt).first == NumericTraits<LabelType>::Zero )
323 numerator += ( ( static_cast<RealType>( (*mapIt).second.m_Source ) -
324 static_cast<RealType>( (*mapIt).second.m_Target ) ) );
325 denominator += ( ( static_cast<RealType>( (*mapIt).second.m_Source ) +
326 static_cast<RealType>( (*mapIt).second.m_Target ) ) );
328 return ( 2.0 * numerator / denominator );
331 template<class TLabelImage>
332 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
333 LabelOverlapMeasuresImageFilter<TLabelImage>
334 ::GetVolumeSimilarity( LabelType label )
336 MapIterator mapIt = this->m_LabelSetMeasures.find( label );
337 if( mapIt == this->m_LabelSetMeasures.end() )
339 itkWarningMacro( "Label " << label << " not found." );
342 RealType value = 2.0 *
343 ( static_cast<RealType>( (*mapIt).second.m_Source ) -
344 static_cast<RealType>( (*mapIt).second.m_Target ) ) /
345 ( static_cast<RealType>( (*mapIt).second.m_Source ) +
346 static_cast<RealType>( (*mapIt).second.m_Target ) );
350 template<class TLabelImage>
351 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
352 LabelOverlapMeasuresImageFilter<TLabelImage>
353 ::GetFalseNegativeError()
355 RealType numerator = 0.0;
356 RealType denominator = 0.0;
357 for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
358 mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
360 // Do not include the background in the final value.
361 if( (*mapIt).first == NumericTraits<LabelType>::Zero )
365 numerator += static_cast<RealType>( (*mapIt).second.m_TargetComplement );
366 denominator += static_cast<RealType>( (*mapIt).second.m_Target );
368 return ( numerator / denominator );
371 template<class TLabelImage>
372 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
373 LabelOverlapMeasuresImageFilter<TLabelImage>
374 ::GetFalseNegativeError( LabelType label )
376 MapIterator mapIt = this->m_LabelSetMeasures.find( label );
377 if( mapIt == this->m_LabelSetMeasures.end() )
379 itkWarningMacro( "Label " << label << " not found." );
383 static_cast<RealType>( (*mapIt).second.m_TargetComplement ) /
384 static_cast<RealType>( (*mapIt).second.m_Target );
388 template<class TLabelImage>
389 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
390 LabelOverlapMeasuresImageFilter<TLabelImage>
391 ::GetFalsePositiveError()
393 RealType numerator = 0.0;
394 RealType denominator = 0.0;
395 for( MapIterator mapIt = this->m_LabelSetMeasures.begin();
396 mapIt != this->m_LabelSetMeasures.end(); ++mapIt )
398 // Do not include the background in the final value.
399 if( (*mapIt).first == NumericTraits<LabelType>::Zero )
403 numerator += static_cast<RealType>( (*mapIt).second.m_SourceComplement );
404 denominator += static_cast<RealType>( (*mapIt).second.m_Source );
406 return ( numerator / denominator );
409 template<class TLabelImage>
410 typename LabelOverlapMeasuresImageFilter<TLabelImage>::RealType
411 LabelOverlapMeasuresImageFilter<TLabelImage>
412 ::GetFalsePositiveError( LabelType label )
414 MapIterator mapIt = this->m_LabelSetMeasures.find( label );
415 if( mapIt == this->m_LabelSetMeasures.end() )
417 itkWarningMacro( "Label " << label << " not found." );
421 static_cast<RealType>( (*mapIt).second.m_SourceComplement ) /
422 static_cast<RealType>( (*mapIt).second.m_Source );
426 template<class TLabelImage>
428 LabelOverlapMeasuresImageFilter<TLabelImage>
429 ::PrintSelf( std::ostream& os, Indent indent ) const
431 Superclass::PrintSelf( os, indent );
436 }// end namespace itk