diff --git a/Utilities/ITK/Code/Review/itkBinaryImageToLabelMapFilter.h b/Utilities/ITK/Code/Review/itkBinaryImageToLabelMapFilter.h index 49c20b056664248c5df1864dcd3dff3ff64a038d..8835e6d8cf208bbc81923c9248a67ca31e21010f 100644 --- a/Utilities/ITK/Code/Review/itkBinaryImageToLabelMapFilter.h +++ b/Utilities/ITK/Code/Review/itkBinaryImageToLabelMapFilter.h @@ -26,8 +26,6 @@ #include "itkProgressReporter.h" #include "itkBarrier.h" -//patch OTB -#include "itkLabelMap.h" namespace itk { diff --git a/Utilities/InsightJournal/itkAttributeKeepNObjectsLabelMapFilter.h b/Utilities/InsightJournal/itkAttributeKeepNObjectsLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..4c212e8f37dfc5fcd13dbb34b61c71d217c10be3 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeKeepNObjectsLabelMapFilter.h @@ -0,0 +1,141 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeKeepNObjectsLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeKeepNObjectsLabelMapFilter_h +#define __itkAttributeKeepNObjectsLabelMapFilter_h + +#include "itkInPlaceLabelMapFilter.h" +#include "itkAttributeLabelObject.h" + +namespace itk { +/** \class AttributeKeepNObjectsLabelMapFilter + * \brief keep N objects according to their attribute + * + * AttributeKeepNObjectsLabelMapFilter keep the N objects in a label collection image + * with the highest (or lowest) attribute value. The attribute is provide by an + * attribute accessor given in template parameter. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT AttributeKeepNObjectsLabelMapFilter : + public InPlaceLabelMapFilter<TImage> +{ +public: + /** Standard class typedefs. */ + typedef AttributeKeepNObjectsLabelMapFilter Self; + typedef InPlaceLabelMapFilter<TImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + typedef typename ImageType::LabelObjectType LabelObjectType; + + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(AttributeKeepNObjectsLabelMapFilter, + InPlaceLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>));*/ + /** End concept checking */ +#endif + + /** + * Set/Get the ordering of the objects. By default, the ones with the + * highest value are kept. Turming ReverseOrdering to true make this filter + * keep the objects with the smallest values + */ + itkSetMacro( ReverseOrdering, bool ); + itkGetConstReferenceMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + + /** + * Set/Get the number of objects to keep + */ + itkSetMacro( NumberOfObjects, unsigned long ); + itkGetConstReferenceMacro( NumberOfObjects, unsigned long ); + +protected: + AttributeKeepNObjectsLabelMapFilter(); + ~AttributeKeepNObjectsLabelMapFilter() {}; + + void GenerateData(); + + void PrintSelf(std::ostream& os, Indent indent) const; + + class ReverseComparator + { + public: + bool operator()( const typename LabelObjectType::Pointer & a, const typename LabelObjectType::Pointer & b ) + { + return accessor( a ) < accessor( b ); + } + AttributeAccessorType accessor; + }; + + class Comparator + { + public: + bool operator()( const typename LabelObjectType::Pointer & a, const typename LabelObjectType::Pointer & b ) + { + return accessor( a ) > accessor( b ); + } + AttributeAccessorType accessor; + }; + +private: + AttributeKeepNObjectsLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_ReverseOrdering; + unsigned long m_NumberOfObjects; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkAttributeKeepNObjectsLabelMapFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkAttributeKeepNObjectsLabelMapFilter.txx b/Utilities/InsightJournal/itkAttributeKeepNObjectsLabelMapFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..347283692150ea4ec429bef0256e8918a2653a61 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeKeepNObjectsLabelMapFilter.txx @@ -0,0 +1,102 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeKeepNObjectsLabelMapFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeKeepNObjectsLabelMapFilter_txx +#define __itkAttributeKeepNObjectsLabelMapFilter_txx + +#include "itkAttributeKeepNObjectsLabelMapFilter.h" +#include "itkProgressReporter.h" + + +namespace itk { + +template <class TImage, class TAttributeAccessor> +AttributeKeepNObjectsLabelMapFilter<TImage, TAttributeAccessor> +::AttributeKeepNObjectsLabelMapFilter() +{ + m_ReverseOrdering = false; + m_NumberOfObjects = 1; +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeKeepNObjectsLabelMapFilter<TImage, TAttributeAccessor> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + + ImageType * output = this->GetOutput(); + + typedef typename ImageType::LabelObjectContainerType LabelObjectContainerType; + const LabelObjectContainerType & labelObjectContainer = output->GetLabelObjectContainer(); + typedef typename std::vector< typename LabelObjectType::Pointer > VectorType; + + ProgressReporter progress( this, 0, 2 * labelObjectContainer.size() ); + + // get the label objects in a vector, so they can be sorted + VectorType labelObjects; + labelObjects.reserve( labelObjectContainer.size() ); + for( typename LabelObjectContainerType::const_iterator it = labelObjectContainer.begin(); + it != labelObjectContainer.end(); + it++ ) + { + labelObjects.push_back( it->second ); + progress.CompletedPixel(); + } + + // instantiate the comparator and sort the vector + if( m_NumberOfObjects < labelObjectContainer.size() ) + { + typename VectorType::iterator end = labelObjects.begin() + m_NumberOfObjects; + if( m_ReverseOrdering ) + { + ReverseComparator comparator; + std::nth_element( labelObjects.begin(), end, labelObjects.end(), comparator ); + } + else + { + Comparator comparator; + std::nth_element( labelObjects.begin(), end, labelObjects.end(), comparator ); + } +// progress.CompletedPixel(); + + // and remove the last objects of the map + for( typename VectorType::const_iterator it = end; + it != labelObjects.end(); + it++ ) + { + output->RemoveLabelObject( *it ); + progress.CompletedPixel(); + } + } +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeKeepNObjectsLabelMapFilter<TImage, TAttributeAccessor> +::PrintSelf(std::ostream& os, Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkAttributeLabelObject.h b/Utilities/InsightJournal/itkAttributeLabelObject.h new file mode 100644 index 0000000000000000000000000000000000000000..bf666318c9308d355c0bbbab2c5b40709047685f --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeLabelObject.h @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelObject.h,v $ + Language: C++ + Date: $Date: 2005/01/21 20:13:31 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeLabelObject_h +#define __itkAttributeLabelObject_h + +#include "itkLabelObject.h" + +namespace itk +{ + + +namespace Functor { + +template< class TLabelObject > +class ITK_EXPORT AttributeLabelObjectAccessor +{ +public: + typedef TLabelObject LabelObjectType; + typedef typename LabelObjectType::AttributeValueType AttributeValueType; + + inline const AttributeValueType operator()( const LabelObjectType * labelObject ) + { + return labelObject->GetAttribute(); + } + + inline void operator()( LabelObjectType * labelObject, AttributeValueType value ) + { + labelObject->SetAttribute( value ); + } +}; + +} + + +/** \class AttributeLabelObject + * \brief A LabelObject with a generic attribute + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + *\sa LabelObject, ShapeLabelObject, StatisticsLabelObject + * + * \ingroup DataRepresentation + */ +template < class TLabel, unsigned int VImageDimension, class TAttributeValue > +class ITK_EXPORT AttributeLabelObject : public LabelObject< TLabel, VImageDimension > +{ +public: + /** Standard class typedefs */ + typedef AttributeLabelObject Self; + typedef LabelObject< TLabel, VImageDimension > Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + typedef WeakPointer<const Self> ConstWeakPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(AttributeLabelObject, LabelObject); + + typedef LabelMap< Self > LabelMapType; + + itkStaticConstMacro(ImageDimension, unsigned int, VImageDimension); + + typedef typename Superclass::IndexType IndexType; + + typedef TLabel LabelType; + + typedef typename Superclass::LineType LineType; + + typedef typename Superclass::LengthType LengthType; + + typedef typename Superclass::LineContainerType LineContainerType; + + typedef TAttributeValue AttributeValueType; + + void SetAttribute( const AttributeValueType & v ) + { + m_Attribute = v; + } + + const AttributeValueType & GetAttribute() const + { + return m_Attribute; + } + + AttributeValueType GetAttribute() + { + return m_Attribute; + } + + + virtual void CopyAttributesFrom( const Self * src ) + { + Superclass::CopyAttributesFrom( src ); + m_Attribute = src->m_Attribute; + } + +protected: + AttributeLabelObject() + { + // how to initialize the attribute ? + } + + + void PrintSelf(std::ostream& os, Indent indent) const + { + Superclass::PrintSelf( os, indent ); + + os << indent << "Attribute: " << m_Attribute << std::endl; + } + +private: + AttributeLabelObject(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + AttributeValueType m_Attribute; + + +}; + +} // end namespace itk + +#endif diff --git a/Utilities/InsightJournal/itkAttributeOpeningLabelMapFilter.h b/Utilities/InsightJournal/itkAttributeOpeningLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..1b3e9dfa0c961757453edac220f3d623037a1143 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeOpeningLabelMapFilter.h @@ -0,0 +1,134 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeOpeningLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeOpeningLabelMapFilter_h +#define __itkAttributeOpeningLabelMapFilter_h + +#include "itkInPlaceLabelMapFilter.h" +#include "itkAttributeLabelObject.h" + +namespace itk { +/** \class AttributeOpeningLabelMapFilter + * \brief remove the objects according to the value of their attribute + * + * AttributeOpeningLabelMapFilter removes the objects in a label collection image + * with an attribute value smaller or greater than a threshold called Lambda. + * The attribute is provide by an attribute accessor given in template parameter. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT AttributeOpeningLabelMapFilter : + public InPlaceLabelMapFilter<TImage> +{ +public: + /** Standard class typedefs. */ + typedef AttributeOpeningLabelMapFilter Self; + typedef InPlaceLabelMapFilter<TImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(AttributeOpeningLabelMapFilter, + InPlaceLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>));*/ + /** End concept checking */ +#endif + + /** + * Set/Get the threshold used to keep or remove the objects. + */ + itkGetConstMacro(Lambda, AttributeValueType); + itkSetMacro(Lambda, AttributeValueType); + + /** + * Set/Get the ordering of the objects. By default, the objects with + * an attribute value smaller than Lamba are removed. Turning ReverseOrdering + * to true make this filter remove the object with an attribute value greater + * than Lambda instead. + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + + AttributeAccessorType & GetAccessor() + { + return m_Accessor; + } + + void SetAccessor(const AttributeAccessorType& accessor) + { + m_Accessor = accessor; + this->Modified(); + } + +protected: + AttributeOpeningLabelMapFilter(); + ~AttributeOpeningLabelMapFilter() {}; + + void GenerateData(); + + void PrintSelf(std::ostream& os, Indent indent) const; + +private: + AttributeOpeningLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + AttributeValueType m_Lambda; + bool m_ReverseOrdering; + AttributeAccessorType m_Accessor; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkAttributeOpeningLabelMapFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkAttributeOpeningLabelMapFilter.txx b/Utilities/InsightJournal/itkAttributeOpeningLabelMapFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..e26d8c377c3939f56b6dbae58edc818b1a31ea09 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeOpeningLabelMapFilter.txx @@ -0,0 +1,85 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeOpeningLabelMapFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeOpeningLabelMapFilter_txx +#define __itkAttributeOpeningLabelMapFilter_txx + +#include "itkAttributeOpeningLabelMapFilter.h" +#include "itkProgressReporter.h" + + +namespace itk { + +template <class TImage, class TAttributeAccessor> +AttributeOpeningLabelMapFilter<TImage, TAttributeAccessor> +::AttributeOpeningLabelMapFilter() +{ + m_Lambda = NumericTraits< AttributeValueType >::Zero; + m_ReverseOrdering = false; +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeOpeningLabelMapFilter<TImage, TAttributeAccessor> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + + ImageType * output = this->GetOutput(); + + const typename ImageType::LabelObjectContainerType & labelObjectContainer = output->GetLabelObjectContainer(); + + ProgressReporter progress( this, 0, labelObjectContainer.size() ); + + typename ImageType::LabelObjectContainerType::const_iterator it = labelObjectContainer.begin(); + while( it != labelObjectContainer.end() ) + { + typedef typename ImageType::LabelObjectType LabelObjectType; + typename LabelObjectType::LabelType label = it->first; + LabelObjectType * labelObject = it->second; + + if( ( !m_ReverseOrdering && m_Accessor( labelObject ) < m_Lambda ) + || ( m_ReverseOrdering && m_Accessor( labelObject ) > m_Lambda ) ) + { + // must increment the iterator before removing the object to avoid invalidating the iterator + it++; + output->RemoveLabel( label ); + } + else + { + it++; + } + + progress.CompletedPixel(); + } +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeOpeningLabelMapFilter<TImage, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "Lambda: " << static_cast<typename NumericTraits<AttributeValueType>::PrintType>(m_Lambda) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkAttributeRelabelImageFilter.h b/Utilities/InsightJournal/itkAttributeRelabelImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..02250f14e974cc7261a2060eb7043ec8e74bb313 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeRelabelImageFilter.h @@ -0,0 +1,152 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeRelabelImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeRelabelImageFilter_h +#define __itkAttributeRelabelImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkLabelMap.h" +#include "itkLabelImageToLabelMapFilter.h" +#include "itkAttributeRelabelLabelMapFilter.h" +#include "itkLabelMapToLabelImageFilter.h" +#include "itkAttributeLabelObject.h" + + +namespace itk { + +/** \class AttributeRelabelImageFilter + * \brief relabel objects according to their shape attributes + * + * AttributeRelabelImageFilter relabel a labeled image according to the attribute of + * the objects. The label produced are always consecutives. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject, RelabelComponentImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT AttributeRelabelImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef AttributeRelabelImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef TLabelObject LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::LabelImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef TLabelObjectValuator LabelObjectValuatorType; + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + typedef typename itk::AttributeRelabelLabelMapFilter< LabelMapType, AttributeAccessorType > RelabelType; + typedef typename itk::LabelMapToLabelImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(AttributeRelabelImageFilter, + ImageToImageFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the order of labeling of the objects. By default, the objects with + * the highest attribute values are labeled first. Set ReverseOrdering to true + * make the one with the smallest attributes be labeled first. + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + +protected: + AttributeRelabelImageFilter(); + ~AttributeRelabelImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** AttributeRelabelImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** AttributeRelabelImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + virtual void CustomizeInternalFilters( LabelizerType *, LabelObjectValuatorType *, RelabelType *, BinarizerType* ) {}; + +private: + AttributeRelabelImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + OutputImagePixelType m_BackgroundValue; + bool m_ReverseOrdering; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkAttributeRelabelImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkAttributeRelabelImageFilter.txx b/Utilities/InsightJournal/itkAttributeRelabelImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..6eb1494d74ba55027907a11f6c641299e5aee756 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeRelabelImageFilter.txx @@ -0,0 +1,115 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeRelabelImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeRelabelImageFilter_txx +#define __itkAttributeRelabelImageFilter_txx + +#include "itkAttributeRelabelImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +AttributeRelabelImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::AttributeRelabelImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ReverseOrdering = false; +} + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +AttributeRelabelImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +AttributeRelabelImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +AttributeRelabelImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(valuator, .3f); + + typename RelabelType::Pointer opening = RelabelType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + this->CustomizeInternalFilters( labelizer, valuator, opening, binarizer ); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +AttributeRelabelImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkAttributeRelabelLabelMapFilter.h b/Utilities/InsightJournal/itkAttributeRelabelLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..23dda370cf9e6f7edd242ed5d8bcc48ae4ecf39e --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeRelabelLabelMapFilter.h @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeRelabelLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeRelabelLabelMapFilter_h +#define __itkAttributeRelabelLabelMapFilter_h + +#include "itkInPlaceLabelMapFilter.h" +#include "itkAttributeLabelObject.h" + +namespace itk { +/** \class AttributeRelabelLabelMapFilter + * \brief relabel objects according to their shape attributes + * + * AttributeRelabelLabelMapFilter relabel a label collection image according to the + * attribute of the objects. + * The attribute is provide by an attribute accessor given in template parameter. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject, RelabelComponentImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT AttributeRelabelLabelMapFilter : + public InPlaceLabelMapFilter<TImage> +{ +public: + /** Standard class typedefs. */ + typedef AttributeRelabelLabelMapFilter Self; + typedef InPlaceLabelMapFilter<TImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + typedef typename ImageType::LabelObjectType LabelObjectType; + + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(AttributeRelabelLabelMapFilter, + InPlaceLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>));*/ + /** End concept checking */ +#endif + + /** + * Set/Get the order of labeling of the objects. By default, the objects with + * the highest attribute values are labeled first. Set ReverseOrdering to true + * make the one with the smallest attributes be labeled first. + */ + itkSetMacro( ReverseOrdering, bool ); + itkGetConstReferenceMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + +protected: + AttributeRelabelLabelMapFilter(); + ~AttributeRelabelLabelMapFilter() {}; + + void GenerateData(); + + void PrintSelf(std::ostream& os, Indent indent) const; + + class ReverseComparator + { + public: + bool operator()( const typename LabelObjectType::Pointer & a, const typename LabelObjectType::Pointer & b ) + { + return accessor( a ) < accessor( b ); + } + AttributeAccessorType accessor; + }; + + class Comparator + { + public: + bool operator()( const typename LabelObjectType::Pointer & a, const typename LabelObjectType::Pointer & b ) + { + return accessor( a ) > accessor( b ); + } + AttributeAccessorType accessor; + }; + +private: + AttributeRelabelLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_ReverseOrdering; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkAttributeRelabelLabelMapFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkAttributeRelabelLabelMapFilter.txx b/Utilities/InsightJournal/itkAttributeRelabelLabelMapFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..3ba46f5afa205f43c141c3382dd3f4ee5e723b01 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeRelabelLabelMapFilter.txx @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeRelabelLabelMapFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeRelabelLabelMapFilter_txx +#define __itkAttributeRelabelLabelMapFilter_txx + +#include "itkAttributeRelabelLabelMapFilter.h" +#include "itkProgressReporter.h" + + +namespace itk { + +template <class TImage, class TAttributeAccessor> +AttributeRelabelLabelMapFilter<TImage, TAttributeAccessor> +::AttributeRelabelLabelMapFilter() +{ + m_ReverseOrdering = false; +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeRelabelLabelMapFilter<TImage, TAttributeAccessor> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + + ImageType * output = this->GetOutput(); + + typedef typename ImageType::LabelObjectContainerType LabelObjectContainerType; + const LabelObjectContainerType & labelObjectContainer = output->GetLabelObjectContainer(); + typedef typename std::vector< typename LabelObjectType::Pointer > VectorType; + + ProgressReporter progress( this, 0, 2 * labelObjectContainer.size() ); + + // get the label objects in a vector, so they can be sorted + VectorType labelObjects; + labelObjects.reserve( labelObjectContainer.size() ); + for( typename LabelObjectContainerType::const_iterator it = labelObjectContainer.begin(); + it != labelObjectContainer.end(); + it++ ) + { + labelObjects.push_back( it->second ); + progress.CompletedPixel(); + } + + // instantiate the comparator and sort the vector + if( m_ReverseOrdering ) + { + ReverseComparator comparator; + std::sort( labelObjects.begin(), labelObjects.end(), comparator ); + } + else + { + Comparator comparator; + std::sort( labelObjects.begin(), labelObjects.end(), comparator ); + } +// progress.CompletedPixel(); + + // and put back the objects in the map + typedef typename ImageType::LabelObjectType LabelObjectType; + output->ClearLabels(); + unsigned int label = 0; + for( typename VectorType::const_iterator it = labelObjects.begin(); + it != labelObjects.end(); + it++ ) + { + // avoid the background label if it is used + if( label == output->GetBackgroundValue() ) + { + label++; + } + (*it)->SetLabel( label ); + output->AddLabelObject( *it ); + + // go to the nex label + label++; + progress.CompletedPixel(); + } +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeRelabelLabelMapFilter<TImage, TAttributeAccessor> +::PrintSelf(std::ostream& os, Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkAttributeSelectionLabelMapFilter.h b/Utilities/InsightJournal/itkAttributeSelectionLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..b680477e23434dbdb47cb20641e7d5154d980d6a --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeSelectionLabelMapFilter.h @@ -0,0 +1,162 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeSelectionLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeSelectionLabelMapFilter_h +#define __itkAttributeSelectionLabelMapFilter_h + +#include "itkInPlaceLabelMapFilter.h" +#include "itkAttributeLabelObject.h" +#include <set> + + +namespace itk { +/** \class AttributeSelectionLabelMapFilter + * \brief remove the objects according to the value of their attribute + * + * AttributeSelectionLabelMapFilter removes the objects in a label collection image + * with an attribute value inside or outside a set of attribute values passed by + * the user. + * The attribute is provide by an attribute accessor given in template parameter. + * Contrary to the other filters made to remove some object of a LabelMap, no + * ordering relation for the attribute is needed in that filter. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT AttributeSelectionLabelMapFilter : + public InPlaceLabelMapFilter<TImage> +{ +public: + /** Standard class typedefs. */ + typedef AttributeSelectionLabelMapFilter Self; + typedef InPlaceLabelMapFilter<TImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + + typedef typename std::set<AttributeValueType> AttributeSetType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(AttributeSelectionLabelMapFilter, + InPlaceLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>));*/ + /** End concept checking */ +#endif + + /** + * Set/Get the threshold used to keep or remove the objects. + */ + const AttributeSetType & GetAttributeSet() const + { + return m_AttributeSet; + } + void SetAttributeSet( const AttributeSetType & set ) + { + m_AttributeSet = set; + this->Modified(); + } + + /** + * Set/Get the ordering of the objects. By default, the objects with + * an attribute value smaller than Lamba are removed. Turning ReverseOrdering + * to true make this filter remove the object with an attribute value greater + * than Lambda instead. + */ + itkGetConstMacro( Exclude, bool ); + itkSetMacro( Exclude, bool ); + itkBooleanMacro( Exclude ); + + /** Clear the attribute set, and add the attribute passed in parameter */ + void SetAttribute( const AttributeValueType & attr ) + { + this->ClearAttributeSet(); + this->AddAttribute( attr ); + } + + void ClearAttributeSet() + { + if( ! m_AttributeSet.empty() ) + { + m_AttributeSet.clear(); + this->Modified(); + } + } + + void AddAttribute( const AttributeValueType & attr ) + { + unsigned long size = m_AttributeSet.size(); + m_AttributeSet.insert( attr ); + if( size != m_AttributeSet.size() ) + { + this->Modified(); + } + } + +protected: + AttributeSelectionLabelMapFilter(); + ~AttributeSelectionLabelMapFilter() {}; + + void GenerateData(); + + void PrintSelf(std::ostream& os, Indent indent) const; + +private: + AttributeSelectionLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + AttributeSetType m_AttributeSet; + bool m_Exclude; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkAttributeSelectionLabelMapFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkAttributeSelectionLabelMapFilter.txx b/Utilities/InsightJournal/itkAttributeSelectionLabelMapFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..fe2de08981984ea32bd1f40ec222b8d01e9fa533 --- /dev/null +++ b/Utilities/InsightJournal/itkAttributeSelectionLabelMapFilter.txx @@ -0,0 +1,86 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkAttributeSelectionLabelMapFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkAttributeSelectionLabelMapFilter_txx +#define __itkAttributeSelectionLabelMapFilter_txx + +#include "itkAttributeSelectionLabelMapFilter.h" +#include "itkProgressReporter.h" + + +namespace itk { + +template <class TImage, class TAttributeAccessor> +AttributeSelectionLabelMapFilter<TImage, TAttributeAccessor> +::AttributeSelectionLabelMapFilter() +{ + m_AttributeSet.clear(); + m_Exclude = false; +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeSelectionLabelMapFilter<TImage, TAttributeAccessor> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + + ImageType * output = this->GetOutput(); + + AttributeAccessorType accessor; + + const typename ImageType::LabelObjectContainerType & labelObjectContainer = output->GetLabelObjectContainer(); + + ProgressReporter progress( this, 0, labelObjectContainer.size() ); + + typename ImageType::LabelObjectContainerType::const_iterator it = labelObjectContainer.begin(); + while( it != labelObjectContainer.end() ) + { + typedef typename ImageType::LabelObjectType LabelObjectType; + typename LabelObjectType::LabelType label = it->first; + LabelObjectType * labelObject = it->second; + bool notInSet = m_AttributeSet.find( accessor( labelObject ) ) == m_AttributeSet.end(); + if( m_Exclude != notInSet ) // no xor in c++, use != instead + { + // must increment the iterator before removing the object to avoid invalidating the iterator + it++; + output->RemoveLabel( label ); + } + else + { + it++; + } + + progress.CompletedPixel(); + } +} + + +template <class TImage, class TAttributeAccessor> +void +AttributeSelectionLabelMapFilter<TImage, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "AttributeSet: " << &m_AttributeSet << std::endl; + os << indent << "Exclude: " << m_Exclude << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryAttributeKeepNObjectsImageFilter.h b/Utilities/InsightJournal/itkBinaryAttributeKeepNObjectsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..6ec667805d426042ac7bf9dab66f4ad6c099fe01 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryAttributeKeepNObjectsImageFilter.h @@ -0,0 +1,183 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryAttributeKeepNObjectsImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryAttributeKeepNObjectsImageFilter_h +#define __itkBinaryAttributeKeepNObjectsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkAttributeKeepNObjectsLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" +#include "itkAttributeLabelObject.h" + + +namespace itk { + +/** \class BinaryAttributeKeepNObjectsImageFilter + * \brief keep N objects according to a generic attribute + * + * BinaryAttributeKeepNObjectsImageFilter keep the N objects in a binary image + * with the highest (or lowest) attribute value. The attribute is valued with + * and attribute valuator given in template parameter and is accessed with a + * attribute accessor also given in template parameter. + * + * Used in combination with AttributeLabelObject, and a specilized attribute valuator, + * this class is the most efficient way to keep N objects in a binary image. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject, InPlaceLabelMapFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT BinaryAttributeKeepNObjectsImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryAttributeKeepNObjectsImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef TLabelObject LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef TLabelObjectValuator LabelObjectValuatorType; + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + typedef typename itk::AttributeKeepNObjectsLabelMapFilter< LabelMapType, AttributeAccessorType > KeepNObjectsType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryAttributeKeepNObjectsImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** + * Set/Get the number of objects to keep + */ + itkGetConstMacro(NumberOfObjects, unsigned long); + itkSetMacro(NumberOfObjects, unsigned long); + + /** + * Set/Get the ordering of the objects. By default, the ones with the + * highest value are kept. Turming ReverseOrdering to true make this filter + * keep the objects with the smallest values + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + +protected: + BinaryAttributeKeepNObjectsImageFilter(); + ~BinaryAttributeKeepNObjectsImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryAttributeKeepNObjectsImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryAttributeKeepNObjectsImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + virtual void CustomizeInternalFilters( LabelizerType *, LabelObjectValuatorType *, KeepNObjectsType *, BinarizerType* ) {}; + +private: + BinaryAttributeKeepNObjectsImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; + unsigned long m_NumberOfObjects; + bool m_ReverseOrdering; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryAttributeKeepNObjectsImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryAttributeKeepNObjectsImageFilter.txx b/Utilities/InsightJournal/itkBinaryAttributeKeepNObjectsImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..d4b0735f21be8c01f90779b748aedc48a94a1854 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryAttributeKeepNObjectsImageFilter.txx @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryAttributeKeepNObjectsImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryAttributeKeepNObjectsImageFilter_txx +#define __itkBinaryAttributeKeepNObjectsImageFilter_txx + +#include "itkBinaryAttributeKeepNObjectsImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +BinaryAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::BinaryAttributeKeepNObjectsImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + m_ReverseOrdering = false; +} + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(valuator, .3f); + + typename KeepNObjectsType::Pointer opening = KeepNObjectsType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetNumberOfObjects( m_NumberOfObjects ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetInput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + this->CustomizeInternalFilters( labelizer, valuator, opening, binarizer ); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryAttributeOpeningImageFilter.h b/Utilities/InsightJournal/itkBinaryAttributeOpeningImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..a9017243bc100ee8e26cc00800f67efca03386ee --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryAttributeOpeningImageFilter.h @@ -0,0 +1,186 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryAttributeOpeningImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryAttributeOpeningImageFilter_h +#define __itkBinaryAttributeOpeningImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkAttributeOpeningLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" +#include "itkAttributeLabelObject.h" + + +namespace itk { + +/** \class BinaryAttributeOpeningImageFilter + * \brief remove the objects in a binary image according to a generic attribute + * + * BinaryAttributeOpeningImageFilter remove the objects in a binary image + * with an attribute value smaller or greater than a threshold called Lambda. + * The attribute is valued with and attribute valuator given in template parameter + * and is accessed with an attribute accessor also given in template parameter. + * + * Used in combination with AttributeLabelObject, and a specilized attribute valuator, + * this class is the most efficient way to perform an attribute opening in a binary + * image. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject, InPlaceLabelMapFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT BinaryAttributeOpeningImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryAttributeOpeningImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef TLabelObject LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef TLabelObjectValuator LabelObjectValuatorType; + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + typedef typename itk::AttributeOpeningLabelMapFilter< LabelMapType, AttributeAccessorType > OpeningType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryAttributeOpeningImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** + * Set/Get the threshold used to keep or remove the objects. + */ + itkGetConstMacro(Lambda, AttributeValueType); + itkSetMacro(Lambda, AttributeValueType); + + /** + * Set/Get the ordering of the objects. By default, the objects with + * an attribute value smaller than Lamba are removed. Turning ReverseOrdering + * to true make this filter remove the object with an attribute value greater + * than Lambda instead. + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + +protected: + BinaryAttributeOpeningImageFilter(); + ~BinaryAttributeOpeningImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryAttributeOpeningImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryAttributeOpeningImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + virtual void CustomizeInternalFilters( LabelizerType *, LabelObjectValuatorType *, OpeningType *, BinarizerType* ) {}; + + +private: + BinaryAttributeOpeningImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; + AttributeValueType m_Lambda; + bool m_ReverseOrdering; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryAttributeOpeningImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryAttributeOpeningImageFilter.txx b/Utilities/InsightJournal/itkBinaryAttributeOpeningImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..c5bb494870b230fff1baed1ed74280ceb2b7d78a --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryAttributeOpeningImageFilter.txx @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryAttributeOpeningImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryAttributeOpeningImageFilter_txx +#define __itkBinaryAttributeOpeningImageFilter_txx + +#include "itkBinaryAttributeOpeningImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +BinaryAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::BinaryAttributeOpeningImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + m_ReverseOrdering = false; +} + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(valuator, .3f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetLambda( m_Lambda ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetInput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + this->CustomizeInternalFilters( labelizer, valuator, opening, binarizer ); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +BinaryAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "Lambda: " <<m_Lambda << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryClosingByReconstructionImageFilter.h b/Utilities/InsightJournal/itkBinaryClosingByReconstructionImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..272e76ddc2fd572e42c27e67ddd1568ddcb1a4d9 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryClosingByReconstructionImageFilter.h @@ -0,0 +1,132 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryClosingByReconstructionImageFilter.h,v $ + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryClosingByReconstructionImageFilter_h +#define __itkBinaryClosingByReconstructionImageFilter_h + +#include "itkImageToImageFilter.h" + +namespace itk { + +/** + * \class BinaryClosingByReconstructionImageFilter + * \brief binary morphological closing of an image. + * + * This filter removes small (i.e., smaller than the structuring + * element) holes in the image. It is defined as: + * Closing(f) = ReconstructionByErosion(Dilation(f)). + * + * The structuring element is assumed to be composed of binary + * values (zero or one). Only elements of the structuring element + * having values > 0 are candidates for affecting the center pixel. + * + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa MorphologyImageFilter, ClosingByReconstructionImageFilter, BinaryOpeningByReconstructionImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ + +template<class TInputImage, class TKernel> +class ITK_EXPORT BinaryClosingByReconstructionImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryClosingByReconstructionImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryClosingByReconstructionImageFilter, + ImageToImageFilter); + + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + /** Declaration of pixel type. */ + typedef typename TInputImage::PixelType InputPixelType ; + typedef typename TInputImage::PixelType OutputPixelType ; + + /** Kernel typedef. */ + typedef TKernel KernelType; + + /** Set kernel (structuring element). */ + itkSetMacro(Kernel, KernelType); + + /** Get the kernel (structuring element). */ + itkGetConstReferenceMacro(Kernel, KernelType); + + /** Set the value in the image to consider as "foreground". Defaults to + * maximum value of InputPixelType. */ + itkSetMacro(ForegroundValue, InputPixelType); + + /** Get the value in the image considered as "foreground". Defaults to + * maximum value of InputPixelType. */ + itkGetMacro(ForegroundValue, InputPixelType); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +protected: + BinaryClosingByReconstructionImageFilter(); + ~BinaryClosingByReconstructionImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryClosingByReconstructionImageFilter need to make sure they request enough of an + * input image to account for the structuring element size. The input + * requested region is expanded by the radius of the structuring element. + * If the request extends past the LargestPossibleRegion for the input, + * the request is cropped by the LargestPossibleRegion. */ + void GenerateInputRequestedRegion() ; + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleDilateImageFilter GrayscaleErodeImageFilter. */ + void GenerateData (); + +private: + BinaryClosingByReconstructionImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + /** kernel or structuring element to use. */ + KernelType m_Kernel ; + + InputPixelType m_ForegroundValue; + + bool m_FullyConnected; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryClosingByReconstructionImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryClosingByReconstructionImageFilter.txx b/Utilities/InsightJournal/itkBinaryClosingByReconstructionImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..cb1efeb9606bb7ce8a63d2854da54a6bf73a7a29 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryClosingByReconstructionImageFilter.txx @@ -0,0 +1,123 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryClosingByReconstructionImageFilter.txx,v $ + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryClosingByReconstructionImageFilter_txx +#define __itkBinaryClosingByReconstructionImageFilter_txx + +#include "itkBinaryClosingByReconstructionImageFilter.h" +#include "itkBinaryReconstructionByErosionImageFilter.h" +#include "itkBinaryDilateImageFilter.h" +#include "itkProgressAccumulator.h" +#include "itkCropImageFilter.h" +#include "itkConstantPadImageFilter.h" +#include "itkConstNeighborhoodIterator.h" +#include "itkNeighborhoodIterator.h" +#include "itkProgressReporter.h" + +namespace itk { + +template<class TInputImage, class TKernel> +BinaryClosingByReconstructionImageFilter<TInputImage, TKernel> +::BinaryClosingByReconstructionImageFilter() + : m_Kernel() +{ + m_ForegroundValue = NumericTraits<InputPixelType>::max(); + m_FullyConnected = false; +} + +template <class TInputImage, class TKernel> +void +BinaryClosingByReconstructionImageFilter<TInputImage, TKernel> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + +template<class TInputImage, class TKernel> +void +BinaryClosingByReconstructionImageFilter<TInputImage, TKernel> +::GenerateData() +{ + // Allocate the outputs + this->AllocateOutputs(); + + // let choose a background value. Background value should not be given by user + // because closing is extensive so no background pixels will be added + // it is just needed for internal erosion filter and constant padder + InputPixelType backgroundValue = NumericTraits<InputPixelType>::Zero; + if ( m_ForegroundValue == backgroundValue ) + { + // current background value is already used for foreground value + // choose another one + backgroundValue = NumericTraits<InputPixelType>::max(); + } + + /** set up erosion and dilation methods */ + typename BinaryDilateImageFilter<TInputImage, TInputImage, TKernel>::Pointer + dilate = BinaryDilateImageFilter<TInputImage, TInputImage, TKernel>::New(); + + typename BinaryReconstructionByErosionImageFilter<OutputImageType>::Pointer + erode = BinaryReconstructionByErosionImageFilter<OutputImageType>::New(); + + // create the pipeline without input and output image + dilate->ReleaseDataFlagOn(); + dilate->SetKernel( this->GetKernel() ); + dilate->SetDilateValue( m_ForegroundValue ); + dilate->SetBackgroundValue( backgroundValue ); + dilate->SetInput( this->GetInput() ); + dilate->SetNumberOfThreads( this->GetNumberOfThreads() ); + + erode->ReleaseDataFlagOn(); + erode->SetForegroundValue( m_ForegroundValue ); + erode->SetBackgroundValue( backgroundValue ); + erode->SetMarkerImage( dilate->GetOutput() ); + erode->SetFullyConnected( m_FullyConnected ); + erode->SetMaskImage( this->GetInput() ); + erode->SetNumberOfThreads( this->GetNumberOfThreads() ); + + + /** set up the minipipeline */ + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + progress->RegisterInternalFilter(erode, .8f); + progress->RegisterInternalFilter(dilate, .2f); + + /** execute the minipipeline */ + erode->GraftOutput( this->GetOutput() ); + erode->Update(); + this->GraftOutput( erode->GetOutput() ); +} + +template<class TInputImage, class TKernel> +void +BinaryClosingByReconstructionImageFilter<TInputImage, TKernel> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "Kernel: " << m_Kernel << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<InputPixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryFillholeImageFilter.h b/Utilities/InsightJournal/itkBinaryFillholeImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..edc217f84fcaa95c0786a9680790b6ce591c7d7b --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryFillholeImageFilter.h @@ -0,0 +1,137 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryFillholeImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.5 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkFillholeImageFilter_h +#define __itkFillholeImageFilter_h + +#include "itkImageToImageFilter.h" + +namespace itk { + +/** \class BinaryFillholeImageFilter + * \brief Remove holes not connected to the boundary of the image. + * + * BinaryFillholeImageFilter fills holes in a binary image. + * + * Geodesic morphology and the Fillhole algorithm is described in + * Chapter 6 of Pierre Soille's book "Morphological Image Analysis: + * Principles and Applications", Second Edition, Springer, 2003. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa GrayscaleFillholeImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT BinaryFillholeImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryFillholeImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + OutputImageType::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryFillholeImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** Set the value in the image to consider as "foreground". Defaults to + * maximum value of InputPixelType. */ + itkSetMacro(ForegroundValue, InputImagePixelType); + + /** Get the value in the image considered as "foreground". Defaults to + * maximum value of InputPixelType. */ + itkGetMacro(ForegroundValue, InputImagePixelType); + + +protected: + BinaryFillholeImageFilter(); + ~BinaryFillholeImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryFillholeImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryFillholeImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + BinaryFillholeImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + InputImagePixelType m_ForegroundValue; + + bool m_FullyConnected; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryFillholeImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryFillholeImageFilter.txx b/Utilities/InsightJournal/itkBinaryFillholeImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..c999f6cb9cdb3934d4a53ff60b614f5010a73ad5 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryFillholeImageFilter.txx @@ -0,0 +1,147 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryFillholeImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/12/15 21:41:24 $ + Version: $Revision: 1.10 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryFillholeImageFilter_txx +#define __itkBinaryFillholeImageFilter_txx + +#include "itkBinaryFillholeImageFilter.h" +#include "itkBinaryReconstructionByErosionImageFilter.h" +#include "itkImageRegionExclusionIteratorWithIndex.h" +#include "itkProgressAccumulator.h" + +namespace itk { + +template <class TInputImage> +BinaryFillholeImageFilter<TInputImage> +::BinaryFillholeImageFilter() +{ + m_FullyConnected = false; + m_ForegroundValue = NumericTraits<InputImagePixelType>::max(); +} + +template <class TInputImage> +void +BinaryFillholeImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template <class TInputImage> +void +BinaryFillholeImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +BinaryFillholeImageFilter<TInputImage> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + + // construct a marker image to manipulate using reconstruction by + // erosion. the marker image will have the same pixel values as the + // input image on the boundary of the image and will have the + // maximum pixel value from the input image for all the pixels in + // the interior + // + + // let choose a background value. Background value should not be given by user + // because closing is extensive so no background pixels will be added + // it is just needed for internal erosion filter and constant padder + InputImagePixelType backgroundValue = NumericTraits<InputImagePixelType>::Zero; + if ( m_ForegroundValue == backgroundValue ) + { + // current background value is already used for foreground value + // choose another one + backgroundValue = NumericTraits<InputImagePixelType>::max(); + } + + // allocate a marker image + InputImagePointer markerPtr = InputImageType::New(); + markerPtr->SetRegions( this->GetInput()->GetRequestedRegion() ); + markerPtr->CopyInformation( this->GetInput() ); + markerPtr->Allocate(); + + // fill the marker image with the maximum value from the input + markerPtr->FillBuffer( m_ForegroundValue ); + + // set the border of the marker to the background value + // + ImageRegionExclusionIteratorWithIndex<TInputImage> + markerBoundaryIt( markerPtr, this->GetInput()->GetRequestedRegion() ); + markerBoundaryIt.SetExclusionRegionToInsetRegion(); + + // copy the boundary pixels + markerBoundaryIt.GoToBegin(); + while ( !markerBoundaryIt.IsAtEnd() ) + { + markerBoundaryIt.Set( backgroundValue ); + ++markerBoundaryIt; + } + + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Delegate to a geodesic erosion filter. + // + // + typename BinaryReconstructionByErosionImageFilter<TInputImage>::Pointer + erode + = BinaryReconstructionByErosionImageFilter<TInputImage>::New(); + erode->SetMarkerImage( markerPtr ); + erode->SetForegroundValue( m_ForegroundValue ); + erode->SetBackgroundValue( backgroundValue ); + erode->SetMaskImage( this->GetInput() ); + erode->SetFullyConnected( m_FullyConnected ); + erode->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(erode,1.0f); + + erode->GraftOutput( this->GetOutput() ); + erode->Update(); + this->GraftOutput( erode->GetOutput() ); +} + + +template<class TInputImage> +void +BinaryFillholeImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<InputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryGrindPeakImageFilter.h b/Utilities/InsightJournal/itkBinaryGrindPeakImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..3fd056fb9cca1dc688ba39c7b245f05d51e7f557 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryGrindPeakImageFilter.h @@ -0,0 +1,145 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryGrindPeakImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.5 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryGrindPeakImageFilter_h +#define __itkBinaryGrindPeakImageFilter_h + +#include "itkImageToImageFilter.h" + +namespace itk { + +/** \class BinaryGrindPeakImageFilter + * \brief Remove the objects not connected to the boundary of the image. + * + * BinaryGrindPeakImageFilter ginds peaks in a grayscale image. + * + * Geodesic morphology and the grind peak algorithm is described in + * Chapter 6 of Pierre Soille's book "Morphological Image Analysis: + * Principles and Applications", Second Edition, Springer, 2003. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa GrayscaleGrindPeakImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT BinaryGrindPeakImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryGrindPeakImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + OutputImageType::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryGrindPeakImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** Set the value in the image to consider as "foreground". Defaults to + * maximum value of InputPixelType. */ + itkSetMacro(ForegroundValue, InputImagePixelType); + + /** Get the value in the image considered as "foreground". Defaults to + * maximum value of InputPixelType. */ + itkGetMacro(ForegroundValue, InputImagePixelType); + + /** Set the value in eroded part of the image. Defaults to zero */ + itkSetMacro(BackgroundValue, InputImagePixelType); + + /** Set the value in eroded part of the image. Defaults to zero */ + itkGetMacro(BackgroundValue, InputImagePixelType); + + +protected: + BinaryGrindPeakImageFilter(); + ~BinaryGrindPeakImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryGrindPeakImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryGrindPeakImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + BinaryGrindPeakImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + InputImagePixelType m_ForegroundValue; + + InputImagePixelType m_BackgroundValue; + + bool m_FullyConnected; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryGrindPeakImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryGrindPeakImageFilter.txx b/Utilities/InsightJournal/itkBinaryGrindPeakImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..e74e45dd086651a888d4d5265e5d616ab0c12984 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryGrindPeakImageFilter.txx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryGrindPeakImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/12/15 21:41:24 $ + Version: $Revision: 1.10 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryGrindPeakImageFilter_txx +#define __itkBinaryGrindPeakImageFilter_txx + +#include "itkBinaryGrindPeakImageFilter.h" +#include "itkBinaryReconstructionByDilationImageFilter.h" +#include "itkImageRegionExclusionIteratorWithIndex.h" +#include "itkProgressAccumulator.h" + +namespace itk { + +template <class TInputImage> +BinaryGrindPeakImageFilter<TInputImage> +::BinaryGrindPeakImageFilter() +{ + m_FullyConnected = false; + m_ForegroundValue = NumericTraits<InputImagePixelType>::max(); + m_BackgroundValue = NumericTraits<InputImagePixelType>::Zero; +} + +template <class TInputImage> +void +BinaryGrindPeakImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template <class TInputImage> +void +BinaryGrindPeakImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +BinaryGrindPeakImageFilter<TInputImage> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + + // construct a marker image to manipulate using reconstruction by + // erosion. the marker image will have the same pixel values as the + // input image on the boundary of the image and will have the + // maximum pixel value from the input image for all the pixels in + // the interior + // + + // allocate a marker image + InputImagePointer markerPtr = InputImageType::New(); + markerPtr->SetRegions( this->GetInput()->GetRequestedRegion() ); + markerPtr->CopyInformation( this->GetInput() ); + markerPtr->Allocate(); + + // fill the marker image with the maximum value from the input + markerPtr->FillBuffer( m_BackgroundValue ); + + // set the border of the marker to the background value + // + ImageRegionExclusionIteratorWithIndex<TInputImage> + markerBoundaryIt( markerPtr, this->GetInput()->GetRequestedRegion() ); + markerBoundaryIt.SetExclusionRegionToInsetRegion(); + + // copy the boundary pixels + markerBoundaryIt.GoToBegin(); + while ( !markerBoundaryIt.IsAtEnd() ) + { + markerBoundaryIt.Set( m_ForegroundValue ); + ++markerBoundaryIt; + } + + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Delegate to a geodesic erosion filter. + // + // + typename BinaryReconstructionByDilationImageFilter<TInputImage>::Pointer + dilate + = BinaryReconstructionByDilationImageFilter<TInputImage>::New(); + dilate->SetMarkerImage( markerPtr ); + dilate->SetForegroundValue( m_ForegroundValue ); + dilate->SetBackgroundValue( m_BackgroundValue ); + dilate->SetMaskImage( this->GetInput() ); + dilate->SetFullyConnected( m_FullyConnected ); + dilate->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(dilate,1.0f); + + dilate->GraftOutput( this->GetOutput() ); + dilate->Update(); + this->GraftOutput( dilate->GetOutput() ); +} + + +template<class TInputImage> +void +BinaryGrindPeakImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<InputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<InputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryNotImageFilter.h b/Utilities/InsightJournal/itkBinaryNotImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..366bca57dc5f8ef3d560be64c3ab00288f6c9641 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryNotImageFilter.h @@ -0,0 +1,143 @@ +#ifndef __itkBinaryNotImageFilter_h +#define __itkBinaryNotImageFilter_h + +#include "itkUnaryFunctorImageFilter.h" +#include "itkNumericTraits.h" + + +namespace itk +{ + +/** \class BinaryNotImageFilter + * \brief Implements the BinaryNot logical operator pixel-wise between two images. + * + * This class is parametrized over the types of the two + * input images and the type of the output image. + * Numeric conversions (castings) are done by the C++ defaults. + * + * + * The total operation over one pixel will be + * + * output_pixel = static_cast<PixelType>( input1_pixel != input2_pixel ) + * + * Where "!=" is the equality operator in C++. + * + * \ingroup IntensityImageFilters Multithreaded + */ +namespace Functor { + +template< class TPixel > +class BinaryNot +{ +public: + BinaryNot() {}; + ~BinaryNot() {}; + bool operator!=( const BinaryNot & ) const + { + return false; + } + bool operator==( const BinaryNot & other ) const + { + return !(*this != other); + } + inline TPixel operator()( const TPixel & A ) + { + bool a = ( A == m_ForegroundValue ); + if( !a ) + { + return m_ForegroundValue; + } + return m_BackgroundValue; + } + + TPixel m_ForegroundValue; + TPixel m_BackgroundValue; +}; + +} +template <class TImage> +class ITK_EXPORT BinaryNotImageFilter : + public +UnaryFunctorImageFilter<TImage, TImage, + Functor::BinaryNot< typename TImage::PixelType > > + + +{ +public: + /** Standard class typedefs. */ + typedef BinaryNotImageFilter Self; + typedef UnaryFunctorImageFilter<TImage, TImage, + Functor::BinaryNot< typename TImage::PixelType> > Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryNotImageFilter, + ImageToImageFilter); + + typedef typename TImage::PixelType PixelType; + + /** Set the value in the image to consider as "foreground". Defaults to + * maximum value of PixelType.*/ + itkSetMacro(ForegroundValue, PixelType); + + /** Get the value in the image considered as "foreground". Defaults to + * maximum value of PixelType. */ + itkGetConstMacro(ForegroundValue, PixelType); + + /** Set the value used as "background". Defaults to + * NumericTraits<PixelType>::NonpositiveMin(). */ + itkSetMacro(BackgroundValue, PixelType); + + /** Get the value used as "background". Defaults to + * NumericTraits<PixelType>::NonpositiveMin(). */ + itkGetConstMacro(BackgroundValue, PixelType); + + +protected: + BinaryNotImageFilter() + { + m_ForegroundValue = NumericTraits<PixelType>::max(); + m_BackgroundValue = NumericTraits<PixelType>::NonpositiveMin(); + } + virtual ~BinaryNotImageFilter() {} + + void PrintSelf(std::ostream& os, Indent indent) const + { + Superclass::PrintSelf(os,indent); + + typedef typename NumericTraits<PixelType>::PrintType + PixelPrintType; + + os << indent << "ForegroundValue: " + << static_cast< PixelPrintType > (m_ForegroundValue) + << std::endl; + + os << indent << "BackgroundValue: " + << static_cast< PixelPrintType > (m_BackgroundValue) + << std::endl; + } + + void GenerateData() + { + this->GetFunctor().m_ForegroundValue = m_ForegroundValue; + this->GetFunctor().m_BackgroundValue = m_BackgroundValue; + Superclass::GenerateData(); + } + +private: + BinaryNotImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + PixelType m_ForegroundValue; + PixelType m_BackgroundValue; + +}; + +} // end namespace itk + + +#endif diff --git a/Utilities/InsightJournal/itkBinaryOpeningByReconstructionImageFilter.h b/Utilities/InsightJournal/itkBinaryOpeningByReconstructionImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..22725730c128f7ccacae5b4c229a96678ded544c --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryOpeningByReconstructionImageFilter.h @@ -0,0 +1,140 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryOpeningByReconstructionImageFilter.h,v $ + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryOpeningByReconstructionImageFilter_h +#define __itkBinaryOpeningByReconstructionImageFilter_h + +#include "itkImageToImageFilter.h" + +namespace itk { + +/** + * \class BinaryOpeningByReconstructionImageFilter + * \brief binary morphological closing of an image. + * + * This filter removes small (i.e., smaller than the structuring + * element) objects in the image. It is defined as: + * Opening(f) = ReconstructionByDilatation(Erosion(f)). + * + * The structuring element is assumed to be composed of binary + * values (zero or one). Only elements of the structuring element + * having values > 0 are candidates for affecting the center pixel. + * + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa MorphologyImageFilter, OpeningByReconstructionImageFilter, BinaryClosingByReconstructionImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ + +template<class TInputImage, class TKernel> +class ITK_EXPORT BinaryOpeningByReconstructionImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryOpeningByReconstructionImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryOpeningByReconstructionImageFilter, + ImageToImageFilter); + + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + + /** Declaration of pixel type. */ + typedef typename TInputImage::PixelType PixelType ; + + /** Kernel typedef. */ + typedef TKernel KernelType; + + /** Set kernel (structuring element). */ + itkSetMacro(Kernel, KernelType); + + /** Get the kernel (structuring element). */ + itkGetConstReferenceMacro(Kernel, KernelType); + + /** Set the value in the image to consider as "foreground". Defaults to + * maximum value of PixelType. */ + itkSetMacro(ForegroundValue, PixelType); + + /** Get the value in the image considered as "foreground". Defaults to + * maximum value of PixelType. */ + itkGetMacro(ForegroundValue, PixelType); + + /** Set the value in eroded part of the image. Defaults to zero */ + itkSetMacro(BackgroundValue, PixelType); + + /** Set the value in eroded part of the image. Defaults to zero */ + itkGetMacro(BackgroundValue, PixelType); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + + +protected: + BinaryOpeningByReconstructionImageFilter(); + ~BinaryOpeningByReconstructionImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryOpeningByReconstructionImageFilter need to make sure they request enough of an + * input image to account for the structuring element size. The input + * requested region is expanded by the radius of the structuring element. + * If the request extends past the LargestPossibleRegion for the input, + * the request is cropped by the LargestPossibleRegion. */ + void GenerateInputRequestedRegion() ; + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleDilateImageFilter GrayscaleErodeImageFilter. */ + void GenerateData (); + +private: + BinaryOpeningByReconstructionImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + /** kernel or structuring element to use. */ + KernelType m_Kernel ; + + PixelType m_ForegroundValue; + + PixelType m_BackgroundValue; + + bool m_FullyConnected; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryOpeningByReconstructionImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryOpeningByReconstructionImageFilter.txx b/Utilities/InsightJournal/itkBinaryOpeningByReconstructionImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..935c8c49119c4a7a739b8d06d02a5dd5aa060f0a --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryOpeningByReconstructionImageFilter.txx @@ -0,0 +1,105 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryOpeningByReconstructionImageFilter.txx,v $ + Language: C++ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryOpeningByReconstructionImageFilter_txx +#define __itkBinaryOpeningByReconstructionImageFilter_txx + +#include "itkBinaryOpeningByReconstructionImageFilter.h" +#include "itkBinaryErodeImageFilter.h" +#include "itkBinaryReconstructionByDilationImageFilter.h" +#include "itkProgressAccumulator.h" + +namespace itk { + +template<class TInputImage, class TKernel> +BinaryOpeningByReconstructionImageFilter<TInputImage, TKernel> +::BinaryOpeningByReconstructionImageFilter() + : m_Kernel() +{ + m_ForegroundValue = NumericTraits<PixelType>::max(); + m_BackgroundValue = NumericTraits<PixelType>::Zero; + m_FullyConnected = false; +} + +template <class TInputImage, class TKernel> +void +BinaryOpeningByReconstructionImageFilter<TInputImage, TKernel> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + +template<class TInputImage, class TKernel> +void +BinaryOpeningByReconstructionImageFilter<TInputImage, TKernel> +::GenerateData() +{ + // Allocate the outputs + this->AllocateOutputs(); + + /** set up erosion and dilation methods */ + typename BinaryErodeImageFilter<InputImageType, OutputImageType, TKernel>::Pointer + erode = BinaryErodeImageFilter<InputImageType, OutputImageType, TKernel>::New(); + erode->SetErodeValue( m_ForegroundValue ); + erode->SetBackgroundValue( m_BackgroundValue ); + erode->SetKernel( this->GetKernel() ); + erode->SetInput( this->GetInput() ); + erode->ReleaseDataFlagOn(); + erode->SetNumberOfThreads( this->GetNumberOfThreads() ); + + typename BinaryReconstructionByDilationImageFilter<OutputImageType>::Pointer + dilate = BinaryReconstructionByDilationImageFilter<OutputImageType>::New(); + dilate->SetForegroundValue( m_ForegroundValue ); + dilate->SetBackgroundValue( m_BackgroundValue ); + dilate->SetMarkerImage( erode->GetOutput() ); + dilate->SetMaskImage( this->GetInput() ); + dilate->SetFullyConnected( m_FullyConnected ); + dilate->ReleaseDataFlagOn(); + dilate->SetNumberOfThreads( this->GetNumberOfThreads() ); + + /** set up the minipipeline */ + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + progress->RegisterInternalFilter(erode, .8f); + progress->RegisterInternalFilter(dilate, .2f); + + /** execute the minipipeline */ + dilate->GraftOutput( this->GetOutput() ); + dilate->Update(); + this->GraftOutput( dilate->GetOutput() ); +} + +template<class TInputImage, class TKernel> +void +BinaryOpeningByReconstructionImageFilter<TInputImage, TKernel> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "Kernel: " << m_Kernel << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<PixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<PixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryReconstructionByDilationImageFilter.h b/Utilities/InsightJournal/itkBinaryReconstructionByDilationImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..fe126f73510a5efd176a2de557adadfb666cf3ad --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryReconstructionByDilationImageFilter.h @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryReconstructionByDilationImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryReconstructionByDilationImageFilter_h +#define __itkBinaryReconstructionByDilationImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkAttributeLabelObject.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkBinaryReconstructionLabelMapFilter.h" +#include "itkAttributeOpeningLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" + + +namespace itk { + +/** \class BinaryReconstructionByDilationImageFilter + * \brief Identify local maxima whose height above the baseline is greater than h. + * +* \brief binary reconstruction by dilation of an image + * + * Reconstruction by dilation operates on a "marker" image and a "mask" + * image, and is defined as the dilation of the marker image with + * respect to the mask image iterated until stability. + * + * Geodesic morphology is described in Chapter 6.2 of Pierre Soille's + * book "Morphological Image Analysis: Principles and Applications", + * Second Edition, Springer, 2003. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa MorphologyImageFilter, ReconstructionByDilationImageFilter, BinaryReconstructionByErosionImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT BinaryReconstructionByDilationImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryReconstructionByDilationImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef AttributeLabelObject<unsigned long, ImageDimension, bool> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::BinaryReconstructionLabelMapFilter< LabelMapType, InputImageType > ReconstructionType; + typedef typename itk::AttributeOpeningLabelMapFilter< LabelMapType > OpeningType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryReconstructionByDilationImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** Set the marker image */ + void SetMarkerImage(InputImageType *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 0, const_cast<InputImageType *>(input) ); + } + + /** Get the marker image */ + InputImageType * GetMarkerImage() + { + return static_cast<InputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(0))); + } + + /** Set the mask image */ + void SetMaskImage( const InputImageType *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<InputImageType *>(input) ); + } + + /** Get the mask image */ + InputImageType * GetMaskImage() + { + return static_cast<InputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + +protected: + BinaryReconstructionByDilationImageFilter(); + ~BinaryReconstructionByDilationImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryReconstructionByDilationImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryReconstructionByDilationImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + BinaryReconstructionByDilationImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryReconstructionByDilationImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryReconstructionByDilationImageFilter.txx b/Utilities/InsightJournal/itkBinaryReconstructionByDilationImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..90a99a5e4e02df64d24d5c15dee1eef74a5d99a0 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryReconstructionByDilationImageFilter.txx @@ -0,0 +1,129 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryReconstructionByDilationImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryReconstructionByDilationImageFilter_txx +#define __itkBinaryReconstructionByDilationImageFilter_txx + +#include "itkBinaryReconstructionByDilationImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage> +BinaryReconstructionByDilationImageFilter<TInputImage> +::BinaryReconstructionByDilationImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + this->SetNumberOfRequiredInputs(2); +} + +template<class TInputImage> +void +BinaryReconstructionByDilationImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetMarkerImage()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } + + input = const_cast<InputImageType *>(this->GetMaskImage()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage> +void +BinaryReconstructionByDilationImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +BinaryReconstructionByDilationImageFilter<TInputImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetMaskImage() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .25f); + + typename ReconstructionType::Pointer reconstruction = ReconstructionType::New(); + reconstruction->SetInput( labelizer->GetOutput() ); + reconstruction->SetMarkerImage( this->GetMarkerImage() ); + reconstruction->SetForegroundValue( m_ForegroundValue ); + reconstruction->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(reconstruction, .25f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( reconstruction->GetOutput() ); + opening->SetLambda( true ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .25f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetMaskImage() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .5f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage> +void +BinaryReconstructionByDilationImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryReconstructionByErosionImageFilter.h b/Utilities/InsightJournal/itkBinaryReconstructionByErosionImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..da1deaf1d7bc9d4063527a8811513a45b79d6ea6 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryReconstructionByErosionImageFilter.h @@ -0,0 +1,192 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryReconstructionByErosionImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryReconstructionByErosionImageFilter_h +#define __itkBinaryReconstructionByErosionImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkAttributeLabelObject.h" +#include "itkLabelMap.h" +#include "itkBinaryNotImageFilter.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkBinaryReconstructionLabelMapFilter.h" +#include "itkAttributeOpeningLabelMapFilter.h" +#include "itkLabelMapMaskImageFilter.h" + + +namespace itk { + +/** \class BinaryReconstructionByErosionImageFilter + * \brief binary reconstruction by erosion of an image + * + * Reconstruction by erosion operates on a "marker" image and a "mask" + * image, and is defined as the erosion of the marker image with + * respect to the mask image iterated until stability. + * + * Geodesic morphology is described in Chapter 6.2 of Pierre Soille's + * book "Morphological Image Analysis: Principles and Applications", + * Second Edition, Springer, 2003. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa MorphologyImageFilter, ReconstructionByErosionImageFilter, BinaryReconstructionByDilationImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT BinaryReconstructionByErosionImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryReconstructionByErosionImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef BinaryNotImageFilter< InputImageType > NotType; + typedef AttributeLabelObject<unsigned long, ImageDimension, bool> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::BinaryReconstructionLabelMapFilter< LabelMapType, InputImageType > ReconstructionType; + typedef typename itk::AttributeOpeningLabelMapFilter< LabelMapType > OpeningType; + typedef typename itk::LabelMapMaskImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryReconstructionByErosionImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** Set the marker image */ + void SetMarkerImage(InputImageType *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 0, const_cast<InputImageType *>(input) ); + } + + /** Get the marker image */ + InputImageType * GetMarkerImage() + { + return static_cast<InputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(0))); + } + + /** Set the mask image */ + void SetMaskImage(const InputImageType *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<InputImageType *>(input) ); + } + + /** Get the mask image */ + InputImageType * GetMaskImage() + { + return static_cast<InputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + +protected: + BinaryReconstructionByErosionImageFilter(); + ~BinaryReconstructionByErosionImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryReconstructionByErosionImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryReconstructionByErosionImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + BinaryReconstructionByErosionImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryReconstructionByErosionImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryReconstructionByErosionImageFilter.txx b/Utilities/InsightJournal/itkBinaryReconstructionByErosionImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..471b56394add333f127931b5c5ed28163f4ffb1a --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryReconstructionByErosionImageFilter.txx @@ -0,0 +1,145 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryReconstructionByErosionImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryReconstructionByErosionImageFilter_txx +#define __itkBinaryReconstructionByErosionImageFilter_txx + +#include "itkBinaryReconstructionByErosionImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage> +BinaryReconstructionByErosionImageFilter<TInputImage> +::BinaryReconstructionByErosionImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + this->SetNumberOfRequiredInputs(2); +} + +template<class TInputImage> +void +BinaryReconstructionByErosionImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetMarkerImage()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } + + input = const_cast<InputImageType *>(this->GetMaskImage()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage> +void +BinaryReconstructionByErosionImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +BinaryReconstructionByErosionImageFilter<TInputImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename NotType::Pointer notMask = NotType::New(); + notMask->SetInput( this->GetMaskImage() ); + notMask->SetForegroundValue( m_ForegroundValue ); + notMask->SetBackgroundValue( m_BackgroundValue ); + notMask->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(notMask, .1f); + + typename NotType::Pointer notMarker = NotType::New(); + notMarker->SetInput( this->GetMarkerImage() ); + notMarker->SetForegroundValue( m_ForegroundValue ); + notMarker->SetBackgroundValue( m_BackgroundValue ); + notMarker->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(notMarker, .1f); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( notMask->GetOutput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .2f); + + typename ReconstructionType::Pointer reconstruction = ReconstructionType::New(); + reconstruction->SetInput( labelizer->GetOutput() ); + reconstruction->SetMarkerImage( notMarker->GetOutput() ); + reconstruction->SetForegroundValue( m_ForegroundValue ); + reconstruction->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(reconstruction, .2f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( reconstruction->GetOutput() ); + opening->SetLambda( true ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + // invert the image during the binarization + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetLabel( m_BackgroundValue ); + binarizer->SetNegated( true ); + binarizer->SetBackgroundValue( m_ForegroundValue ); + binarizer->SetFeatureImage( this->GetMaskImage() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage> +void +BinaryReconstructionByErosionImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryReconstructionLabelMapFilter.h b/Utilities/InsightJournal/itkBinaryReconstructionLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..755d99bcca80ca8fba7105903847f82d7ab7b72a --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryReconstructionLabelMapFilter.h @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryReconstructionLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryReconstructionLabelMapFilter_h +#define __itkBinaryReconstructionLabelMapFilter_h + +#include "itkInPlaceLabelMapFilter.h" +#include "itkAttributeLabelObject.h" + +namespace itk { +/** \class BinaryReconstructionLabelMapFilter + * \brief + * + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage, class TMarkerImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT BinaryReconstructionLabelMapFilter : + public InPlaceLabelMapFilter<TImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryReconstructionLabelMapFilter Self; + typedef InPlaceLabelMapFilter<TImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + typedef typename ImageType::LabelObjectType LabelObjectType; + + typedef TMarkerImage MarkerImageType; + typedef typename MarkerImageType::Pointer MarkerImagePointer; + typedef typename MarkerImageType::ConstPointer MarkerImageConstPointer; + typedef typename MarkerImageType::PixelType MarkerImagePixelType; + + typedef TAttributeAccessor AttributeAccessorType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryReconstructionLabelMapFilter, + InPlaceLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<PixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, PixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<PixelType>));*/ + /** End concept checking */ +#endif + + /** Set the marker image */ + void SetMarkerImage(TMarkerImage *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<TMarkerImage *>(input) ); + } + + /** Get the marker image */ + MarkerImageType * GetMarkerImage() + { + return static_cast<MarkerImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + /** Set the input image */ + void SetInput1(TImage *input) + { + this->SetInput( input ); + } + + /** Set the marker image */ + void SetInput2(TMarkerImage *input) + { + this->SetMarkerImage( input ); + } + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<MaskPixelType>::max(). + */ + itkSetMacro(ForegroundValue, PixelType); + itkGetConstMacro(ForegroundValue, PixelType); + +protected: + BinaryReconstructionLabelMapFilter(); + ~BinaryReconstructionLabelMapFilter() {}; + + virtual void ThreadedGenerateData( LabelObjectType * labelObject ); + + void PrintSelf(std::ostream& os, Indent indent) const; + +private: + BinaryReconstructionLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + MarkerImagePixelType m_ForegroundValue; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryReconstructionLabelMapFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryReconstructionLabelMapFilter.txx b/Utilities/InsightJournal/itkBinaryReconstructionLabelMapFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..62be887941b24b14f026f1255a7df2075ddf4700 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryReconstructionLabelMapFilter.txx @@ -0,0 +1,83 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryReconstructionLabelMapFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryReconstructionLabelMapFilter_txx +#define __itkBinaryReconstructionLabelMapFilter_txx + +#include "itkBinaryReconstructionLabelMapFilter.h" +#include "itkProgressReporter.h" + + +namespace itk { + +template <class TImage, class TMarkerImage, class TAttributeAccessor> +BinaryReconstructionLabelMapFilter<TImage, TMarkerImage, TAttributeAccessor> +::BinaryReconstructionLabelMapFilter() +{ + this->SetNumberOfRequiredInputs(2); + m_ForegroundValue = NumericTraits< MarkerImagePixelType >::max(); +} + + +template <class TImage, class TMarkerImage, class TAttributeAccessor> +void +BinaryReconstructionLabelMapFilter<TImage, TMarkerImage, TAttributeAccessor> +::ThreadedGenerateData( LabelObjectType * labelObject ) +{ + AttributeAccessorType accessor; + + const MarkerImageType * maskImage = this->GetMarkerImage(); + + typename LabelObjectType::LineContainerType::const_iterator lit; + typename LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + // iterate over all the lines to find a pixel inside the object + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + const IndexType & firstIdx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + + long endIdx0 = firstIdx[0] + length; + for( IndexType idx = firstIdx; idx[0]<endIdx0; idx[0]++ ) + { + const MarkerImagePixelType & v = maskImage->GetPixel( idx ); + if( v == m_ForegroundValue ) + { + // keep the object + accessor( labelObject, true ); + return; + } + } + } + + // remove the object + accessor( labelObject, false ); + +} + + +template <class TImage, class TMarkerImage, class TAttributeAccessor> +void +BinaryReconstructionLabelMapFilter<TImage, TMarkerImage, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<MarkerImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryShapeKeepNObjectsImageFilter.h b/Utilities/InsightJournal/itkBinaryShapeKeepNObjectsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..aed66974f853b43b53ef099b8fc2fa97034295d0 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryShapeKeepNObjectsImageFilter.h @@ -0,0 +1,188 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryShapeKeepNObjectsImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryShapeKeepNObjectsImageFilter_h +#define __itkBinaryShapeKeepNObjectsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkShapeLabelObject.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkShapeLabelMapFilter.h" +#include "itkShapeKeepNObjectsLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" + + +namespace itk { + +/** \class BinaryShapeKeepNObjectsImageFilter + * \brief keep N objects according to their shape attributes + * + * BinaryShapeKeepNObjectsImageFilter keep the N objects in a binary image + * with the highest (or lowest) attribute value. The attributes are the ones + * of the ShapeLabelObject. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa ShapeLabelObject, LabelShapeKeepNObjectsImageFilter, BinaryStatisticsKeepNObjectsImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT BinaryShapeKeepNObjectsImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryShapeKeepNObjectsImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef ShapeLabelObject<unsigned long, ImageDimension> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::ShapeLabelMapFilter< LabelMapType > LabelObjectValuatorType; + typedef typename LabelObjectType::AttributeType AttributeType; + typedef typename itk::ShapeKeepNObjectsLabelMapFilter< LabelMapType > KeepNObjectsType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryShapeKeepNObjectsImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** + * Set/Get the number of objects to keep + */ + itkGetConstMacro(NumberOfObjects, unsigned long); + itkSetMacro(NumberOfObjects, unsigned long); + + /** + * Set/Get the ordering of the objects. By default, the ones with the + * highest value are kept. Turming ReverseOrdering to true make this filter + * keep the objects with the smallest values + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + + /** + * Set/Get the attribute to use to select the object to keep. The default + * is "Size". + */ + itkGetConstMacro( Attribute, AttributeType ); + itkSetMacro( Attribute, AttributeType ); + void SetAttribute( const std::string & s ) + { + this->SetAttribute( LabelObjectType::GetAttributeFromName( s ) ); + } + +protected: + BinaryShapeKeepNObjectsImageFilter(); + ~BinaryShapeKeepNObjectsImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryShapeKeepNObjectsImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryShapeKeepNObjectsImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + +private: + BinaryShapeKeepNObjectsImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; + unsigned long m_NumberOfObjects; + bool m_ReverseOrdering; + AttributeType m_Attribute; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryShapeKeepNObjectsImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryShapeKeepNObjectsImageFilter.txx b/Utilities/InsightJournal/itkBinaryShapeKeepNObjectsImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..e1029c723d2156513427238ca9a30c79b892dc5a --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryShapeKeepNObjectsImageFilter.txx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryShapeKeepNObjectsImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryShapeKeepNObjectsImageFilter_txx +#define __itkBinaryShapeKeepNObjectsImageFilter_txx + +#include "itkBinaryShapeKeepNObjectsImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage> +BinaryShapeKeepNObjectsImageFilter<TInputImage> +::BinaryShapeKeepNObjectsImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + m_ReverseOrdering = false; + m_Attribute = LabelObjectType::SIZE; +} + +template<class TInputImage> +void +BinaryShapeKeepNObjectsImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage> +void +BinaryShapeKeepNObjectsImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +BinaryShapeKeepNObjectsImageFilter<TInputImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + if( m_Attribute == LabelObjectType::PERIMETER || m_Attribute == LabelObjectType::ROUNDNESS ) + { + valuator->SetComputePerimeter( true ); + } + if( m_Attribute == LabelObjectType::FERET_DIAMETER ) + { + valuator->SetComputeFeretDiameter( true ); + } + progress->RegisterInternalFilter(valuator, .3f); + + typename KeepNObjectsType::Pointer opening = KeepNObjectsType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetNumberOfObjects( m_NumberOfObjects ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetAttribute( m_Attribute ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetInput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage> +void +BinaryShapeKeepNObjectsImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "Attribute: " << LabelObjectType::GetNameFromAttribute(m_Attribute) << " (" << m_Attribute << ")" << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryShapeOpeningImageFilter.h b/Utilities/InsightJournal/itkBinaryShapeOpeningImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..4b14f53983b241ed3b0d4be489ba252d6a586780 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryShapeOpeningImageFilter.h @@ -0,0 +1,191 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryShapeOpeningImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryShapeOpeningImageFilter_h +#define __itkBinaryShapeOpeningImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkShapeLabelObject.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkShapeLabelMapFilter.h" +#include "itkShapeOpeningLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" + + +namespace itk { + +/** \class BinaryShapeOpeningImageFilter + * \brief remove the objects according to the value of their shape attribute + * + * BinaryShapeOpeningImageFilter removes the objects in a binary image + * with an attribute value smaller or greater than a threshold called Lambda. + * The attributes are the ones of the ShapeLabelObject. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa ShapeLabelObject, LabelShapeOpeningImageFilter, BinaryStatisticsOpeningImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT BinaryShapeOpeningImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryShapeOpeningImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef ShapeLabelObject<unsigned long, ImageDimension> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::ShapeLabelMapFilter< LabelMapType > LabelObjectValuatorType; + typedef typename LabelObjectType::AttributeType AttributeType; + typedef typename itk::ShapeOpeningLabelMapFilter< LabelMapType > OpeningType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryShapeOpeningImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** + * Set/Get the threshold used to keep or remove the objects. + */ + itkGetConstMacro(Lambda, double); + itkSetMacro(Lambda, double); + + /** + * Set/Get the ordering of the objects. By default, the objects with + * an attribute value smaller than Lamba are removed. Turning ReverseOrdering + * to true make this filter remove the object with an attribute value greater + * than Lambda instead. + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + + /** + * Set/Get the attribute to use to select the object to remove. The default + * is "Size". + */ + itkGetConstMacro( Attribute, AttributeType ); + itkSetMacro( Attribute, AttributeType ); + void SetAttribute( const std::string & s ) + { + this->SetAttribute( LabelObjectType::GetAttributeFromName( s ) ); + } + + +protected: + BinaryShapeOpeningImageFilter(); + ~BinaryShapeOpeningImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryShapeOpeningImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryShapeOpeningImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + BinaryShapeOpeningImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; + double m_Lambda; + bool m_ReverseOrdering; + AttributeType m_Attribute; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryShapeOpeningImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryShapeOpeningImageFilter.txx b/Utilities/InsightJournal/itkBinaryShapeOpeningImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..6ff29cc87372cda52a8503ace15847a43b24a44c --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryShapeOpeningImageFilter.txx @@ -0,0 +1,135 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryShapeOpeningImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryShapeOpeningImageFilter_txx +#define __itkBinaryShapeOpeningImageFilter_txx + +#include "itkBinaryShapeOpeningImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage> +BinaryShapeOpeningImageFilter<TInputImage> +::BinaryShapeOpeningImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + m_ReverseOrdering = false; + m_Attribute = LabelObjectType::SIZE; +} + +template<class TInputImage> +void +BinaryShapeOpeningImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage> +void +BinaryShapeOpeningImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +BinaryShapeOpeningImageFilter<TInputImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + if( m_Attribute == LabelObjectType::PERIMETER || m_Attribute == LabelObjectType::ROUNDNESS ) + { + valuator->SetComputePerimeter( true ); + } + if( m_Attribute == LabelObjectType::FERET_DIAMETER ) + { + valuator->SetComputeFeretDiameter( true ); + } + progress->RegisterInternalFilter(valuator, .3f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetLambda( m_Lambda ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetAttribute( m_Attribute ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetInput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage> +void +BinaryShapeOpeningImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "Lambda: " << m_Lambda << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "Attribute: " << LabelObjectType::GetNameFromAttribute(m_Attribute) << " (" << m_Attribute << ")" << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryStatisticsKeepNObjectsImageFilter.h b/Utilities/InsightJournal/itkBinaryStatisticsKeepNObjectsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..27bdfbc6b5bf6396d26b86ad74e8b8c804c94490 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryStatisticsKeepNObjectsImageFilter.h @@ -0,0 +1,219 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryStatisticsKeepNObjectsImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryStatisticsKeepNObjectsImageFilter_h +#define __itkBinaryStatisticsKeepNObjectsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkStatisticsLabelObject.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkStatisticsLabelMapFilter.h" +#include "itkStatisticsKeepNObjectsLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" + + +namespace itk { + +/** \class BinaryStatisticsKeepNObjectsImageFilter + * \brief keep N objects according to their statistics attributes + * + * BinaryStatisticsKeepNObjectsImageFilter keep the N objects in a binary image + * with the highest (or lowest) attribute value. The attributes are the ones + * of the StatisticsLabelObject. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa StatisticsLabelObject, LabelStatisticsKeepNObjectsImageFilter, BinaryShapeKeepNObjectsImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TFeatureImage> +class ITK_EXPORT BinaryStatisticsKeepNObjectsImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryStatisticsKeepNObjectsImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + typedef TFeatureImage FeatureImageType; + typedef typename FeatureImageType::Pointer FeatureImagePointer; + typedef typename FeatureImageType::ConstPointer FeatureImageConstPointer; + typedef typename FeatureImageType::PixelType FeatureImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef StatisticsLabelObject<unsigned long, ImageDimension> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::StatisticsLabelMapFilter< LabelMapType, TFeatureImage > LabelObjectValuatorType; + typedef typename LabelObjectType::AttributeType AttributeType; + typedef typename itk::StatisticsKeepNObjectsLabelMapFilter< LabelMapType > KeepNObjectsType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryStatisticsKeepNObjectsImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** + * Set/Get the number of objects to keep + */ + itkGetConstMacro(NumberOfObjects, unsigned long); + itkSetMacro(NumberOfObjects, unsigned long); + + /** + * Set/Get the ordering of the objects. By default, the ones with the + * highest value are kept. Turming ReverseOrdering to true make this filter + * keep the objects with the smallest values + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + + /** + * Set/Get the attribute to use to select the object to keep. The default + * is "Mean". + */ + itkGetConstMacro( Attribute, AttributeType ); + itkSetMacro( Attribute, AttributeType ); + void SetAttribute( const std::string & s ) + { + this->SetAttribute( LabelObjectType::GetAttributeFromName( s ) ); + } + + + /** Set the feature image */ + void SetFeatureImage(TFeatureImage *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<TFeatureImage *>(input) ); + } + + /** Get the feature image */ + FeatureImageType * GetFeatureImage() + { + return static_cast<FeatureImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + /** Set the input image */ + void SetInput1(InputImageType *input) + { + this->SetInput( input ); + } + + /** Set the feature image */ + void SetInput2(FeatureImageType *input) + { + this->SetFeatureImage( input ); + } + +protected: + BinaryStatisticsKeepNObjectsImageFilter(); + ~BinaryStatisticsKeepNObjectsImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryStatisticsKeepNObjectsImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryStatisticsKeepNObjectsImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + +private: + BinaryStatisticsKeepNObjectsImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; + unsigned long m_NumberOfObjects; + bool m_ReverseOrdering; + AttributeType m_Attribute; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryStatisticsKeepNObjectsImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryStatisticsKeepNObjectsImageFilter.txx b/Utilities/InsightJournal/itkBinaryStatisticsKeepNObjectsImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..8a309c19050c4e13f4afe763c3336dcd3f047b5b --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryStatisticsKeepNObjectsImageFilter.txx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryStatisticsKeepNObjectsImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryStatisticsKeepNObjectsImageFilter_txx +#define __itkBinaryStatisticsKeepNObjectsImageFilter_txx + +#include "itkBinaryStatisticsKeepNObjectsImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TFeatureImage> +BinaryStatisticsKeepNObjectsImageFilter<TInputImage, TFeatureImage> +::BinaryStatisticsKeepNObjectsImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + m_ReverseOrdering = false; + m_Attribute = LabelObjectType::MEAN; + this->SetNumberOfRequiredInputs(2); +} + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsKeepNObjectsImageFilter<TInputImage, TFeatureImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsKeepNObjectsImageFilter<TInputImage, TFeatureImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsKeepNObjectsImageFilter<TInputImage, TFeatureImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetFeatureImage( this->GetFeatureImage() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + valuator->SetComputeHistogram( false ); + if( m_Attribute == LabelObjectType::PERIMETER || m_Attribute == LabelObjectType::ROUNDNESS ) + { + valuator->SetComputePerimeter( true ); + } + if( m_Attribute == LabelObjectType::FERET_DIAMETER ) + { + valuator->SetComputeFeretDiameter( true ); + } + progress->RegisterInternalFilter(valuator, .3f); + + typename KeepNObjectsType::Pointer opening = KeepNObjectsType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetNumberOfObjects( m_NumberOfObjects ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetAttribute( m_Attribute ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetInput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsKeepNObjectsImageFilter<TInputImage, TFeatureImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "Attribute: " << LabelObjectType::GetNameFromAttribute(m_Attribute) << " (" << m_Attribute << ")" << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkBinaryStatisticsOpeningImageFilter.h b/Utilities/InsightJournal/itkBinaryStatisticsOpeningImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..74b267497ca8124f0c67392f0d0a394894c418b2 --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryStatisticsOpeningImageFilter.h @@ -0,0 +1,221 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryStatisticsOpeningImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryStatisticsOpeningImageFilter_h +#define __itkBinaryStatisticsOpeningImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkStatisticsLabelObject.h" +#include "itkLabelMap.h" +#include "itkBinaryImageToLabelMapFilter.h" +#include "itkStatisticsLabelMapFilter.h" +#include "itkStatisticsOpeningLabelMapFilter.h" +#include "itkLabelMapToBinaryImageFilter.h" + + +namespace itk { + +/** \class BinaryStatisticsOpeningImageFilter + * \brief remove the objects according to the value of their statistics attribute + * + * BinaryStatisticsOpeningImageFilter removes the objects in a binary image + * with an attribute value smaller or greater than a threshold called Lambda. + * The attributes are the ones of the StatisticsLabelObject. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa StatisticsLabelObject, LabelStatisticsOpeningImageFilter, BinaryShapeOpeningImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TFeatureImage> +class ITK_EXPORT BinaryStatisticsOpeningImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef BinaryStatisticsOpeningImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + typedef TFeatureImage FeatureImageType; + typedef typename FeatureImageType::Pointer FeatureImagePointer; + typedef typename FeatureImageType::ConstPointer FeatureImageConstPointer; + typedef typename FeatureImageType::PixelType FeatureImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef StatisticsLabelObject<unsigned long, ImageDimension> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::BinaryImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::StatisticsLabelMapFilter< LabelMapType, TFeatureImage > LabelObjectValuatorType; + typedef typename LabelObjectType::AttributeType AttributeType; + typedef typename itk::StatisticsOpeningLabelMapFilter< LabelMapType > OpeningType; + typedef typename itk::LabelMapToBinaryImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(BinaryStatisticsOpeningImageFilter, + ImageToImageFilter); + + /** + * Set/Get whether the connected components are defined strictly by + * face connectivity or by face+edge+vertex connectivity. Default is + * FullyConnectedOff. For objects that are 1 pixel wide, use + * FullyConnectedOn. + */ + itkSetMacro(FullyConnected, bool); + itkGetConstReferenceMacro(FullyConnected, bool); + itkBooleanMacro(FullyConnected); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the value used as "foreground" in the output image. + * Defaults to NumericTraits<PixelType>::max(). + */ + itkSetMacro(ForegroundValue, OutputImagePixelType); + itkGetConstMacro(ForegroundValue, OutputImagePixelType); + + /** + * Set/Get the threshold used to keep or remove the objects. + */ + itkGetConstMacro(Lambda, double); + itkSetMacro(Lambda, double); + + /** + * Set/Get the ordering of the objects. By default, the objects with + * an attribute value smaller than Lamba are removed. Turning ReverseOrdering + * to true make this filter remove the object with an attribute value greater + * than Lambda instead. + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + + /** + * Set/Get the attribute to use to select the object to remove. The default + * is "Mean". + */ + itkGetConstMacro( Attribute, AttributeType ); + itkSetMacro( Attribute, AttributeType ); + void SetAttribute( const std::string & s ) + { + this->SetAttribute( LabelObjectType::GetAttributeFromName( s ) ); + } + + + /** Set the feature image */ + void SetFeatureImage(TFeatureImage *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<TFeatureImage *>(input) ); + } + + /** Get the feature image */ + FeatureImageType * GetFeatureImage() + { + return static_cast<FeatureImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + /** Set the input image */ + void SetInput1(InputImageType *input) + { + this->SetInput( input ); + } + + /** Set the feature image */ + void SetInput2(FeatureImageType *input) + { + this->SetFeatureImage( input ); + } + +protected: + BinaryStatisticsOpeningImageFilter(); + ~BinaryStatisticsOpeningImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** BinaryStatisticsOpeningImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** BinaryStatisticsOpeningImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + BinaryStatisticsOpeningImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + bool m_FullyConnected; + OutputImagePixelType m_BackgroundValue; + OutputImagePixelType m_ForegroundValue; + double m_Lambda; + bool m_ReverseOrdering; + AttributeType m_Attribute; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkBinaryStatisticsOpeningImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkBinaryStatisticsOpeningImageFilter.txx b/Utilities/InsightJournal/itkBinaryStatisticsOpeningImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..b1bfdb5ad8235f9b228738c34c949c990ffe11fb --- /dev/null +++ b/Utilities/InsightJournal/itkBinaryStatisticsOpeningImageFilter.txx @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkBinaryStatisticsOpeningImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkBinaryStatisticsOpeningImageFilter_txx +#define __itkBinaryStatisticsOpeningImageFilter_txx + +#include "itkBinaryStatisticsOpeningImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TFeatureImage> +BinaryStatisticsOpeningImageFilter<TInputImage, TFeatureImage> +::BinaryStatisticsOpeningImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_ForegroundValue = NumericTraits<OutputImagePixelType>::max(); + m_FullyConnected = false; + m_ReverseOrdering = false; + m_Attribute = LabelObjectType::MEAN; + this->SetNumberOfRequiredInputs(2); +} + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsOpeningImageFilter<TInputImage, TFeatureImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsOpeningImageFilter<TInputImage, TFeatureImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsOpeningImageFilter<TInputImage, TFeatureImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetForegroundValue( m_ForegroundValue ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetFullyConnected( m_FullyConnected ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetFeatureImage( this->GetFeatureImage() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + valuator->SetComputeHistogram( false ); + if( m_Attribute == LabelObjectType::PERIMETER || m_Attribute == LabelObjectType::ROUNDNESS ) + { + valuator->SetComputePerimeter( true ); + } + if( m_Attribute == LabelObjectType::FERET_DIAMETER ) + { + valuator->SetComputeFeretDiameter( true ); + } + progress->RegisterInternalFilter(valuator, .3f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetLambda( m_Lambda ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetAttribute( m_Attribute ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetForegroundValue( m_ForegroundValue ); + binarizer->SetBackgroundValue( m_BackgroundValue ); + binarizer->SetBackgroundImage( this->GetInput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TFeatureImage> +void +BinaryStatisticsOpeningImageFilter<TInputImage, TFeatureImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "FullyConnected: " << m_FullyConnected << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_ForegroundValue) << std::endl; + os << indent << "Lambda: " << m_Lambda << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; + os << indent << "Attribute: " << LabelObjectType::GetNameFromAttribute(m_Attribute) << " (" << m_Attribute << ")" << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkConnectedComponentAlgorithm.h b/Utilities/InsightJournal/itkConnectedComponentAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..d97cdafdbe8d0321e65675d5cf5fb78a202c91aa --- /dev/null +++ b/Utilities/InsightJournal/itkConnectedComponentAlgorithm.h @@ -0,0 +1,138 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkConnectedComponentAlgorithm.h,v $ + Language: C++ + Date: $Date: 2006/12/14 10:27:37 $ + Version: $Revision: 1.2 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#ifndef __itkConnectedComponentAlgorithm_h +#define __itkConnectedComponentAlgorithm_h + +#include "itkImage.h" +#include "itkConstShapedNeighborhoodIterator.h" +#include "itkShapedNeighborhoodIterator.h" + +namespace itk +{ +template< class TIterator > +TIterator* +setConnectivity( TIterator* it, bool fullyConnected=false ) +{ + typename TIterator::OffsetType offset; + it->ClearActiveList(); + if( !fullyConnected) + { + // only activate the neighbors that are face connected + // to the current pixel. do not include the center pixel + offset.Fill( 0 ); + for( unsigned int d=0; d < TIterator::Dimension; ++d ) + { + offset[d] = -1; + it->ActivateOffset( offset ); + offset[d] = 1; + it->ActivateOffset( offset ); + offset[d] = 0; + } + } + else + { + // activate all neighbors that are face+edge+vertex + // connected to the current pixel. do not include the center pixel + unsigned int centerIndex = it->GetCenterNeighborhoodIndex(); + for( unsigned int d=0; d < centerIndex*2 + 1; d++ ) + { + offset = it->GetOffset( d ); + it->ActivateOffset( offset ); + } + offset.Fill(0); + it->DeactivateOffset( offset ); + } + return it; +} + +template< class TIterator > +TIterator* +setConnectivityPrevious( TIterator* it, bool fullyConnected=false ) +{ + // activate the "previous" neighbours + typename TIterator::OffsetType offset; + it->ClearActiveList(); + if( !fullyConnected) + { + // only activate the neighbors that are face connected + // to the current pixel. do not include the center pixel + offset.Fill( 0 ); + for( unsigned int d=0; d < TIterator::Dimension; ++d ) + { + offset[d] = -1; + it->ActivateOffset( offset ); +// offset[d] = 1; +// it->ActivateOffset( offset ); + offset[d] = 0; + } + } + else + { + // activate all neighbors that are face+edge+vertex + // connected to the current pixel. do not include the center pixel + unsigned int centerIndex = it->GetCenterNeighborhoodIndex(); + for( unsigned int d=0; d < centerIndex; d++ ) + { + offset = it->GetOffset( d ); + it->ActivateOffset( offset ); + } + offset.Fill(0); + it->DeactivateOffset( offset ); + } + return it; +} + +template< class TIterator > +TIterator* +setConnectivityLater( TIterator* it, bool fullyConnected=false ) +{ + // activate the "later" neighbours + typename TIterator::OffsetType offset; + it->ClearActiveList(); + if( !fullyConnected) + { + // only activate the neighbors that are face connected + // to the current pixel. do not include the center pixel + offset.Fill( 0 ); + for( unsigned int d=0; d < TIterator::Dimension; ++d ) + { + offset[d] = 1; + it->ActivateOffset( offset ); + offset[d] = 0; + } + } + else + { + // activate all neighbors that are face+edge+vertex + // connected to the current pixel. do not include the center pixel + unsigned int centerIndex = it->GetCenterNeighborhoodIndex(); + for( unsigned int d=centerIndex+1; d < 2*centerIndex+1; d++ ) + { + offset = it->GetOffset( d ); + it->ActivateOffset( offset ); + } + offset.Fill(0); + it->DeactivateOffset( offset ); + } + return it; +} + +} + + +#endif diff --git a/Utilities/InsightJournal/itkLabelAttributeKeepNObjectsImageFilter.h b/Utilities/InsightJournal/itkLabelAttributeKeepNObjectsImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..099070239940f85da71fa80beb11d7a6fdd44d1a --- /dev/null +++ b/Utilities/InsightJournal/itkLabelAttributeKeepNObjectsImageFilter.h @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelAttributeKeepNObjectsImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelAttributeKeepNObjectsImageFilter_h +#define __itkLabelAttributeKeepNObjectsImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkLabelMap.h" +#include "itkLabelImageToLabelMapFilter.h" +#include "itkAttributeKeepNObjectsLabelMapFilter.h" +#include "itkLabelMapToLabelImageFilter.h" +#include "itkAttributeLabelObject.h" + + +namespace itk { + +/** \class LabelAttributeKeepNObjectsImageFilter + * \brief keep N objects according to a generic attribute + * + * LabelAttributeKeepNObjectsImageFilter keep the N objects in a labeled image + * with the highest (or lowest) attribute value. The attribute is valued with + * and attribute valuator given in template parameter and is accessed with a + * attribute accessor also given in template parameter. + * + * Used in combination with AttributeLabelObject, and a specilized attribute valuator, + * this class is the most efficient way to keep N objects in a labeled image. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject, InPlaceLabelMapFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT LabelAttributeKeepNObjectsImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelAttributeKeepNObjectsImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef TLabelObject LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::LabelImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef TLabelObjectValuator LabelObjectValuatorType; + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + typedef typename itk::AttributeKeepNObjectsLabelMapFilter< LabelMapType, AttributeAccessorType > KeepNObjectsType; + typedef typename itk::LabelMapToLabelImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelAttributeKeepNObjectsImageFilter, + ImageToImageFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the number of objects to keep + */ + itkGetConstMacro(NumberOfObjects, unsigned long); + itkSetMacro(NumberOfObjects, unsigned long); + + /** + * Set/Get the ordering of the objects. By default, the ones with the + * highest value are kept. Turming ReverseOrdering to true make this filter + * keep the objects with the smallest values + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + +protected: + LabelAttributeKeepNObjectsImageFilter(); + ~LabelAttributeKeepNObjectsImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** LabelAttributeKeepNObjectsImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** LabelAttributeKeepNObjectsImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + virtual void CustomizeInternalFilters( LabelizerType *, LabelObjectValuatorType *, KeepNObjectsType *, BinarizerType* ) {}; + +private: + LabelAttributeKeepNObjectsImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + OutputImagePixelType m_BackgroundValue; + unsigned long m_NumberOfObjects; + bool m_ReverseOrdering; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelAttributeKeepNObjectsImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelAttributeKeepNObjectsImageFilter.txx b/Utilities/InsightJournal/itkLabelAttributeKeepNObjectsImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..a403922ecb0200c47f9924b627398019383f6132 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelAttributeKeepNObjectsImageFilter.txx @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelAttributeKeepNObjectsImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelAttributeKeepNObjectsImageFilter_txx +#define __itkLabelAttributeKeepNObjectsImageFilter_txx + +#include "itkLabelAttributeKeepNObjectsImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +LabelAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::LabelAttributeKeepNObjectsImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_NumberOfObjects = 1; + m_ReverseOrdering = false; +} + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(valuator, .3f); + + typename KeepNObjectsType::Pointer opening = KeepNObjectsType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetNumberOfObjects( m_NumberOfObjects ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + this->CustomizeInternalFilters( labelizer, valuator, opening, binarizer ); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeKeepNObjectsImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelAttributeOpeningImageFilter.h b/Utilities/InsightJournal/itkLabelAttributeOpeningImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..149fc3ed34cef2741845bd72c41f6c5b1731ada8 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelAttributeOpeningImageFilter.h @@ -0,0 +1,167 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelAttributeOpeningImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelAttributeOpeningImageFilter_h +#define __itkLabelAttributeOpeningImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkLabelMap.h" +#include "itkLabelImageToLabelMapFilter.h" +#include "itkAttributeOpeningLabelMapFilter.h" +#include "itkLabelMapToLabelImageFilter.h" +#include "itkAttributeLabelObject.h" + + +namespace itk { + +/** \class LabelAttributeOpeningImageFilter + * \brief remove the objects in a labeled image according to a generic attribute + * + * LabelAttributeOpeningImageFilter remove the objects in a labeled image + * with an attribute value smaller or greater than a threshold called Lambda. + * The attribute is valued with and attribute valuator given in template parameter + * and is accessed with an attribute accessor also given in template parameter. + * + * Used in combination with AttributeLabelObject, and a specilized attribute valuator, + * this class is the most efficient way to perform an attribute opening in a labeled + * image. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject, InPlaceLabelMapFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT LabelAttributeOpeningImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelAttributeOpeningImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef TLabelObject LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::LabelImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef TLabelObjectValuator LabelObjectValuatorType; + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + typedef typename itk::AttributeOpeningLabelMapFilter< LabelMapType, AttributeAccessorType > OpeningType; + typedef typename itk::LabelMapToLabelImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelAttributeOpeningImageFilter, + ImageToImageFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * Set/Get the threshold used to keep or remove the objects. + */ + itkGetConstMacro(Lambda, AttributeValueType); + itkSetMacro(Lambda, AttributeValueType); + + /** + * Set/Get the ordering of the objects. By default, the objects with + * an attribute value smaller than Lamba are removed. Turning ReverseOrdering + * to true make this filter remove the object with an attribute value greater + * than Lambda instead. + */ + itkGetConstMacro( ReverseOrdering, bool ); + itkSetMacro( ReverseOrdering, bool ); + itkBooleanMacro( ReverseOrdering ); + +protected: + LabelAttributeOpeningImageFilter(); + ~LabelAttributeOpeningImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** LabelAttributeOpeningImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** LabelAttributeOpeningImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + virtual void CustomizeInternalFilters( LabelizerType *, LabelObjectValuatorType *, OpeningType *, BinarizerType* ) {}; + + +private: + LabelAttributeOpeningImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + OutputImagePixelType m_BackgroundValue; + AttributeValueType m_Lambda; + bool m_ReverseOrdering; +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelAttributeOpeningImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelAttributeOpeningImageFilter.txx b/Utilities/InsightJournal/itkLabelAttributeOpeningImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..cd7b693895c24aaab91dd981d23238173e515960 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelAttributeOpeningImageFilter.txx @@ -0,0 +1,118 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelAttributeOpeningImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelAttributeOpeningImageFilter_txx +#define __itkLabelAttributeOpeningImageFilter_txx + +#include "itkLabelAttributeOpeningImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +LabelAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::LabelAttributeOpeningImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + m_Lambda = NumericTraits< AttributeValueType >::Zero; + m_ReverseOrdering = false; +} + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetInput() ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .3f); + + typename LabelObjectValuatorType::Pointer valuator = LabelObjectValuatorType::New(); + valuator->SetInput( labelizer->GetOutput() ); + valuator->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(valuator, .3f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( valuator->GetOutput() ); + opening->SetLambda( m_Lambda ); + opening->SetReverseOrdering( m_ReverseOrdering ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .2f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .2f); + + this->CustomizeInternalFilters( labelizer, valuator, opening, binarizer ); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage, class TLabelObject, class TLabelObjectValuator, class TAttributeAccessor> +void +LabelAttributeOpeningImageFilter<TInputImage, TLabelObject, TLabelObjectValuator, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "Lambda: " << m_Lambda << std::endl; + os << indent << "ReverseOrdering: " << m_ReverseOrdering << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelMapMaskImageFilter.h b/Utilities/InsightJournal/itkLabelMapMaskImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..9e8c8426fd1baeb9a6a9d916d0f867ed14ffdc5d --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapMaskImageFilter.h @@ -0,0 +1,190 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapMaskImageFilter.h,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.4 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapMaskImageFilter_h +#define __itkLabelMapMaskImageFilter_h + +#include "itkLabelMapFilter.h" +#include "itkBarrier.h" + +namespace itk { + +/** \class LabelMapMaskImageFilter + * \brief Mask and image with a LabelMap + * + * LabelMapMaskImageFilter mask the content of an input image according + * to the content of the input LabelMap. The masked pixel of the input image + * are set to the BackgroundValue. + * LabelMapMaskImageFilter can keep the input image for one label only, with + * Negated = false (the default) or it can mask the input image for a single label, when + * Negated equals true. In Both cases, the label is set with SetLabel(). + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa LabelMapToBinaryImageFilter, LabelMapToLabelImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TOutputImage> +class ITK_EXPORT LabelMapMaskImageFilter : + public LabelMapFilter<TInputImage, TOutputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelMapMaskImageFilter Self; + typedef LabelMapFilter<TInputImage, TOutputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename InputImageType::LabelObjectType LabelObjectType; + typedef typename LabelObjectType::LabelType LabelType; + + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + typedef typename OutputImageType::IndexType IndexType; + typedef typename OutputImageType::SizeType SizeType; + typedef typename OutputImageType::RegionType RegionType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TOutputImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelMapMaskImageFilter, + ImageToImageFilter); + + /** Set the feature image */ + void SetFeatureImage(const TOutputImage *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<TOutputImage *>(input) ); + } + + /** Get the feature image */ + OutputImageType * GetFeatureImage() + { + return static_cast<OutputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + /** Set the input image */ + void SetInput1(TInputImage *input) + { + this->SetInput( input ); + } + + /** Set the feature image */ + void SetInput2(TOutputImage *input) + { + this->SetFeatureImage( input ); + } + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::Zero. + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** + * The label to mask or to not mask, depending on the value of the Negated ivar. + */ + itkSetMacro(Label, InputImagePixelType); + itkGetConstMacro(Label, InputImagePixelType); + + /** + * Set/Get whether the Label should be masked or not. + */ + itkSetMacro(Negated, bool); + itkGetConstReferenceMacro(Negated, bool); + itkBooleanMacro(Negated); + + /** + * Set/Get whether the image size should be adjusted to the masked image or not. + */ + itkSetMacro(Crop, bool); + itkGetConstReferenceMacro(Crop, bool); + itkBooleanMacro(Crop); + + /** + * Set/Get the boder added to the mask before the crop. The default is 0 on + * all the axes. + */ + itkSetMacro(CropBorder, SizeType); + itkGetConstReferenceMacro(CropBorder, SizeType); + +protected: + LabelMapMaskImageFilter(); + ~LabelMapMaskImageFilter() {}; + + /** LabelMapMaskImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** LabelMapMaskImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + virtual void GenerateOutputInformation(); + + virtual void BeforeThreadedGenerateData(); + + virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId ); + + virtual void ThreadedGenerateData( LabelObjectType * labelObject ); + + void PrintSelf(std::ostream& os, Indent indent) const; + +private: + LabelMapMaskImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + InputImagePixelType m_Label; + OutputImagePixelType m_BackgroundValue; + bool m_Negated; + bool m_Crop; + SizeType m_CropBorder; + + TimeStamp m_CropTimeStamp; + + typename Barrier::Pointer m_Barrier; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelMapMaskImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelMapMaskImageFilter.txx b/Utilities/InsightJournal/itkLabelMapMaskImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..7d5143d91aaa814809c9885ce513722d3631387c --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapMaskImageFilter.txx @@ -0,0 +1,442 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapMaskImageFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapMaskImageFilter_txx +#define __itkLabelMapMaskImageFilter_txx + +#include "itkLabelMapMaskImageFilter.h" +#include "itkNumericTraits.h" +#include "itkProgressReporter.h" +#include "itkImageRegionConstIterator.h" +#include "itkImageRegionIterator.h" + +namespace itk { + +template <class TInputImage, class TOutputImage> +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::LabelMapMaskImageFilter() +{ + this->SetNumberOfRequiredInputs(2); + m_Label = NumericTraits< InputImagePixelType >::One; + m_BackgroundValue = NumericTraits< OutputImagePixelType >::Zero; + m_Negated = false; + m_Crop = false; + m_CropBorder.Fill( 0 ); +} + +template <class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if ( !input ) + { return; } + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); +} + +template <class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::GenerateOutputInformation() +{ + + if( m_Crop ) + { + const InputImageType * input = this->GetInput(); + + if( !(input->GetMTime() > m_CropTimeStamp) && !(this->GetMTime() > m_CropTimeStamp) ) + { + // early exit, crop sizes already computed + // std::cout << "Don't recompute the output size again." << std::endl; + // std::cout << "LargestPossibleRegion: " << this->GetOutput()->GetLargestPossibleRegion() << std::endl; + // std::cout << "BufferedRegion: " << this->GetOutput()->GetBufferedRegion() << std::endl; + // std::cout << "RequestedRegion: " << this->GetOutput()->GetRequestedRegion() << std::endl; + return; + } + + // first, call the default implementation, to be sure to forgot nothing + Superclass::GenerateOutputInformation(); + + // update the input if needed + if( input->GetSource()) + { + ProcessObject * upstream = input->GetSource(); + if (upstream) + { + // this->SetInput(NULL); + // std::cout << "Update the input (again?)." << std::endl; + upstream->Update(); + // this->SetInput(input); + } + } + + // Prefetch image region and size + InputImageRegionType cropRegion = input->GetLargestPossibleRegion(); + + // now the output image size can be computed + if( m_Negated ) + { + if( input->GetBackgroundValue() != m_Label ) + { + // the "bad" case - the zone outside the object is at least partially + // covered by the background, which is not explicitely defined. + + // simply do nothing for now + // TODO: implement that part + itkWarningMacro( << "Cropping according to background label is no yet implemented. The full image will be used." ); + + } + else + { + // compute the bounding box of all the objects which don't have that label + IndexType mins; + mins.Fill( NumericTraits< long >::max() ); + IndexType maxs; + maxs.Fill( NumericTraits< long >::NonpositiveMin() ); + typename InputImageType::LabelObjectContainerType container = this->GetInput()->GetLabelObjectContainer(); + for( typename InputImageType::LabelObjectContainerType::const_iterator loit = container.begin(); + loit != container.end(); + loit++ ) + { + if( loit->first != m_Label ) + { + typename LabelObjectType::LineContainerType::const_iterator lit; + typename LabelObjectType::LineContainerType & lineContainer = loit->second->GetLineContainer(); + // iterate over all the lines + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + const IndexType & idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + + // update the mins and maxs + for( int i=0; i<ImageDimension; i++) + { + if( idx[i] < mins[i] ) + { + mins[i] = idx[i]; + } + if( idx[i] > maxs[i] ) + { + maxs[i] = idx[i]; + } + } + // must fix the max for the axis 0 + if( idx[0] + (long)length > maxs[0] ) + { + maxs[0] = idx[0] + length - 1; + } + } + } + } + + // final computation + SizeType regionSize; + for( int i=0; i<ImageDimension; i++ ) + { + regionSize[i] = maxs[i] - mins[i] + 1; + } + cropRegion.SetIndex( mins ); + cropRegion.SetSize( regionSize ); + + } + } + else + { + if( input->GetBackgroundValue() == m_Label ) + { + // the other "bad" case - the label we want is not defined as a label object, + // but implicitely, in the zones not defined. + + // simply do nothing for now + // TODO: implement that part + itkWarningMacro( << "Cropping according to background label is no yet implemented. The full image will be used." ); + + } + else + { + // just find the bounding box of the object with that label + + const LabelObjectType * labelObject = input->GetLabelObject( m_Label ); + typename LabelObjectType::LineContainerType::const_iterator lit; + const typename LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + IndexType mins; + mins.Fill( NumericTraits< long >::max() ); + IndexType maxs; + maxs.Fill( NumericTraits< long >::NonpositiveMin() ); + // iterate over all the lines + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + const IndexType & idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + + // update the mins and maxs + for( int i=0; i<ImageDimension; i++) + { + if( idx[i] < mins[i] ) + { + mins[i] = idx[i]; + } + if( idx[i] > maxs[i] ) + { + maxs[i] = idx[i]; + } + } + // must fix the max for the axis 0 + if( idx[0] + (long)length > maxs[0] ) + { + maxs[0] = idx[0] + length - 1; + } + } + // final computation + SizeType regionSize; + for( int i=0; i<ImageDimension; i++ ) + { + regionSize[i] = maxs[i] - mins[i] + 1; + } + cropRegion.SetIndex( mins ); + cropRegion.SetSize( regionSize ); + + } + } + + // pad by the crop border, but take care to not be larger than the largest + // possible region of the input image + cropRegion.PadByRadius( m_CropBorder ); + cropRegion.Crop( input->GetLargestPossibleRegion() ); + + // finally set that region as the largest output region + this->GetOutput()->SetLargestPossibleRegion( cropRegion ); + + m_CropTimeStamp.Modified(); + + } + else + { + // no crop -> use the default implementation + Superclass::GenerateOutputInformation(); + } + + // std::cout << "LargestPossibleRegion: " << this->GetOutput()->GetLargestPossibleRegion() << std::endl; + // std::cout << "BufferedRegion: " << this->GetOutput()->GetBufferedRegion() << std::endl; + // std::cout << "RequestedRegion: " << this->GetOutput()->GetRequestedRegion() << std::endl; + +} + +template <class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template <class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::BeforeThreadedGenerateData() +{ + m_Barrier = Barrier::New(); + m_Barrier->Initialize( this->GetNumberOfThreads() ); + + Superclass::BeforeThreadedGenerateData(); + +} + + +template <class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, int threadId ) +{ + OutputImageType * output = this->GetOutput(); + InputImageType * input = const_cast<InputImageType *>(this->GetInput()); + const OutputImageType * input2 = this->GetFeatureImage(); + + // we will keep the values from the feature image if the same pixel in the label image + // equals the label given by the user. The other pixels are set to the background value. + if( ( input->GetBackgroundValue() == m_Label ) ^ m_Negated ) + { + // the user want the mask to be the background of the label collection image + // copy the feature image to the output image + ImageRegionConstIterator< OutputImageType > featureIt( input2, outputRegionForThread ); + ImageRegionIterator< OutputImageType > outputIt( output, outputRegionForThread ); + + for ( featureIt.GoToBegin(), outputIt.GoToBegin(); + !featureIt.IsAtEnd(); + ++featureIt, ++outputIt ) + { + outputIt.Set( featureIt.Get() ); + } + } + else + { + ImageRegionIterator< OutputImageType > outputIt( output, outputRegionForThread ); + + for ( outputIt.GoToBegin(); !outputIt.IsAtEnd(); ++outputIt ) + { + outputIt.Set( m_BackgroundValue ); + } + } + + // wait for the other threads to complete that part + m_Barrier->Wait(); + + if( input->GetBackgroundValue() == m_Label ) + { + // and delegate to the superclass implementation to use the thread support for the label objects + Superclass::ThreadedGenerateData( outputRegionForThread, threadId ); + } + else + { + // need only one thread - take the first one + if( threadId == 0 ) + { + const LabelObjectType * labelObject = this->GetLabelMap()->GetLabelObject( m_Label ); + ProgressReporter progress( this, 0, labelObject->GetLineContainer().size() ); + + if( !m_Negated ) + { + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + const typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + output->SetPixel( idx, input2->GetPixel( idx ) ); + idx[0]++; + } + progress.CompletedPixel(); + } + } + else + { + // and mark the label object as background + + // should we take care to not write outside the image ? + bool testIdxIsInside = m_Crop && ( input->GetBackgroundValue() == m_Label ) ^ m_Negated; + RegionType outputRegion = output->GetLargestPossibleRegion(); + + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + const typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + if( !testIdxIsInside || outputRegion.IsInside( idx ) ) + { + output->SetPixel( idx, m_BackgroundValue ); + } + idx[0]++; + } + progress.CompletedPixel(); + } + } + + } + } +} + + +template<class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::ThreadedGenerateData( LabelObjectType * labelObject ) +{ + OutputImageType * output = this->GetOutput(); + InputImageType * input = const_cast<InputImageType *>(this->GetInput()); + const OutputImageType * input2 = this->GetFeatureImage(); + + if( !m_Negated ) + { + // we will keep the values from the feature image if the same pixel in the label image + // equals the label given by the user. The other pixels are set to the background value. + + // should we take care to not write outside the image ? + bool testIdxIsInside = m_Crop && ( input->GetBackgroundValue() == m_Label ) ^ m_Negated; + RegionType outputRegion = output->GetLargestPossibleRegion(); + + // the user want the mask to be the background of the label collection image + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + if( !testIdxIsInside || outputRegion.IsInside( idx ) ) + { + output->SetPixel( idx, m_BackgroundValue ); + } + idx[0]++; + } + } + } + else + { + // we will keep the pixels from the feature image if the same pixel from the label image + // is not equal to the label provided by the user. The pixels with the label provided by the + // user are set to the background value + + // and copy the feature image where the label objects are + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + output->SetPixel( idx, input2->GetPixel( idx ) ); + idx[0]++; + } + } + } +} + + +template<class TInputImage, class TOutputImage> +void +LabelMapMaskImageFilter<TInputImage, TOutputImage> +::PrintSelf(std::ostream& os, Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "Label: " << static_cast<typename NumericTraits<LabelType>::PrintType>(m_Label) << std::endl; + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; + os << indent << "Negated: " << m_Negated << std::endl; + os << indent << "Crop: " << m_Crop << std::endl; + os << indent << "CropBorder: " << m_CropBorder << std::endl; +} + + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelMapOverlayImageFilter.h b/Utilities/InsightJournal/itkLabelMapOverlayImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..e4431da5028f65f91a03ea6e9ab65b939f7c988d --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapOverlayImageFilter.h @@ -0,0 +1,163 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapOverlayImageFilter.h,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.4 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapOverlayImageFilter_h +#define __itkLabelMapOverlayImageFilter_h + +#include "itkLabelMapFilter.h" +#include "itkBarrier.h" +#include "itkLabelOverlayFunctor.h" + +namespace itk { + +/** \class LabelMapOverlayImageFilter + * \brief Mask and image with a LabelMap + * + * LabelMapOverlayImageFilter mask the content of an input image according + * to the content of the input LabelMap. The masked pixel of the input image + * are set to the BackgroundValue. + * LabelMapOverlayImageFilter can keep the input image for one label only, with + * Negated = false (the default) or it can mask the input image for a single label, when + * Negated equals true. In Both cases, the label is set with SetLabel(). + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa LabelMapToBinaryImageFilter, LabelMapToLabelImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TFeatureImage, class TOutputImage=Image< RGBPixel< typename TFeatureImage::PixelType >, TFeatureImage::ImageDimension > > +class ITK_EXPORT LabelMapOverlayImageFilter : + public LabelMapFilter<TInputImage, TOutputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelMapOverlayImageFilter Self; + typedef LabelMapFilter<TInputImage, TOutputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename InputImageType::LabelObjectType LabelObjectType; + typedef typename LabelObjectType::LabelType LabelType; + + typedef TFeatureImage FeatureImageType; + typedef typename FeatureImageType::Pointer FeatureImagePointer; + typedef typename FeatureImageType::ConstPointer FeatureImageConstPointer; + typedef typename FeatureImageType::RegionType FeatureImageRegionType; + typedef typename FeatureImageType::PixelType FeatureImagePixelType; + + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + typedef typename OutputImageType::IndexType IndexType; + typedef typename OutputImageType::SizeType SizeType; + typedef typename OutputImageType::RegionType RegionType; + + typedef typename Functor::LabelOverlayFunctor<FeatureImagePixelType, InputImagePixelType, OutputImagePixelType> FunctorType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TOutputImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelMapOverlayImageFilter, + ImageToImageFilter); + + /** Set the feature image */ + void SetFeatureImage(TFeatureImage *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<TFeatureImage *>(input) ); + } + + /** Get the feature image */ + FeatureImageType * GetFeatureImage() + { + return static_cast<FeatureImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + /** Set the input image */ + void SetInput1(TInputImage *input) + { + this->SetInput( input ); + } + + /** Set the feature image */ + void SetInput2(TFeatureImage *input) + { + this->SetFeatureImage( input ); + } + + /** Set/Get the opacity of the colored label image. The value must be + * between 0 and 1 + */ + itkSetMacro( Opacity, double ); + itkGetConstReferenceMacro( Opacity, double ); + +protected: + LabelMapOverlayImageFilter(); + ~LabelMapOverlayImageFilter() {}; + + /** LabelMapOverlayImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** LabelMapOverlayImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + virtual void BeforeThreadedGenerateData(); + + virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId ); + + virtual void ThreadedGenerateData( LabelObjectType * labelObject ); + + void PrintSelf(std::ostream& os, Indent indent) const; + + +private: + LabelMapOverlayImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + double m_Opacity; + typename Barrier::Pointer m_Barrier; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelMapOverlayImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelMapOverlayImageFilter.txx b/Utilities/InsightJournal/itkLabelMapOverlayImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..b6d844fb9667ee261234fb214ee1b2b30174e74c --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapOverlayImageFilter.txx @@ -0,0 +1,150 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapOverlayImageFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapOverlayImageFilter_txx +#define __itkLabelMapOverlayImageFilter_txx + +#include "itkLabelMapOverlayImageFilter.h" +#include "itkNumericTraits.h" +#include "itkProgressReporter.h" +#include "itkImageRegionConstIterator.h" +#include "itkImageRegionIterator.h" + +namespace itk { + +template<class TInputImage, class TFeatureImage, class TOutputImage> +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::LabelMapOverlayImageFilter() +{ + this->SetNumberOfRequiredInputs(2); + m_Opacity = 0.5; +} + +template<class TInputImage, class TFeatureImage, class TOutputImage> +void +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if ( !input ) + { return; } + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); +} + +template <class TInputImage, class TFeatureImage, class TOutputImage> +void +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TFeatureImage, class TOutputImage> +void +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::BeforeThreadedGenerateData() +{ + m_Barrier = Barrier::New(); + m_Barrier->Initialize( this->GetNumberOfThreads() ); + + Superclass::BeforeThreadedGenerateData(); + +} + + +template<class TInputImage, class TFeatureImage, class TOutputImage> +void +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::ThreadedGenerateData( const OutputImageRegionType& outputRegionForThread, int threadId ) +{ + OutputImageType * output = this->GetOutput(); + InputImageType * input = const_cast<InputImageType *>(this->GetInput()); + const FeatureImageType * input2 = this->GetFeatureImage(); + + FunctorType function; + function.SetBackgroundValue( input->GetBackgroundValue() ); + function.SetOpacity( m_Opacity ); + + ImageRegionConstIterator< FeatureImageType > featureIt( input2, outputRegionForThread ); + ImageRegionIterator< OutputImageType > outputIt( output, outputRegionForThread ); + + for ( featureIt.GoToBegin(), outputIt.GoToBegin(); + !featureIt.IsAtEnd(); + ++featureIt, ++outputIt ) + { + outputIt.Set( function( featureIt.Get(), input->GetBackgroundValue() ) ); + } + + // wait for the other threads to complete that part + m_Barrier->Wait(); + + // and delegate to the superclass implementation to use the thread support for the label objects + Superclass::ThreadedGenerateData( outputRegionForThread, threadId ); +} + + +template<class TInputImage, class TFeatureImage, class TOutputImage> +void +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::ThreadedGenerateData( LabelObjectType * labelObject ) +{ + OutputImageType * output = this->GetOutput(); + InputImageType * input = const_cast<InputImageType *>(this->GetInput()); + const FeatureImageType * input2 = this->GetFeatureImage(); + + FunctorType function; + function.SetBackgroundValue( input->GetBackgroundValue() ); + function.SetOpacity( m_Opacity ); + + const typename LabelObjectType::LabelType & label = labelObject->GetLabel(); + + // the user want the mask to be the background of the label collection image + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + output->SetPixel( idx, function( input2->GetPixel(idx), label ) ); + idx[0]++; + } + } + +} + + +template<class TInputImage, class TFeatureImage, class TOutputImage> +void +LabelMapOverlayImageFilter<TInputImage, TFeatureImage, TOutputImage> +::PrintSelf(std::ostream& os, Indent indent) const +{ + Superclass::PrintSelf(os,indent); + + os << indent << "Opacity: " << m_Opacity << std::endl; +} + + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelMapToAttributeImageFilter.h b/Utilities/InsightJournal/itkLabelMapToAttributeImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..34161c5d41a13ac49b0dda4fcffa57204153bc4f --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapToAttributeImageFilter.h @@ -0,0 +1,120 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapToAttributeImageFilter.h,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.4 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapToAttributeImageFilter_h +#define __itkLabelMapToAttributeImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkAttributeLabelObject.h" + +namespace itk { + +/** \class LabelMapToAttributeImageFilter + * \brief Convert a LabelMap to a labeled image + * + * LabelMapToAttributeImageFilter converts a LabelMap to an + * Image where all the pixels get the attribute value of the label object they belong. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa LabelMapToBinaryImageFilter, LabelMapMaskImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TOutputImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TInputImage::LabelObjectType > > +class ITK_EXPORT LabelMapToAttributeImageFilter : + public ImageToImageFilter<TInputImage, TOutputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelMapToAttributeImageFilter Self; + typedef ImageToImageFilter<TInputImage, TOutputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + typedef typename OutputImageType::IndexType IndexType; + + typedef TAttributeAccessor AttributeAccessorType; + typedef typename AttributeAccessorType::AttributeValueType AttributeValueType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelMapToAttributeImageFilter, + ImageToImageFilter); + + /** + * Set/Get the value used as "background" in the output image, if the input + * LabelMap use a background. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + +protected: + LabelMapToAttributeImageFilter(); + ~LabelMapToAttributeImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** LabelMapToAttributeImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** LabelMapToAttributeImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + LabelMapToAttributeImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + OutputImagePixelType m_BackgroundValue; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelMapToAttributeImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelMapToAttributeImageFilter.txx b/Utilities/InsightJournal/itkLabelMapToAttributeImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..5f26a24b9f7416184f1f5d57a7c5e0edb0365aef --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapToAttributeImageFilter.txx @@ -0,0 +1,111 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapToAttributeImageFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapToAttributeImageFilter_txx +#define __itkLabelMapToAttributeImageFilter_txx + +#include "itkLabelMapToAttributeImageFilter.h" +#include "itkNumericTraits.h" +#include "itkProgressReporter.h" +#include "itkImageRegionConstIteratorWithIndex.h" + +namespace itk { + +template <class TInputImage, class TOutputImage, class TAttributeAccessor> +LabelMapToAttributeImageFilter<TInputImage, TOutputImage, TAttributeAccessor> +::LabelMapToAttributeImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); +} + +template <class TInputImage, class TOutputImage, class TAttributeAccessor> +void +LabelMapToAttributeImageFilter<TInputImage, TOutputImage, TAttributeAccessor> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetInput()); + if ( !input ) + { return; } + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); +} + + +template <class TInputImage, class TOutputImage, class TAttributeAccessor> +void +LabelMapToAttributeImageFilter<TInputImage, TOutputImage, TAttributeAccessor> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage, class TOutputImage, class TAttributeAccessor> +void +LabelMapToAttributeImageFilter<TInputImage, TOutputImage, TAttributeAccessor> +::GenerateData() +{ + // Allocate the output + this->AllocateOutputs(); + OutputImageType * output = this->GetOutput(); + const InputImageType * input = this->GetInput(); + ProgressReporter progress( this, 0, output->GetRequestedRegion().GetNumberOfPixels() ); + + AttributeAccessorType accessor; + + output->FillBuffer( m_BackgroundValue ); + + typename InputImageType::LabelObjectContainerType::const_iterator it; + const typename InputImageType::LabelObjectContainerType & labelObjectContainer = input->GetLabelObjectContainer(); + for( it = labelObjectContainer.begin(); it != labelObjectContainer.end(); it++ ) + { + const typename InputImageType::LabelObjectType * labeObject = it->second; + const AttributeValueType & attribute = accessor( labeObject ); + + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + const typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labeObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + output->SetPixel( idx, static_cast<OutputImagePixelType>( attribute ) ); + idx[0]++; + progress.CompletedPixel(); + } + } + } +} + + +template<class TInputImage, class TOutputImage, class TAttributeAccessor> +void +LabelMapToAttributeImageFilter<TInputImage, TOutputImage, TAttributeAccessor> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelMapToRGBImageFilter.h b/Utilities/InsightJournal/itkLabelMapToRGBImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..da3d6b3a58ff2aaf2b4630d4fffa197e30396495 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapToRGBImageFilter.h @@ -0,0 +1,100 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapToRGBImageFilter.h,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.4 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapToRGBImageFilter_h +#define __itkLabelMapToRGBImageFilter_h + +#include "itkLabelMapFilter.h" +#include "itkLabelToRGBFunctor.h" +#include "itkImage.h" +#include "itkRGBPixel.h" + + +namespace itk { + +/** \class LabelMapToRGBImageFilter + * \brief Convert a LabelMap to a colored image + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa LabelMapToBinaryImageFilter, LabelMapMaskImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage, class TOutputImage=Image< RGBPixel<unsigned char>, TInputImage::ImageDimension > > +class ITK_EXPORT LabelMapToRGBImageFilter : + public LabelMapFilter<TInputImage, TOutputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelMapToRGBImageFilter Self; + typedef LabelMapFilter<TInputImage, TOutputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TOutputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename InputImageType::LabelObjectType LabelObjectType; + + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + typedef typename OutputImageType::IndexType IndexType; + + typedef typename Functor::LabelToRGBFunctor< InputImagePixelType, OutputImagePixelType > FunctorType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TOutputImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelMapToRGBImageFilter, + ImageToImageFilter); + +protected: + LabelMapToRGBImageFilter(); + ~LabelMapToRGBImageFilter() {}; + + virtual void BeforeThreadedGenerateData(); + + virtual void ThreadedGenerateData( LabelObjectType * labelObject ); + +private: + LabelMapToRGBImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelMapToRGBImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelMapToRGBImageFilter.txx b/Utilities/InsightJournal/itkLabelMapToRGBImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..c41ba09bbe159bae8576a94cf43a092c8b89aef7 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelMapToRGBImageFilter.txx @@ -0,0 +1,77 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelMapToRGBImageFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelMapToRGBImageFilter_txx +#define __itkLabelMapToRGBImageFilter_txx + +#include "itkLabelMapToRGBImageFilter.h" +#include "itkNumericTraits.h" +#include "itkProgressReporter.h" +#include "itkImageRegionConstIteratorWithIndex.h" + +namespace itk { + +template <class TInputImage, class TOutputImage> +LabelMapToRGBImageFilter<TInputImage, TOutputImage> +::LabelMapToRGBImageFilter() +{ +} + + +template<class TInputImage, class TOutputImage> +void +LabelMapToRGBImageFilter<TInputImage, TOutputImage> +::BeforeThreadedGenerateData() +{ + OutputImageType * output = this->GetOutput(); + const InputImageType * input = this->GetInput(); + + FunctorType function; + function.SetBackgroundValue( input->GetBackgroundValue() ); + output->FillBuffer( function( input->GetBackgroundValue() ) ); + + Superclass::BeforeThreadedGenerateData(); + +} + + +template<class TInputImage, class TOutputImage> +void +LabelMapToRGBImageFilter<TInputImage, TOutputImage> +::ThreadedGenerateData( LabelObjectType * labelObject ) +{ + const typename LabelObjectType::LabelType & label = labelObject->GetLabel(); + + FunctorType function; + function.SetBackgroundValue( this->GetInput()->GetBackgroundValue() ); + + typename InputImageType::LabelObjectType::LineContainerType::const_iterator lit; + typename InputImageType::LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + IndexType idx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + for( unsigned int i=0; i<length; i++) + { + this->GetOutput()->SetPixel( idx, function( label ) ); + idx[0]++; + } + } +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelObjectUtils.h b/Utilities/InsightJournal/itkLabelObjectUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..6be33ba3a1666bf1ed07e0e42afe70ac5d528982 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelObjectUtils.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelObject.h,v $ + Language: C++ + Date: $Date: 2005/01/21 20:13:31 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelObjectUtils_h +#define __itkLabelObjectUtils_h + +#include <deque> +#include <itkLightObject.h> +#include "itkLabelMap.h" +#include "itkLabelObjectLine.h" + +namespace itk +{ + + +namespace Functor { + +template< class TLabelObject > +class ITK_EXPORT LabelLabelObjectAccessor +{ +public: + typedef TLabelObject LabelObjectType; + typedef typename LabelObjectType::LabelType AttributeValueType; + + inline const AttributeValueType operator()( const LabelObjectType * labelObject ) + { + return labelObject->GetLabel(); + } +}; + +template< class TLabelObject > +class ITK_EXPORT NumberOfLinesLabelObjectAccessor +{ +public: + typedef TLabelObject LabelObjectType; + typedef int AttributeValueType; + + inline const AttributeValueType operator()( const LabelObjectType * labelObject ) + { + return labelObject->GetNumberOfLines(); + } +}; + +template< class TLabelObject, class TAttributeAccessor > +class LabelObjectComparator +{ +public: + typedef TLabelObject LabelObjectType; + typedef TAttributeAccessor AttributeAccessorType; + bool operator()( const LabelObjectType * a, const LabelObjectType * b ) + { + return accessor( a ) > accessor( b ); + } +private: + AttributeAccessorType accessor; +}; + +template< class TLabelObject, class TAttributeAccessor > +class LabelObjectReverseComparator +{ +public: + typedef TLabelObject LabelObjectType; + typedef TAttributeAccessor AttributeAccessorType; + bool operator()( const LabelObjectType * a, const LabelObjectType * b ) + { + return accessor( a ) < accessor( b ); + } +private: + AttributeAccessorType accessor; +}; + +} + +} // end namespace itk + +#endif diff --git a/Utilities/InsightJournal/itkLabelReconstructionByDilationImageFilter.h b/Utilities/InsightJournal/itkLabelReconstructionByDilationImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..d62dc10d0056ebb15a0f1f3853765b18bc4dbc61 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelReconstructionByDilationImageFilter.h @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelReconstructionByDilationImageFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelReconstructionByDilationImageFilter_h +#define __itkLabelReconstructionByDilationImageFilter_h + +#include "itkImageToImageFilter.h" +#include "itkAttributeLabelObject.h" +#include "itkLabelMap.h" +#include "itkLabelImageToLabelMapFilter.h" +#include "itkLabelReconstructionLabelMapFilter.h" +#include "itkAttributeOpeningLabelMapFilter.h" +#include "itkLabelMapToLabelImageFilter.h" + + +namespace itk { + +/** \class LabelReconstructionByDilationImageFilter + * \brief Identify local maxima whose height above the baseline is greater than h. + * +* \brief label reconstruction by dilation of an image + * + * Reconstruction by dilation operates on a "marker" image and a "mask" + * image, and is defined as the dilation of the marker image with + * respect to the mask image iterated until stability. + * + * Geodesic morphology is described in Chapter 6.2 of Pierre Soille's + * book "Morphological Image Analysis: Principles and Applications", + * Second Edition, Springer, 2003. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa MorphologyImageFilter, ReconstructionByDilationImageFilter, LabelReconstructionByErosionImageFilter + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TInputImage> +class ITK_EXPORT LabelReconstructionByDilationImageFilter : + public ImageToImageFilter<TInputImage, TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelReconstructionByDilationImageFilter Self; + typedef ImageToImageFilter<TInputImage, TInputImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TInputImage InputImageType; + typedef TInputImage OutputImageType; + typedef typename InputImageType::Pointer InputImagePointer; + typedef typename InputImageType::ConstPointer InputImageConstPointer; + typedef typename InputImageType::RegionType InputImageRegionType; + typedef typename InputImageType::PixelType InputImagePixelType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::ConstPointer OutputImageConstPointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** ImageDimension constants */ + itkStaticConstMacro(InputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(OutputImageDimension, unsigned int, + TInputImage::ImageDimension); + itkStaticConstMacro(ImageDimension, unsigned int, + TInputImage::ImageDimension); + + typedef AttributeLabelObject<unsigned long, ImageDimension, bool> LabelObjectType; + typedef typename itk::LabelMap< LabelObjectType > LabelMapType; + typedef typename itk::LabelImageToLabelMapFilter< InputImageType, LabelMapType > LabelizerType; + typedef typename itk::LabelReconstructionLabelMapFilter< LabelMapType, InputImageType > ReconstructionType; + typedef typename itk::AttributeOpeningLabelMapFilter< LabelMapType > OpeningType; + typedef typename itk::LabelMapToLabelImageFilter< LabelMapType, OutputImageType > BinarizerType; + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelReconstructionByDilationImageFilter, + ImageToImageFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>)); + /** End concept checking */ +#endif + + /** + * Set/Get the value used as "background" in the output image. + * Defaults to NumericTraits<PixelType>::NonpositiveMin(). + */ + itkSetMacro(BackgroundValue, OutputImagePixelType); + itkGetConstMacro(BackgroundValue, OutputImagePixelType); + + /** Set the marker image */ + void SetMarkerImage(InputImageType *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 0, const_cast<InputImageType *>(input) ); + } + + /** Get the marker image */ + InputImageType * GetMarkerImage() + { + return static_cast<InputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(0))); + } + + /** Set the mask image */ + void SetMaskImage( const InputImageType *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<InputImageType *>(input) ); + } + + /** Get the mask image */ + InputImageType * GetMaskImage() + { + return static_cast<InputImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + +protected: + LabelReconstructionByDilationImageFilter(); + ~LabelReconstructionByDilationImageFilter() {}; + void PrintSelf(std::ostream& os, Indent indent) const; + + /** LabelReconstructionByDilationImageFilter needs the entire input be + * available. Thus, it needs to provide an implementation of + * GenerateInputRequestedRegion(). */ + void GenerateInputRequestedRegion() ; + + /** LabelReconstructionByDilationImageFilter will produce the entire output. */ + void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)); + + /** Single-threaded version of GenerateData. This filter delegates + * to GrayscaleGeodesicErodeImageFilter. */ + void GenerateData(); + + +private: + LabelReconstructionByDilationImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + OutputImagePixelType m_BackgroundValue; + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelReconstructionByDilationImageFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelReconstructionByDilationImageFilter.txx b/Utilities/InsightJournal/itkLabelReconstructionByDilationImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..ef731666e8a16724bcc0a16a51abb2cf39f193bd --- /dev/null +++ b/Utilities/InsightJournal/itkLabelReconstructionByDilationImageFilter.txx @@ -0,0 +1,119 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelReconstructionByDilationImageFilter.txx,v $ + Language: C++ + Date: $Date: 2006/08/01 19:16:18 $ + Version: $Revision: 1.7 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelReconstructionByDilationImageFilter_txx +#define __itkLabelReconstructionByDilationImageFilter_txx + +#include "itkLabelReconstructionByDilationImageFilter.h" +#include "itkProgressAccumulator.h" + + +namespace itk { + +template<class TInputImage> +LabelReconstructionByDilationImageFilter<TInputImage> +::LabelReconstructionByDilationImageFilter() +{ + m_BackgroundValue = NumericTraits<OutputImagePixelType>::NonpositiveMin(); + this->SetNumberOfRequiredInputs(2); +} + +template<class TInputImage> +void +LabelReconstructionByDilationImageFilter<TInputImage> +::GenerateInputRequestedRegion() +{ + // call the superclass' implementation of this method + Superclass::GenerateInputRequestedRegion(); + + // We need all the input. + InputImagePointer input = const_cast<InputImageType *>(this->GetMarkerImage()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } + + input = const_cast<InputImageType *>(this->GetMaskImage()); + if( input ) + { + input->SetRequestedRegion( input->GetLargestPossibleRegion() ); + } +} + + +template<class TInputImage> +void +LabelReconstructionByDilationImageFilter<TInputImage> +::EnlargeOutputRequestedRegion(DataObject *) +{ + this->GetOutput() + ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() ); +} + + +template<class TInputImage> +void +LabelReconstructionByDilationImageFilter<TInputImage> +::GenerateData() +{ + // Create a process accumulator for tracking the progress of this minipipeline + ProgressAccumulator::Pointer progress = ProgressAccumulator::New(); + progress->SetMiniPipelineFilter(this); + + // Allocate the output + this->AllocateOutputs(); + + typename LabelizerType::Pointer labelizer = LabelizerType::New(); + labelizer->SetInput( this->GetMaskImage() ); + labelizer->SetBackgroundValue( m_BackgroundValue ); + labelizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(labelizer, .25f); + + typename ReconstructionType::Pointer reconstruction = ReconstructionType::New(); + reconstruction->SetInput( labelizer->GetOutput() ); + reconstruction->SetMarkerImage( this->GetMarkerImage() ); + reconstruction->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(reconstruction, .25f); + + typename OpeningType::Pointer opening = OpeningType::New(); + opening->SetInput( reconstruction->GetOutput() ); + opening->SetLambda( true ); + opening->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(opening, .25f); + + typename BinarizerType::Pointer binarizer = BinarizerType::New(); + binarizer->SetInput( opening->GetOutput() ); + binarizer->SetNumberOfThreads( this->GetNumberOfThreads() ); + progress->RegisterInternalFilter(binarizer, .5f); + + binarizer->GraftOutput( this->GetOutput() ); + binarizer->Update(); + this->GraftOutput( binarizer->GetOutput() ); +} + + +template<class TInputImage> +void +LabelReconstructionByDilationImageFilter<TInputImage> +::PrintSelf(std::ostream &os, Indent indent) const +{ + Superclass::PrintSelf(os, indent); + + os << indent << "BackgroundValue: " << static_cast<typename NumericTraits<OutputImagePixelType>::PrintType>(m_BackgroundValue) << std::endl; +} + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelReconstructionLabelMapFilter.h b/Utilities/InsightJournal/itkLabelReconstructionLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..1417de17406ca271779d9087da3593f3d6f52ab6 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelReconstructionLabelMapFilter.h @@ -0,0 +1,124 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelReconstructionLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelReconstructionLabelMapFilter_h +#define __itkLabelReconstructionLabelMapFilter_h + +#include "itkInPlaceLabelMapFilter.h" +#include "itkAttributeLabelObject.h" + +namespace itk { +/** \class LabelReconstructionLabelMapFilter + * \brief + * + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage, class TMarkerImage, class TAttributeAccessor= + typename Functor::AttributeLabelObjectAccessor< typename TImage::LabelObjectType > > +class ITK_EXPORT LabelReconstructionLabelMapFilter : + public InPlaceLabelMapFilter<TImage> +{ +public: + /** Standard class typedefs. */ + typedef LabelReconstructionLabelMapFilter Self; + typedef InPlaceLabelMapFilter<TImage> + Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + typedef typename ImageType::LabelObjectType LabelObjectType; + + typedef TMarkerImage MarkerImageType; + typedef typename MarkerImageType::Pointer MarkerImagePointer; + typedef typename MarkerImageType::ConstPointer MarkerImageConstPointer; + typedef typename MarkerImageType::PixelType MarkerImagePixelType; + + typedef TAttributeAccessor AttributeAccessorType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelReconstructionLabelMapFilter, + InPlaceLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<PixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, PixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<PixelType>));*/ + /** End concept checking */ +#endif + + /** Set the marker image */ + void SetMarkerImage(TMarkerImage *input) + { + // Process object is not const-correct so the const casting is required. + this->SetNthInput( 1, const_cast<TMarkerImage *>(input) ); + } + + /** Get the marker image */ + MarkerImageType * GetMarkerImage() + { + return static_cast<MarkerImageType*>(const_cast<DataObject *>(this->ProcessObject::GetInput(1))); + } + + /** Set the input image */ + void SetInput1(TImage *input) + { + this->SetInput( input ); + } + + /** Set the marker image */ + void SetInput2(TMarkerImage *input) + { + this->SetMarkerImage( input ); + } + +protected: + LabelReconstructionLabelMapFilter(); + ~LabelReconstructionLabelMapFilter() {}; + + virtual void ThreadedGenerateData( LabelObjectType * labelObject ); + +private: + LabelReconstructionLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + +} ; // end of class + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkLabelReconstructionLabelMapFilter.txx" +#endif + +#endif + + diff --git a/Utilities/InsightJournal/itkLabelReconstructionLabelMapFilter.txx b/Utilities/InsightJournal/itkLabelReconstructionLabelMapFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..ca1945a155a3c437c8b4b7c611843b2bdc1c8056 --- /dev/null +++ b/Utilities/InsightJournal/itkLabelReconstructionLabelMapFilter.txx @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelReconstructionLabelMapFilter.txx,v $ + Language: C++ + Date: $Date: 2005/08/23 15:09:03 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelReconstructionLabelMapFilter_txx +#define __itkLabelReconstructionLabelMapFilter_txx + +#include "itkLabelReconstructionLabelMapFilter.h" +#include "itkProgressReporter.h" + + +namespace itk { + +template <class TImage, class TMarkerImage, class TAttributeAccessor> +LabelReconstructionLabelMapFilter<TImage, TMarkerImage, TAttributeAccessor> +::LabelReconstructionLabelMapFilter() +{ + this->SetNumberOfRequiredInputs(2); +} + + +template <class TImage, class TMarkerImage, class TAttributeAccessor> +void +LabelReconstructionLabelMapFilter<TImage, TMarkerImage, TAttributeAccessor> +::ThreadedGenerateData( LabelObjectType * labelObject ) +{ + AttributeAccessorType accessor; + + const MarkerImageType * maskImage = this->GetMarkerImage(); + const PixelType & label = labelObject->GetLabel(); + + typename LabelObjectType::LineContainerType::const_iterator lit; + typename LabelObjectType::LineContainerType & lineContainer = labelObject->GetLineContainer(); + + // iterate over all the lines to find a pixel inside the object + for( lit = lineContainer.begin(); lit != lineContainer.end(); lit++ ) + { + const IndexType & firstIdx = lit->GetIndex(); + unsigned long length = lit->GetLength(); + + long endIdx0 = firstIdx[0] + length; + for( IndexType idx = firstIdx; idx[0]<endIdx0; idx[0]++ ) + { + const MarkerImagePixelType & v = maskImage->GetPixel( idx ); + if( v == label ) + { + // keep the object + accessor( labelObject, true ); + return; + } + } + } + + // remove the object + accessor( labelObject, false ); + +} + + +}// end namespace itk +#endif diff --git a/Utilities/InsightJournal/itkLabelSelectionLabelMapFilter.h b/Utilities/InsightJournal/itkLabelSelectionLabelMapFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..d476cc4bf20b477037d589a6bfdb988e51e9cf1b --- /dev/null +++ b/Utilities/InsightJournal/itkLabelSelectionLabelMapFilter.h @@ -0,0 +1,126 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkLabelSelectionLabelMapFilter.h,v $ + Language: C++ + Date: $Date: 2006/03/28 19:59:05 $ + Version: $Revision: 1.6 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkLabelSelectionLabelMapFilter_h +#define __itkLabelSelectionLabelMapFilter_h + +#include "itkAttributeSelectionLabelMapFilter.h" +#include "itkLabelObject.h" +#include <set> + + +namespace itk { +/** \class LabelSelectionLabelMapFilter + * \brief remove the objects according to the value of their attribute + * + * LabelSelectionLabelMapFilter removes the objects in a label collection image + * with an attribute value inside or outside a set of attribute values passed by + * the user. + * The attribute is provide by an attribute accessor given in template parameter. + * Contrary to the other filters made to remove some object of a LabelMap, no + * ordering relation for the attribute is needed in that filter. + * + * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA de Jouy-en-Josas, France. + * + * \sa AttributeLabelObject + * \ingroup ImageEnhancement MathematicalMorphologyImageFilters + */ +template<class TImage> +class ITK_EXPORT LabelSelectionLabelMapFilter : + public AttributeSelectionLabelMapFilter<TImage, typename Functor::LabelLabelObjectAccessor< typename TImage::LabelObjectType > > +{ +public: + /** Standard class typedefs. */ + typedef LabelSelectionLabelMapFilter Self; + typedef AttributeSelectionLabelMapFilter<TImage, typename Functor::LabelLabelObjectAccessor< typename TImage::LabelObjectType > > Superclass; + typedef SmartPointer<Self> Pointer; + typedef SmartPointer<const Self> ConstPointer; + + /** Some convenient typedefs. */ + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointer; + typedef typename ImageType::ConstPointer ImageConstPointer; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::IndexType IndexType; + + typedef typename Superclass::AttributeAccessorType AttributeAccessorType; + typedef typename Superclass::AttributeValueType AttributeValueType; + + typedef typename Superclass::AttributeSetType AttributeSetType; + + /** ImageDimension constants */ + itkStaticConstMacro(ImageDimension, unsigned int, + TImage::ImageDimension); + + /** Standard New method. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(LabelSelectionLabelMapFilter, + AttributeSelectionLabelMapFilter); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ +/* itkConceptMacro(InputEqualityComparableCheck, + (Concept::EqualityComparable<InputImagePixelType>)); + itkConceptMacro(IntConvertibleToInputCheck, + (Concept::Convertible<int, InputImagePixelType>)); + itkConceptMacro(InputOStreamWritableCheck, + (Concept::OStreamWritable<InputImagePixelType>));*/ + /** End concept checking */ +#endif + + const AttributeSetType & GetLabelSet() const + { + return this->GetAttributeSet(); + } + + void SetLabelSet( const AttributeSetType & set ) + { + this->SetAttributeSet( set ); + } + + /** Clear the attribute set, and add the attribute passed in parameter */ + void SetLabel( const AttributeValueType & attr ) + { + this->SetAttribute( attr ); + } + + void ClearLabelSet() + { + this->ClearAttributeSet(); + } + + void AddLabel( const AttributeValueType & attr ) + { + this->AddAttribute( attr ); + } + +protected: + LabelSelectionLabelMapFilter() {}; + ~LabelSelectionLabelMapFilter() {}; + +private: + LabelSelectionLabelMapFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + +} ; // end of class + +} // end namespace itk + +#endif + + diff --git a/Utilities/InsightJournal/itkScaleInvariantFeatureImageFilter.h b/Utilities/InsightJournal/itkScaleInvariantFeatureImageFilter.h new file mode 100644 index 0000000000000000000000000000000000000000..2453e9aef53593f60532b2a875764e7d9e32f5b4 --- /dev/null +++ b/Utilities/InsightJournal/itkScaleInvariantFeatureImageFilter.h @@ -0,0 +1,325 @@ +/*========================================================================= +Program: ITK nSIFT Implemention (Header) +Module: $RCSfile: itkScaleInvariantFeatureImageFilter.h,v $ +Language: C++ +Date: $Date: 2007/11/25 15:51:48 $ +Version: $Revision: 1.0 $ +Copyright (c) 2005,2006,2007 Warren Cheung +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +* The name of the Insight Consortium, nor the names of any consortium members, +nor of any contributors, may be used to endorse or promote products derived +from this software without specific prior written permission. +* Modified source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=========================================================================*/ + +//#define VERBOSE +//#define DEBUG +//#define DEBUG_VERBOSE + +//#define GENERATE_KEYS +//#define REORIENT + +//#define SIFT_FEATURE + +//Generate histograms +//compare gradient histograms +// + +// Min DoG value for keypoints +// Fix Gaussian Scale +// Only iterate through the region up to 3 sigma from the point + +//More advanced features for better matching? +//Simple quadrant system? + + +/* Based on example code from the ITK Toolkit + * TODO: Use resampler+identity transform+spacing change instead of scaling + * arbitrary downscale between pyramid levels + * may need to have a threshold + * Gaussian filtration may fail if input image format is integer + * Generate Pointset + * Get Orientation + * Generate Features + + * Test vs Noise (no need to for orientation) + * vs Stretch + * vs Scale + */ +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#ifndef SIFTKEY_H +#define SIFTKEY_H + +#include "itkImageRegistrationMethod.h" + +#include "itkLinearInterpolateImageFunction.h" +#include "itkNearestNeighborInterpolateImageFunction.h" +#include "itkImage.h" + +#include "itkImageFileReader.h" +#include "itkImageFileWriter.h" + +#include "itkAffineTransform.h" +#include "itkIdentityTransform.h" +#include "itkResampleImageFilter.h" + +#include "itkDiscreteGaussianImageFilter.h" +#include "itkSubtractImageFilter.h" +#include "itkGradientImageFilter.h" +#include "itkGradientMagnitudeImageFilter.h" +#include "itkMultiplyImageFilter.h" + +#include "itkGaussianImageSource.h" + +#include "itkConstNeighborhoodIterator.h" + +#include "itkPointSet.h" +#include "itkVector.h" + +#include <cstdio> + + +namespace itk +{ + +/** \class ScaleInvariantFeatureImageFilter + * \brief Generate and match scale invariant features from an image input. + * + * This class takes the input image and locates scale invariant features in + * the image. The result is a set of keypoints, each with an associated + * vector of values (the corresponding feature). Two sets of keypoints + * can then be matched, to determine which points in the sets are likely + * to correspond, by comparing feature vectors. + * + * Three different features can be compiled from this source using + * preprocessor \#define commands: + * + * - default (no special \#define) + * - Histogram Feature + * - \#define REORIENT + * - Histogram Feature with reoriented to the highest magnitude histogram bin + * - \#define SIFT_FEATURE + * - n-Dimensional adaptation of the SIFT feature. + */ + + template <class TFixedImageType, unsigned int VDimension=2> + class ITK_EXPORT ScaleInvariantFeatureImageFilter + { + public: + + /** typedefs to facilitate access to the image-related types */ + typedef typename TFixedImageType::PixelType PixelType; + typedef typename TFixedImageType::Pointer FixedImagePointer; + typedef typename TFixedImageType::IndexType IndexType; + + /** used for validating results from synthetic images */ + typedef typename itk::ScalableAffineTransform< double, VDimension > TransformType; + +#ifdef GENERATE_KEYS + /** multidimensional histogram for the features */ + typedef Array< float > FeatureType; + /** keypoints, storing the associated feature as well */ + typedef PointSet< FeatureType, VDimension, + DefaultStaticMeshTraits< FeatureType, VDimension, VDimension, double > > PointSetType; +#else + typedef PointSet< float, VDimension, + DefaultStaticMeshTraits< FeatureType, VDimension, VDimension, double > > PointSetType; +#endif + typedef typename PointSetType::PointType PointType; + typedef typename PointSetType::Pointer PointSetTypePointer; + + /** Filters for scaling and resampling images for the multiple scales */ + typedef ResampleImageFilter< TFixedImageType, TFixedImageType > ResampleFilterType; + typedef typename ResampleFilterType::Pointer ResampleFilterPointerType; + + /** Constructor to set default values */ + ScaleInvariantFeatureImageFilter(); + + /** Used for debugging. Writes an image to disk */ + void writeImage(FixedImagePointer fixedImage, const char *filename); + + /** Create a filter that resamples the image (scale up or down) */ + ResampleFilterPointerType getScaleResampleFilter ( FixedImagePointer fixedImage, float scale ); + + void SetDoubling (bool tmp); + void SetNumBins( unsigned int tmp); + void SetSigma( double tmp); + void SetNumScales ( unsigned int tmp); + void SetMatchRatio ( float tmp); + + /** Generate and return the scale invariant keypoints and features */ + PointSetTypePointer getSiftFeatures(FixedImagePointer fixedImage); + + /** Match keypoints purely based on position. Upper bounds + * the performance when matching using features. Supply + * the inverse transform to get performance measures. + * Mainly used with synthetic tests. + */ + void MatchKeypointsPos(PointSetTypePointer keypoints1, PointSetTypePointer keypoints2, + typename TransformType::Pointer inverse_transform); + +#ifdef GENERATE_KEYS + /** Match keypoints based on similarity of features. Matches are printed + * to standard out. Supply the inverse transform to get performance + * measures. + */ + void MatchKeypointsFeatures(PointSetTypePointer keypoints1, PointSetTypePointer keypoints2, + typename TransformType::Pointer inverse_transform); +#endif + + + private: + + /** Filter to obtain gradient directions and magnitudes */ + typedef itk::GradientImageFilter<TFixedImageType> GradientFilterType; + typedef typename GradientFilterType::OutputImageType GradientImageType; + typedef itk::GradientMagnitudeImageFilter<TFixedImageType, TFixedImageType> GradientMagFilterType; + + /** Shorthand for an identity transform */ + typedef IdentityTransform< double, VDimension > IdentityTransformType; + typename IdentityTransformType::Pointer m_IdentityTransform; + + /** Scale up the original image by a factor of 2 before processing */ + bool m_DoubleOriginalImage; + /** Number of image pyramid levels (scales) to test */ + unsigned int m_ImageScalesTestedNumber; + /** Factor by which the images are scaled between pyramid levels */ + float m_ScalingFactor; + + /** The range of Gaussian sigma that will be tested */ + float m_GaussianSigma; + /** Number of Gaussian Images that will be used to sample the range of + * sigma values ... + */ + unsigned int m_GaussianImagesNumber; + /** ... determining the number of difference of gaussian images ... */ + unsigned int m_DifferenceOfGaussianImagesNumber; + /** ... determining the number of sets of images we can test for + * feature points + */ + unsigned int m_DifferenceOfGaussianTestsNumber; + + /** Number of bins to cover 2pi radians + * Note that the multidimensional histogram has this many bins + * for each dimension when describing the angle in hyperspherical + * coordinates + */ + unsigned int m_HistogramBinsNumber; + /** Minimum voxel intensity for a feature point */ + float m_MinKeypointValue; + /** When looking for difference of Gaussian extrema in the images, + * consider a voxel to be extremal even if there are voxels + * that are this much more extreme. + */ + float m_ErrorThreshold; + + /** When matching points, reject a match if the ratio: + * \f[ + * \frac{\textrm{distance to best match}}{\textrm{distance to second-best match}} + * \f] + * is greater than this value + */ + float m_MaxFeatureDistanceRatio; + + PointSetTypePointer m_KeypointSet; + long m_PointsCount; + + /** Distance from the centre to the edge of the hypercube + * summarised by the nSIFT feature + */ + unsigned int m_SIFTHalfWidth; + /** The hypercube edge length (in voxels) of the subregion summarised + * by each multidimensional histogram of the nSIFT feature + */ + unsigned int m_SIFTSubfeatureWidth; + /** Number of bin used to summarise the hyperspherical coordinates + * of the voxels in each subregion + */ + unsigned int m_SIFTSubfeatureBins; + + /** The sigma for the Gaussian filtering for the j-th image on a level + * of the image pyramid + */ + double GetGaussianScale( int j ); + + /** The total size of the (reoriented) histogram feature */ + unsigned int HistFeatureSize(); + + /** Returns an image where all gradients are converted to hyperspherical + * coordinates + */ + typename GradientImageType::Pointer GetHypersphericalCoordinates(typename GradientImageType::Pointer inputImg); + + /** Convert a histogram bin number into an angle in hyperspherical + * coordinates + */ + typename GradientImageType::PixelType BinToVector (unsigned int maxbin); + + /** Size of the nSIFT feature */ + unsigned int SiftFeatureSize(); + + /** Used when generating nSIFT features to figure out what portion + * of the nSIFT feature vector the current summary histogram starts at + */ + unsigned int DeltaToSiftIndex (int delta[]); + +#ifdef GENERATE_KEYS + /** Generate nSIFT feature for pixel at pixelIndex */ + FeatureType GetSiftKey(typename GradientImageType::Pointer inputImg, + FixedImagePointer multImg, + IndexType pixelIndex); + + + /** Generate weighted histogram feature for voxel at pixelIndex + * Feature point is weighted due to the Gaussian. + */ + FeatureType GetHistogram(typename GradientImageType::Pointer inputImg, + FixedImagePointer multImg); +#endif + + + /** Determine whether voxel at pixelIndex with intensity + * pixelvalue is the local max/min + */ + void CheckLocalExtrema(FixedImagePointer image, IndexType pixelIndex, + PixelType pixelValue, + bool &isMax, bool &isMin, + bool checkCentre); + +#ifdef GENERATE_KEYS + /** Generate the (reoriented)histogram/nSIFT feature at a point + */ + FeatureType GetFeatures( FixedImagePointer fixedImage, + typename GradientImageType::Pointer hgradImage, + PointType &point, float currScale); +#endif + + }; +} + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkScaleInvariantFeatureImageFilter.txx" +#endif + +#endif /* SIFTKEY_H */ diff --git a/Utilities/InsightJournal/itkScaleInvariantFeatureImageFilter.txx b/Utilities/InsightJournal/itkScaleInvariantFeatureImageFilter.txx new file mode 100644 index 0000000000000000000000000000000000000000..0723f3a202f561a27778e8365c6db68768bdbc1a --- /dev/null +++ b/Utilities/InsightJournal/itkScaleInvariantFeatureImageFilter.txx @@ -0,0 +1,1335 @@ +/*========================================================================= +Program: ITK nSIFT Implemention (Template Source) +Module: $RCSfile: itkScaleInvariantFeatureImageFilter.txx,v $ +Language: C++ +Date: $Date: 2007/11/25 15:51:48 $ +Version: $Revision: 1.0 $ +Copyright (c) 2005,2006,2007 Warren Cheung +All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. +* The name of the Insight Consortium, nor the names of any consortium members, +nor of any contributors, may be used to endorse or promote products derived +from this software without specific prior written permission. +* Modified source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=========================================================================*/ + +//#define VERBOSE +//#define DEBUG +//#define DEBUG_VERBOSE + +//#define GENERATE_KEYS +//#define REORIENT + +//#define SIFT_FEATURE + +//TODO: Migrate the histogram reorientation code to the SIFT feature +// Make histogram feature special case of the sift feature with +// a single histogram. +//REORIENT NSIFT: Keep a "global histogram" in addition to the specific ones. +// Or maybe do the global histogram/reorient phase first? + +// Granularity of the Histogram causing cycles in reorientation accuracy? +// Or maybe we need to shift all the angles by half a bin width? + +//Generate histograms +//compare gradient histograms +// + +// Min DoG value for keypoints +// Fix Gaussian Scale +// Only iterate through the region up to 3 sigma from the point + +//More advanced features for better matching? +//Simple quadrant system? + + +/* Based on example code from the ITK Toolkit + * TODO: Use resampler+identity transform+spacing change instead of scaling + * arbitrary downscale between pyramid levels + * may need to have a threshold + * Gaussian filtration may fail if input image format is integer + * Generate Pointset + * Get Orientation + * Generate Features + + * Test vs Noise (no need to for orientation) + * vs Stretch + * vs Scale + */ +#if defined(_MSC_VER) +#pragma warning ( disable : 4786 ) +#endif + +#include "itkScaleInvariantFeatureImageFilter.h" +#include <cstdio> +#include "vnl/vnl_math.h" + +#ifndef SIFTKEY_CLASS +#define SIFTKEY_CLASS + + +const float PI=3.14159265; + +namespace itk +{ + + template <class TFixedImageType, unsigned int VDimension> + + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::ScaleInvariantFeatureImageFilter() + { +#ifdef DO_DOUBLE + m_ImageScalesTestedNumber = 4; +#else + m_ImageScalesTestedNumber = 3; +#endif + m_ScalingFactor = 2.0; + m_DifferenceOfGaussianTestsNumber = 3; +#ifdef DO_DOUBLE + m_DoubleOriginalImage = true; +#else + m_DoubleOriginalImage = false; +#endif + m_HistogramBinsNumber = 36; + m_ErrorThreshold = 0.0; + m_MaxFeatureDistanceRatio = 0.8; + m_GaussianSigma = 1.5; + m_MinKeypointValue = 0.0075; + m_SIFTHalfWidth = 8; // This MUST be a multiple of m_SIFTSubfeatureWidth + m_SIFTSubfeatureWidth = 4; + m_SIFTSubfeatureBins = 8; + + // Derived from above + m_DifferenceOfGaussianImagesNumber = m_DifferenceOfGaussianTestsNumber+2; + m_GaussianImagesNumber = m_DifferenceOfGaussianImagesNumber+1; + m_IdentityTransform = IdentityTransformType::New(); + } + + + template <class TFixedImageType, unsigned int VDimension> + double + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::GetGaussianScale( int j ) + { + return (vcl_pow(2, (double) j / (double) m_DifferenceOfGaussianTestsNumber) * m_GaussianSigma); + } + + template <class TFixedImageType, unsigned int VDimension> + unsigned int + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::HistFeatureSize() + { + unsigned int size = 1; + // Have m_HistogramBinsNumber for each of the (VDimension-1) Orientation dimensions + for (unsigned int i = 1; i < VDimension; ++i) + { + size *= m_HistogramBinsNumber; + } + return size; + } + + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::GradientImageType::Pointer + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::GetHypersphericalCoordinates(typename GradientImageType::Pointer inputImg) + { + typedef itk::ImageRegionIteratorWithIndex< GradientImageType > ImageIteratorType; + typedef itk::ImageRegionConstIteratorWithIndex< GradientImageType > ConstImageIteratorType; + typedef itk::ImageRegionConstIteratorWithIndex< TFixedImageType > ConstFixedImageIteratorType; + typename GradientImageType::Pointer outputImg = GradientImageType::New(); + // Copy attributes + outputImg->SetRegions(inputImg->GetLargestPossibleRegion()); + outputImg->CopyInformation( inputImg ); + outputImg->Allocate(); + + ConstImageIteratorType inputIt(inputImg, inputImg->GetLargestPossibleRegion()); + ImageIteratorType outputIt(outputImg, inputImg->GetLargestPossibleRegion()); + + for ( inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); + ++inputIt, ++outputIt) + { + typename GradientImageType::PixelType x = inputIt.Get(); + typename GradientImageType::PixelType p; + + // position 0 is the norm + p[0] = x.GetNorm(); + + // position 1 is arctan (x0 / x1) + p[1] = atan2( x[0],x[1] ); + + // Iterate over all the positions + // position k is arctan (x_k-1 / (x_k * cos p_k)) + for (unsigned int k = 2; k < x.Size(); ++k) + { + p[k] = atan2( x[k-1], x[k] * cos(p[k-1])); + } + outputIt.Set(p); + } + + return outputImg; + } + + // Generates a vector with positions 1 to VDimension-1 filled with + // histogram bin numbers from a single bin number + + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::GradientImageType::PixelType + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::BinToVector (unsigned int maxbin) + { + // convert maxpos to orientation bin vector + typename GradientImageType::PixelType maxp; + for (unsigned int i = 1; i < VDimension; ++i) { + maxp[i] = maxbin % m_HistogramBinsNumber; + maxbin /= m_HistogramBinsNumber; + } + return maxp; + } + + template <class TFixedImageType, unsigned int VDimension> + unsigned int + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::SiftFeatureSize() + { + unsigned int size = 1; + // Have m_HistogramBinsNumber for each of the (VDimension-1) Orientation dimensions + for (unsigned int i = 0; i < VDimension; ++i) + { + size *= (m_SIFTHalfWidth * 2 / m_SIFTSubfeatureWidth ); + if (i > 0) + size *= m_SIFTSubfeatureBins; + } + + return size; + } + + // Convert the delta iterator into index to the + // start of the SIFT histogram + template <class TFixedImageType, unsigned int VDimension> + unsigned int + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::DeltaToSiftIndex (int delta[]) + { + unsigned int bin = 0; + unsigned int binpos = 1; +#ifdef DEBUG_VERBOSE + std::cerr << "Converting delta: "; +#endif + for (unsigned int i = 0; i < VDimension; ++i) { +#ifdef DEBUG_VERBOSE + std::cerr << delta[i]; +#endif + unsigned int tmp = (delta[i] + m_SIFTHalfWidth) / m_SIFTSubfeatureWidth; + + bin += tmp * binpos; + binpos *= (m_SIFTHalfWidth * 2 / m_SIFTSubfeatureWidth ); + } + for (unsigned int i = 1; i < VDimension; ++i) + bin *= m_SIFTSubfeatureBins; + +#ifdef DEBUG_VERBOSE + std::cerr << "\n"; +#endif + return bin; + } + + +#ifdef GENERATE_KEYS + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::FeatureType + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::GetSiftKey(typename GradientImageType::Pointer inputImg, + FixedImagePointer multImg, + IndexType pixelIndex) + { +#ifdef DEBUG_VERBOSE + std::cerr << "GetSiftKey..." << std::endl; +#endif + FeatureType sifthistogram(this->SiftFeatureSize()); + sifthistogram.Fill(0); + + // delta iterates from -m_SIFTHalfWidth to m_SIFTHalfWidth-1 + // in each dimensions + int delta[VDimension]; + for (unsigned int k = 0; k < VDimension; ++k) { + delta[k] = -m_SIFTHalfWidth; + } + + typename GradientImageType::SizeType regionSize = + inputImg->GetLargestPossibleRegion().GetSize(); + + while(1) { + unsigned int siftbin = this->DeltaToSiftIndex(delta); + +#ifdef DEBUG_VERBOSE + std::cerr << "Siftbin:" << siftbin << std::endl; +#endif + + // Get pixel index + // Clamp to image edges + IndexType tmpIndex; + for (unsigned int k=0; k < VDimension; ++k) { + if ((pixelIndex[k] + delta[k]) < 0) { + tmpIndex[k] = 0; + } else { + tmpIndex[k] = pixelIndex[k] + delta[k]; + if (static_cast<unsigned int>(tmpIndex[k]) >= regionSize[k] ) + tmpIndex[k] = regionSize[k]-1; + } + } + +#ifdef DEBUG_VERBOSE + std::cerr << "Pixel:" << tmpIndex << std::endl; +#endif + typename GradientImageType::PixelType x = + inputImg->GetPixel(tmpIndex); + + // Get histogram bin + // Iterate over all the positions + unsigned int bin = 0; + unsigned int binpos = 1; + for (unsigned int k = 1; k < x.Size(); ++k) + { + // Rescale from -PI to PI -> 0 to m_HistogramBinsNumber-1 + float p; + p = (x[k] + PI) * (float) m_SIFTSubfeatureBins / (2.0 * PI); + + + if (p < 0 || p >= m_SIFTSubfeatureBins) + p = 0; + bin += (unsigned int) p * binpos; + +#ifdef DEBUG_VERBOSE + std::cout << " " << p; +#endif + binpos *= m_SIFTSubfeatureBins; + } + + bin += siftbin; + + // Fill Sift Index bin + if (bin > this->SiftFeatureSize()) { + // VERY BAD + std::cerr << bin << " > " << this->SiftFeatureSize() << " Warning -- Overload2\n"; + } + sifthistogram[bin] += x[0] * multImg->GetPixel(tmpIndex); + +#ifdef DEBUG_VERBOSE + std::cerr << "Incrementing\n"; +#endif + // Increment delta + bool resetdelta=false; + for(unsigned int k=0; k <= VDimension; ++k) { +#ifdef DEBUG_VERBOSE + std::cerr << delta[k]; +#endif + if (k == VDimension) { +#ifdef DEBUG_VERBOSE + std::cerr << "done\n"; +#endif + resetdelta = true; + break; // done + } + // Don't want to go past m_SIFTHalfWidth-1 + if (++delta[k] < (int) m_SIFTHalfWidth) { + break; + } + delta[k] = -m_SIFTHalfWidth; // reset and increment the next pos + } + if(resetdelta) break; + } + +#ifdef DEBUG_VERBOSE + std::cerr << "SIFT key: " << sifthistogram << "\n"; +#endif + return(sifthistogram); + } + + + // Takes a hyperspherical coordinate gradient and gaussian weights + // returns a histogram + // Each orientation divides the 2PI angles into m_HistogramBinsNumber + // The value in each bin is the weighted magnitude + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::FeatureType + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::GetHistogram(typename GradientImageType::Pointer inputImg, + FixedImagePointer multImg) + { + +#ifdef ERROR_CHECK + std::cerr << "GetHistogram ... "; +#endif + + FeatureType histogram(this->HistFeatureSize()); + + histogram.Fill(0); + + typedef itk::ImageRegionConstIteratorWithIndex< GradientImageType > ConstImageIteratorType; + typedef itk::ImageRegionConstIteratorWithIndex< TFixedImageType > ConstFixedImageIteratorType; + + ConstImageIteratorType inputIt(inputImg, inputImg->GetLargestPossibleRegion()); + ConstFixedImageIteratorType multIt( multImg, inputImg->GetLargestPossibleRegion()); + + for ( inputIt.GoToBegin(), multIt.GoToBegin(); !inputIt.IsAtEnd(); + ++inputIt, ++multIt) + { + typename GradientImageType::PixelType x = inputIt.Get(); + typename TFixedImageType::PixelType m = multIt.Get(); + unsigned int bin = 0; + unsigned int binpos = 1; + typename GradientImageType::PixelType p; + + // position 0 is the norm + p[0] = x[0]; + + if (vnl_math_isnan(p[0]) || (p[0] == 0.0)) + continue; + + // multiply by m + p[0] *= m; + +#ifdef DEBUG_VERBOSE + std::cout << "Bin: "; +#endif + // Iterate over all the positions + for (unsigned int k = 1; k < x.Size(); ++k) + { + // Rescale from -PI to PI -> 0 to m_HistogramBinsNumber-1 + p[k] = (x[k] + PI) * (float) m_HistogramBinsNumber / (2.0 * PI); + + + if (p[k] < 0 || p[k] >= m_HistogramBinsNumber) + p[k] = 0; + bin += (unsigned int) p[k] * binpos; + +#ifdef DEBUG_VERBOSE + std::cout << " " << p[k]; +#endif + binpos *= m_HistogramBinsNumber; + } +#ifdef DEBUG_VERBOSE + std::cout << " Value: " << p[0] << std::endl; +#endif + if (bin > this->HistFeatureSize()) { + // VERY BAD + std::cerr << x << " -> " << p << "\n"; + std::cerr << bin << " > " << this->HistFeatureSize() << " Warning -- Overload2\n"; + } + histogram[bin] += p[0]; + } +#ifdef DEBUG + // Print the Histogram + std::cout << histogram << std::endl; +#endif + + // Since we are going to use this as a feature + // Normalise + float hmag = 0.0; +#ifdef REORIENT + float maxmag = -1; + unsigned int maxbin; +#endif + for (unsigned int i = 0; i < this->HistFeatureSize(); ++i) { + float mag = histogram[i]*histogram[i]; + hmag += mag; +#ifdef REORIENT + if (maxmag < 0 || mag > maxmag) { + maxmag = mag; + maxbin = i; + } +#endif + } + hmag = sqrt(hmag); + +#ifdef REORIENT + typename GradientImageType::PixelType maxp = this->BinToVector(maxbin); + + FeatureType histogram2(this->HistFeatureSize()); + histogram2.Fill(0); +#endif + + for (unsigned int i = 0; i < this->HistFeatureSize(); ++i) { + histogram[i] /= hmag; + +#ifdef REORIENT + typename GradientImageType::PixelType bini = this->BinToVector(i); + + unsigned int bin = 0; + unsigned int binpos = 1; + for (unsigned int k = 1; k < VDimension; ++k) { + bini[k] = ((int) (bini[k] - maxp[k] + m_HistogramBinsNumber)) % m_HistogramBinsNumber; + if (bini[k] < 0 || bini[k] >= m_HistogramBinsNumber) + bini[k] = 0; + bin += (int) bini[k] * binpos; + binpos *= m_HistogramBinsNumber; + } + histogram2[bin] = histogram[i]; +#endif + } + + +#ifdef DEBUG + std::cout << histogram << std::endl; +#ifdef REORIENT + std::cout << "Max Bin: " << maxbin << " Max Mag: " << maxmag << std::endl; + std::cout << "Reoriented: " << histogram2 << std::endl; +#endif +#endif +#ifdef ERROR_CHECK + std::cerr << "OK\n "; +#endif + +#ifdef REORIENT + return histogram2; +#else + return histogram; +#endif + } +#endif + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::CheckLocalExtrema(FixedImagePointer image, IndexType pixelIndex, + PixelType pixelValue, + bool &isMax, bool &isMin, + bool checkCentre) + { +#ifdef ERROR_CHECK + std::cerr << "CheckLocalExtrema ... "; +#endif + int delta[VDimension]; + for (unsigned int k = 0; k < VDimension; ++k) { + delta[k] = -1; + } + while(1) { + bool isZero=true; + if (!checkCentre) { + for (unsigned int k=0; k < VDimension; ++k) { + if(delta[k] != 0) { + isZero = false; + break; + } + } + } + + if (checkCentre || !isZero) { + // Check if not the centre + IndexType tmpIndex; + for (unsigned int k=0; k < VDimension; ++k) { + tmpIndex[k] = pixelIndex[k] + delta[k]; + } + + typename TFixedImageType::PixelType tmpValue = + image->GetPixel(tmpIndex); + +#ifdef DEBUG_VERBOSE + std::cout << "...Comparing to ( "; + for (unsigned int k = 0; k < VDimension; ++k) + std::cout << tmpIndex[k] << " "; + std::cout << ") = " << tmpValue << "\n"; +#endif + // Treat as equality if within the error bound + if (((tmpValue - pixelValue) <= m_ErrorThreshold) && + ((tmpValue - pixelValue) >= -m_ErrorThreshold)) { + isMax = false; + isMin = false; + } else + if (tmpValue > pixelValue) { + isMax = false; + } else + if (tmpValue < pixelValue) { + isMin = false; + } + if (!isMax && !isMin) break; + } + // Increment delta + bool resetdelta=false; + for(unsigned int k=0; k <= VDimension; ++k) { + if (k == VDimension) { + resetdelta = true; + break; // done + } + if (delta[k] < 1) { + ++delta[k]; + break; + } + delta[k] = -1; // reset and increment the next pos + } + if(resetdelta) break; + } +#ifdef ERROR_CHECK + std::cerr << "OK\n"; +#endif + } + +#ifdef GENERATE_KEYS + // Input: Image, Gradient Image, Point + // Output: Vector of direction + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::FeatureType + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::GetFeatures( FixedImagePointer fixedImage, + typename GradientImageType::Pointer hgradImage, + PointType &point, float currScale) + { +#ifdef ERROR_CHECK + std::cerr << "GetFeatures ... "; +#endif + + // Generate the Gaussian + typedef GaussianImageSource<TFixedImageType> GaussianImageSourceType; + typename GaussianImageSourceType::Pointer gaussImgSource; + typename GaussianImageSourceType::ArrayType sigma; + + gaussImgSource = GaussianImageSourceType::New(); + gaussImgSource->SetNormalized(true); + //gaussImgSource->SetNormalized(false); + //gaussImgSource->SetScale(255); + gaussImgSource->SetSpacing(fixedImage->GetSpacing()); + gaussImgSource->SetSize(fixedImage->GetLargestPossibleRegion().GetSize()); + gaussImgSource->SetMean(point); + +#if 0 + // If we wanted to find the orientation, we would use this + for (unsigned int i = 0; i < VDimension; ++i) + sigma[i] = 3.0 * currScale; + gaussImgSource->SetSigma(sigma); +#endif + + // Simulate the 16x16 Gaussian window descriptor + // use sigma equal to half the descriptor window width + for (unsigned int i = 0; i < VDimension; ++i) + sigma[i] = 8.0; + gaussImgSource->SetSigma(sigma); + + gaussImgSource->Update(); + + IndexType pixelIndex; + fixedImage->TransformPhysicalPointToIndex(point, pixelIndex); + +#if 0 + // Only iterate through the region that is within 3 sigma of the mean + + IndexType regionStart; + for (unsigned int k=0; k < VDimension; ++k) + { + if ((pixelIndex[k] - 3*sigma[k]) > 0) + regionStart[k] = (int) floor(pixelIndex[k] - 3*sigma[k]); + else + regionStart[k] = 0; + } + + typename TFixedImageType::SizeType regionSize = + fixedImage->GetLargestPossibleRegion().GetSize(); + + // Avoid far edge + for (unsigned int k=0; k < VDimension; ++k) { + if ( ceil(regionStart[k] + 6*sigma[k]) < regionSize[k]) + regionSize[k] = (int) ceil(6*sigma[k]); + else + regionSize[k] -= regionStart[k]; + } + + typename TFixedImageType::RegionType itregion; + itregion.SetIndex(regionStart); + itregion.SetSize(regionSize); +#endif + + // return the Gaussian weighted Histogram +#ifdef SIFT_FEATURE + return this->GetSiftKey(hgradImage, gaussImgSource->GetOutput(), + pixelIndex); +#else + return this->GetHistogram(hgradImage, gaussImgSource->GetOutput()); +#endif + } + +#endif + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::writeImage(FixedImagePointer fixedImage, const char *filename) + { + + if (VDimension != 2) return; + + typedef itk::Image< unsigned char, VDimension > OutImageType; + typedef typename itk::ImageFileWriter< OutImageType > FixedWriterType; + typedef itk::ResampleImageFilter< TFixedImageType, OutImageType > + OutResampleFilterType; + + + typename OutResampleFilterType::Pointer resampler = + OutResampleFilterType::New(); + + resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() ); + resampler->SetOutputSpacing( fixedImage->GetSpacing() ); + resampler->SetTransform(m_IdentityTransform); + resampler->SetInput(fixedImage); + + typename FixedWriterType::Pointer fixedWriter = FixedWriterType::New(); + + fixedWriter->SetFileName(filename); + fixedWriter->SetInput( resampler->GetOutput() ); + + std::cout << "[Writing file << " << filename << "]"; + + try + { + fixedWriter->Update(); + } + catch( itk::ExceptionObject & excep ) + { + std::cerr << "Exception caught !" << std::endl; + std::cerr << excep << std::endl; + } + + } + + // create a filter that resamples the image (scale up or down) + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::ResampleFilterPointerType + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::getScaleResampleFilter ( FixedImagePointer fixedImage, float scale ) + { + ResampleFilterPointerType scaler = ResampleFilterType::New(); + + scaler->SetInput( fixedImage ); + + + // Change the size of the image + typename TFixedImageType::SizeType size = + fixedImage->GetLargestPossibleRegion().GetSize(); + for (unsigned int k = 0; k < VDimension; ++k) + size[k] = (unsigned int) floor(size[k] * scale); + scaler->SetSize( size ); + + // Change the spacing + typename TFixedImageType::SpacingType spacing = + fixedImage->GetSpacing(); + for (unsigned int k = 0; k < VDimension; ++k) + spacing[k] = (spacing[k] / scale); + scaler->SetOutputSpacing( spacing ); + + scaler->SetTransform( m_IdentityTransform ); + scaler->SetDefaultPixelValue( 100 ); + scaler->Update(); + + return scaler; + } + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::SetDoubling (bool tmp) + { + m_DoubleOriginalImage = tmp; + } + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::SetNumBins( unsigned int tmp) + { + m_HistogramBinsNumber = tmp; + } + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::SetSigma( double tmp) + { + m_GaussianSigma = tmp; + } + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::SetNumScales ( unsigned int tmp) + { + m_ImageScalesTestedNumber = tmp; + } + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::SetMatchRatio ( float tmp) + { + m_MaxFeatureDistanceRatio = tmp; + } + + + template <class TFixedImageType, unsigned int VDimension> + typename ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension>::PointSetTypePointer + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::getSiftFeatures(FixedImagePointer fixedImage) + { + unsigned int numMin = 0, numMax = 0, numReject = 0; + + m_KeypointSet = PointSetType::New(); + + m_PointsCount = 0; + + // Declare Gaussian + typedef itk::DiscreteGaussianImageFilter<TFixedImageType, TFixedImageType > + GaussianFilterType; + + std::vector<typename GaussianFilterType::Pointer> gaussianFilter(m_GaussianImagesNumber); + + std::vector<typename TFixedImageType::Pointer> + gaussianImage(m_GaussianImagesNumber); + + // Declare DoG + typedef itk::SubtractImageFilter<TFixedImageType, TFixedImageType, + TFixedImageType> DifferenceFilterType; + std::vector<typename DifferenceFilterType::Pointer> dogFilter(m_DifferenceOfGaussianImagesNumber); + std::vector<typename TFixedImageType::Pointer> dogImage(m_DifferenceOfGaussianImagesNumber); + + // Resampled image filters + std::vector<typename ResampleFilterType::Pointer> scaler(m_ImageScalesTestedNumber); + std::vector<typename TFixedImageType::Pointer> scaleImage(m_ImageScalesTestedNumber); + +#ifdef GENERATE_KEYS + // Declare Gradient + std::vector<typename GradientFilterType::Pointer> gradFilter(m_ImageScalesTestedNumber); + std::vector<typename GradientImageType::Pointer> gradImage(m_ImageScalesTestedNumber); + std::vector<typename GradientImageType::Pointer> hgradImage(m_ImageScalesTestedNumber); + + std::vector<typename GradientMagFilterType::Pointer> gradMagFilter(m_ImageScalesTestedNumber); + std::vector<FixedImagePointer> gradMagImage(m_ImageScalesTestedNumber); +#endif + + + float currScale = 0.5; + + // For each scale + for (unsigned int i = 0; i < m_ImageScalesTestedNumber; ++i) { + std::cout << "Computing Scale Level " << i << "... ("; + + if (i == 0 && !m_DoubleOriginalImage) { + scaleImage[0] = fixedImage; + } else { + if (i == 0) { + // Input is the fixed Image. + scaler[i] = getScaleResampleFilter ( fixedImage, m_ScalingFactor ); + } else { + // Input is the 2*sigma smoothed image from the previous octave + scaler[i] = getScaleResampleFilter ( gaussianImage[m_DifferenceOfGaussianTestsNumber] , 1.0 / m_ScalingFactor ); + } + scaleImage[i] = scaler[i]->GetOutput(); + } + + { + typename TFixedImageType::SizeType gsize = + scaleImage[i]->GetLargestPossibleRegion().GetSize(); + for (unsigned int j = 0; j < VDimension; ++j) + std::cout << gsize[j] << " "; + } + + std::cout << ") Done\n"; + +#ifdef DEBUG + char filename[256]; + sprintf(filename, "gauss-%d-0.png", i); + this->writeImage(scaleImage[i], filename); +#endif + +#ifdef GENERATE_KEYS + // ...Compute Gradient + std::cout << "...Computing Gradient..."; + gradFilter[i] = GradientFilterType::New(); + gradFilter[i]->SetInput(scaleImage[i]); + // Do this in pixel space + gradFilter[i]->SetUseImageSpacing(false); + gradFilter[i]->Update(); + gradImage[i] = gradFilter[i]->GetOutput(); + hgradImage[i] = this->GetHypersphericalCoordinates(gradImage[i]); + + gradMagFilter[i] = GradientMagFilterType::New(); + gradMagFilter[i]->SetInput(scaleImage[i]); + // Do this in pixel space + gradMagFilter[i]->SetUseImageSpacing(false); + gradMagFilter[i]->Update(); + gradMagImage[i] = gradMagFilter[i]->GetOutput(); + std::cout << "...Done\n"; +#endif + + // ...Compute Gaussians + for (unsigned int j = 0; j < m_GaussianImagesNumber; ++j) { +#ifdef VERBOSE + std::cout << "Setting Up Gaussian Filter " << i << "-" << j << "..."; + std::cout.flush(); +#endif + gaussianFilter[j] = GaussianFilterType::New(); + + /* Variance is square of the sigma + * sigma = (2^(j/s)*sigma) + */ + + double variance = this->GetGaussianScale(j); + variance *= variance; + gaussianFilter[j]->SetVariance(variance); + gaussianFilter[j]->SetInput( scaleImage[i] ); + // pixel-wise smoothing + gaussianFilter[j]->SetUseImageSpacing(false); + try { + gaussianFilter[j]->Update(); + } + catch( itk::ExceptionObject & excep ) { + std::cerr << "Exception caught !" << std::endl; + std::cerr << excep << std::endl; + } + + gaussianImage[j] = gaussianFilter[j]->GetOutput(); + +#ifdef DEBUG + char filename[256]; + sprintf(filename, "gauss-%d-%d.png", i, j); + this->writeImage(gaussianImage[j], filename); +#endif + +#ifdef VERBOSE + std::cout << "Done\n"; + std::cout.flush(); +#endif + } + + // ...Compute Difference of Gaussians + for (unsigned int j = 0; j < (m_DifferenceOfGaussianImagesNumber); ++j) { +#ifdef VERBOSE + std::cout << "Setting Up DoG Filter " << i << "-" << j << "..."; + std::cout.flush(); +#endif + dogFilter[j] = DifferenceFilterType::New(); + dogFilter[j]->SetInput1( gaussianImage[j] ); + dogFilter[j]->SetInput2( gaussianImage[j+1] ); + dogFilter[j]->Update(); + dogImage[j] = dogFilter[j]->GetOutput(); + +#ifdef DEBUG + char filename[256]; + sprintf(filename, "dog-%d-%d.png", i, j); + this->writeImage(dogImage[j], filename); +#endif + +#ifdef VERBOSE + std::cout << "Done\n"; + std::cout.flush(); +#endif + } + + for (unsigned int j=1; j < (m_DifferenceOfGaussianImagesNumber - 1); ++j) { + // Search the dogImages for local maxima, w.r.t. corresponding + // point in the scale above and below + // level 0 is the "doubled" image + // Iterate over the various doG filters + // Only use the middle dogs (ones with both neighbours above and below) + // Iterate over each position in the dog filter + typedef itk::ImageRegionIteratorWithIndex< TFixedImageType > + ImageIteratorType; + + IndexType regionStart; + // Avoid the edges + for (unsigned int k=0; k < VDimension; ++k) + regionStart[k] = 1; + + typename TFixedImageType::SizeType regionSize = + dogImage[j]->GetLargestPossibleRegion().GetSize(); + +#ifdef VERBOSE + std::cout << "Searching for Extrema in DoG Image " << i << "-" << j; + std::cout << " ( "; + for (unsigned int k=0; k < VDimension; ++k) + std::cout << regionSize[k] << " "; + std::cout << ") Scale " << currScale << "\n"; + std::cout.flush(); +#endif + + // Avoid far edge + for (unsigned int k=0; k < VDimension; ++k) + regionSize[k] -= 2; + + typename TFixedImageType::RegionType itregion; + itregion.SetIndex(regionStart); + itregion.SetSize(regionSize); + + ImageIteratorType pixelIt(dogImage[j], + itregion); + + for ( pixelIt.GoToBegin(); !pixelIt.IsAtEnd(); ++pixelIt) { + // Make sure to start sufficiently into the image so that all + // neighbours are present + IndexType pixelIndex = pixelIt.GetIndex(); + typename TFixedImageType::PixelType pixelValue = pixelIt.Get(); + + PointType point; + dogImage[j]->TransformIndexToPhysicalPoint (pixelIndex, point); + +#ifdef ERROR_CHECK + std::cerr << "Checking ( "; + for (unsigned int k = 0; k < VDimension; ++k) + std::cerr << pixelIndex[k] << " "; + std::cerr << ") = " << pixelValue <<"\n"; +#endif + + // Compare to the 8 immediate neighbours + bool isMax=true; + bool isMin=true; + + this->CheckLocalExtrema(dogImage[j], + pixelIndex, pixelValue, isMax, isMin, false); + + if (!isMax && !isMin) continue; + + // Compare to scale above + if (j < (m_GaussianImagesNumber-1)) { +#ifdef DEBUG_VERBOSE + std::cout << "...Checking Scale Above\n"; +#endif + //dogImage[i+1][j]->TransformPhysicalPointToIndex (point, tmpIndex); + + this->CheckLocalExtrema(dogImage[j+1], + pixelIndex, pixelValue, isMax, isMin, true); + } + if (!isMax && !isMin) continue; + + // Compare to scale below + if (j > 0) { +#ifdef DEBUG_VERBOSE + std::cout << "...Checking Scale Below\n"; +#endif + //dogImage[i-1][j]->TransformPhysicalPointToIndex (point, tmpIndex); + + this->CheckLocalExtrema(dogImage[j-1], + pixelIndex, pixelValue, isMax, isMin, true); + } + if (!isMax && !isMin) continue; + + // Check if it is sufficiently large (absolute value) + if (fabs(pixelValue) < m_MinKeypointValue) { + ++numReject; + continue; + } + + + // Passed all checks: + +#ifdef DEBUG + std::cout << point << std::endl; +#endif + m_KeypointSet->SetPoint( m_PointsCount, point); +#ifdef GENERATE_KEYS + // Generate features + // Space used is the (smoothed) original image) + m_KeypointSet->SetPointData( m_PointsCount, + this->GetFeatures( gaussianImage[0], + hgradImage[i], point, + this->GetGaussianScale(j))); +#else + m_KeypointSet->SetPointData( m_PointsCount, currScale); +#endif + ++m_PointsCount; + + if (isMax) { + // Maxima detected. + ++numMax; +#ifdef DEBUG + std::cout << "Found Maxima! "; +#endif + } + if (isMin) { + // Minima detected. + ++numMin; +#ifdef DEBUG + std::cout << "Found Minima! "; +#endif + } + } +#ifdef VERBOSE + std::cout << "Acc. Num Max: " << numMax + << "\nAcc. Num Min: " << numMin + << "\nAcc. Num Reject: " << numReject + << std::endl; + std::cout.flush(); +#endif + } + currScale *= m_ScalingFactor; + } + +#ifdef VERBOSE + std::cout << "Total Num Max: " << numMax + << "\nTotal Num Min: " << numMin + << "\nTotal Num Reject: " << numReject + << std::endl; + std::cout.flush(); +#endif + return m_KeypointSet; + } + + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::MatchKeypointsPos(PointSetTypePointer keypoints1, PointSetTypePointer keypoints2, + typename TransformType::Pointer inverse_transform) + { + // Compare Keypoints. Check Coverage and Accuracy + // This does the comparison based on position of the keypoints + // Find: + // # of points that match which will tell us + // # of points that did not scale + // # of points created by the scale + unsigned int numMatches; + unsigned int numMatches2; + unsigned int numMatches5; + const double MATCH_THRESHOLD = 1.5; + typename PointSetType::PointsContainer::Pointer keyps1, keyps2; + + unsigned long numpoints1, numpoints2; + numpoints1 = keypoints1->GetNumberOfPoints(); + std::cout << "Keypoints1 Found: " << numpoints1 << std::endl; + numpoints2 = keypoints2->GetNumberOfPoints(); + std::cout << "Keypoints2 Found: " << numpoints2 << std::endl; + + if (!inverse_transform) + return; + + numMatches = 0; + numMatches2 = 0; + numMatches5 = 0; + for (unsigned int i = 0; i < numpoints2; ++i) { + PointType pp2; + keypoints2->GetPoint(i, &pp2); + + bool match = false; + bool match2 = false; + bool match5 = false; + for (unsigned int j = 0; j < numpoints1; ++j) { + PointType tmpp, pp; + keypoints1->GetPoint(j, &tmpp); + pp = inverse_transform->TransformPoint(tmpp); + // for (int k = 0; k < VDimension; ++k) + // pp[k] *= scale_test; + if(!match && pp.EuclideanDistanceTo(pp2) <= MATCH_THRESHOLD) + { + ++numMatches; + match = true; + } + if(!match2 && pp.EuclideanDistanceTo(pp2) <= 2*MATCH_THRESHOLD) + { + ++numMatches2; + match2 = true; + } + if(!match5 && pp.EuclideanDistanceTo(pp2) <= 5*MATCH_THRESHOLD) + { + ++numMatches5; + match5 = true; + } + if (match && match2 && match5) + break; + } + } + + std::cout << "Keypoints 2 Matching to Keypoints 1 (<" << MATCH_THRESHOLD << "): " << numMatches << std::endl; + std::cout << "% of Keypoints 2 Matching (<" << MATCH_THRESHOLD << "): " << (float) numMatches / numpoints2 << std::endl; + std::cout << "Keypoints 2 Matching to Keypoints 1 (<" << 2*MATCH_THRESHOLD << "): " << numMatches2 << std::endl; + std::cout << "% of Keypoints 2 Matching (<" << 2*MATCH_THRESHOLD << "): " << (float) numMatches2 / numpoints2 << std::endl; + std::cout << "Keypoints 2 Matching to Keypoints 1 (<" << 5*MATCH_THRESHOLD << "): " << numMatches5 << std::endl; + std::cout << "% of Keypoints 2 Matching (<" << 5*MATCH_THRESHOLD << "): " << (float) numMatches5 / numpoints2 << std::endl; + + + numMatches = 0; + numMatches2 = 0; + numMatches5 = 0; + for (unsigned int j = 0; j < numpoints1; ++j) { + PointType tmpp, pp; + keypoints1->GetPoint(j, &tmpp); + pp = inverse_transform->TransformPoint(tmpp); + // for (int k = 0; k < VDimension; ++k) + // pp[k] *= scale_test; + + bool match = false; + bool match2 = false; + bool match5 = false; + for (unsigned int i = 0; i < numpoints2; ++i) { + PointType pp2; + keypoints2->GetPoint(i, &pp2); + + if(!match && pp.EuclideanDistanceTo(pp2) <= MATCH_THRESHOLD) + { + ++numMatches; + match = true; + } + if(!match2 && pp.EuclideanDistanceTo(pp2) <= 2*MATCH_THRESHOLD) + { + ++numMatches2; + match2 = true; + } + if(!match5 && pp.EuclideanDistanceTo(pp2) <= 5*MATCH_THRESHOLD) + { + ++numMatches5; + match5 = true; + } + if (match && match2 && match5) + break; + } + } + + std::cout << "Keypoints 1 Matching to Keypoints 2 (<" << MATCH_THRESHOLD << "): " << numMatches << std::endl; + std::cout << "% of Keypoints 1 Matching (<" << MATCH_THRESHOLD << "): " << (float) numMatches / numpoints1 << std::endl; + std::cout << "Keypoints 1 Matching to Keypoints 2 (<" << 2*MATCH_THRESHOLD << "): " << numMatches2 << std::endl; + std::cout << "% of Keypoints 1 Matching (<" << 2*MATCH_THRESHOLD << "): " << (float) numMatches2 / numpoints1 << std::endl; + std::cout << "Keypoints 1 Matching to Keypoints 2 (<" << 5*MATCH_THRESHOLD << "): " << numMatches5 << std::endl; + std::cout << "% of Keypoints 1 Matching (<" << 5*MATCH_THRESHOLD << "): " << (float) numMatches5 / numpoints1 << std::endl; + } + +#ifdef GENERATE_KEYS + template <class TFixedImageType, unsigned int VDimension> + void + ScaleInvariantFeatureImageFilter<TFixedImageType,VDimension> + ::MatchKeypointsFeatures(PointSetTypePointer keypoints1, PointSetTypePointer keypoints2, + typename TransformType::Pointer inverse_transform) + { + // Compare Keypoints. Check Coverage and Accuracy + // This does the comparison based on position of the keypoints + // Find: + // # of points that match which will tell us + // # of points that did not scale + // # of points created by the scale + unsigned int numMatches; + unsigned int numMatchesTried; + unsigned int numMatches2; + unsigned int numMatches5; + const double MATCH_THRESHOLD = 1.5; + typename PointSetType::PointsContainer::Pointer keyps1, keyps2; + + unsigned long numpoints1, numpoints2; + numpoints1 = keypoints1->GetNumberOfPoints(); + std::cout << "Keypoints1 Found: " << numpoints1 << std::endl; + numpoints2 = keypoints2->GetNumberOfPoints(); + std::cout << "Keypoints2 Found: " << numpoints2 << std::endl; + + std::cout << "***Keypoint Matches***\n"; + + numMatches = 0; + numMatches2 = 0; + numMatches5 = 0; + numMatchesTried = 0; + for (unsigned int i = 0; i < numpoints2; ++i) { + PointType pp2; + keypoints2->GetPoint(i, &pp2); + FeatureType ft2; + keypoints2->GetPointData(i, &ft2); + + FeatureType bestft; + float bestdist = -1.0; + float nextbestdist = -1.0; + unsigned int bestj = 0; + for (unsigned int j = 0; j < numpoints1; ++j) { + PointType pp; + keypoints1->GetPoint(j, &pp); + FeatureType ft; + keypoints1->GetPointData(j, &ft); + + float dist = 0.0; + for (unsigned int k = 0; k < ft.Size(); ++k) + dist += (ft[k] - ft2[k])*(ft[k] - ft2[k]); + + if (nextbestdist < 0.0 || dist < bestdist) + { + nextbestdist = bestdist; + bestdist=dist; + bestft = ft; + bestj = j; + } + } + + /* Reject "too close" matches */ + if ((bestdist / nextbestdist) > m_MaxFeatureDistanceRatio) + continue; + + /* NEW IDEA -- look to make sure it is a reciprocal best match */ + /* Take the best feature found, see if pp2 makes the cut */ + bestdist = -1.0; + nextbestdist = -1.0; + FeatureType bestft2; + unsigned int bestj2 = 0; + + for (unsigned int j = 0; j < numpoints2; ++j) { + PointType pp; + keypoints2->GetPoint(j, &pp); + FeatureType ft; + keypoints2->GetPointData(j, &ft); + + float dist = 0.0; + for (int unsigned k = 0; k < ft.Size(); ++k) + dist += (ft[k] - bestft[k])*(ft[k] - bestft[k]); + + if (nextbestdist < 0.0 || dist < bestdist) + { + nextbestdist = bestdist; + bestdist=dist; + bestft2 = ft; + bestj2 = j; + } + } + + /* Reject if not reciprocal best hit or "too close" matches */ + if ( bestft2 != ft2 || ((bestdist / nextbestdist) > m_MaxFeatureDistanceRatio)) + continue; + /* END NEW IDEA */ + + ++numMatchesTried; + + // Check goodness of best feature + PointType tmpp, pp; + keypoints1->GetPoint(bestj, &tmpp); + + // Print the match + std::cout << tmpp << " => " << pp2 << std::endl; + + if (!inverse_transform) + continue; + pp = inverse_transform->TransformPoint(tmpp); + + if(pp.EuclideanDistanceTo(pp2) <= MATCH_THRESHOLD) + ++numMatches; + if(pp.EuclideanDistanceTo(pp2) <= (2*MATCH_THRESHOLD)) + ++numMatches2; + if(pp.EuclideanDistanceTo(pp2) <= (5*MATCH_THRESHOLD)) + ++numMatches5; + } + + std::cout << "\n***Features 2 Matches Attempted: " << numMatchesTried << std::endl; + std::cout << "Features 2 Matching to Features 1 (<" << MATCH_THRESHOLD << "): " << numMatches << std::endl; + std::cout << "% of Features 2 Matching (<" << MATCH_THRESHOLD << "): " << (float) numMatches / numMatchesTried << std::endl; + std::cout << "Features 2 Matching to Features 1 (<" << 2*MATCH_THRESHOLD << "): " << numMatches2 << std::endl; + std::cout << "% of Features 2 Matching (<" << 2*MATCH_THRESHOLD << "): " << (float) numMatches2 / numMatchesTried << std::endl; + std::cout << "Features 2 Matching to Features 1 (<" << 5*MATCH_THRESHOLD << "): " << numMatches5 << std::endl; + std::cout << "% of Features 2 Matching (<" << 5*MATCH_THRESHOLD << "): " << (float) numMatches5 / numMatchesTried << std::endl; + + } +#endif + +} // end namespace itk + +#endif