ITK  4.0.0
Insight Segmentation and Registration Toolkit
itkCannyEdgeDetectionImageFilter.h
Go to the documentation of this file.
00001 /*=========================================================================
00002  *
00003  *  Copyright Insight Software Consortium
00004  *
00005  *  Licensed under the Apache License, Version 2.0 (the "License");
00006  *  you may not use this file except in compliance with the License.
00007  *  You may obtain a copy of the License at
00008  *
00009  *         http://www.apache.org/licenses/LICENSE-2.0.txt
00010  *
00011  *  Unless required by applicable law or agreed to in writing, software
00012  *  distributed under the License is distributed on an "AS IS" BASIS,
00013  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  *  See the License for the specific language governing permissions and
00015  *  limitations under the License.
00016  *
00017  *=========================================================================*/
00018 #ifndef __itkCannyEdgeDetectionImageFilter_h
00019 #define __itkCannyEdgeDetectionImageFilter_h
00020 
00021 #include "itkConstNeighborhoodIterator.h"
00022 #include "itkDiscreteGaussianImageFilter.h"
00023 #include "itkMultiplyImageFilter.h"
00024 #include "itkMultiThreader.h"
00025 #include "itkDerivativeOperator.h"
00026 #include "itkSparseFieldLayer.h"
00027 #include "itkObjectStore.h"
00028 
00029 namespace itk
00030 {
00031 template< class TValueType >
00032 class ListNode
00033 {
00034 public:
00035   TValueType m_Value;
00036 
00037   ListNode *Next;
00038   ListNode *Previous;
00039 };
00040 
00083 template< class TInputImage, class TOutputImage >
00084 class ITK_EXPORT CannyEdgeDetectionImageFilter:
00085   public ImageToImageFilter< TInputImage, TOutputImage >
00086 {
00087 public:
00089   typedef CannyEdgeDetectionImageFilter                   Self;
00090   typedef ImageToImageFilter< TInputImage, TOutputImage > Superclass;
00091 
00093   typedef TInputImage  InputImageType;
00094   typedef TOutputImage OutputImageType;
00095 
00097   typedef SmartPointer< Self >       Pointer;
00098   typedef SmartPointer< const Self > ConstPointer;
00099 
00101   typedef typename TInputImage::PixelType     InputImagePixelType;
00102   typedef typename TOutputImage::PixelType    OutputImagePixelType;
00103   typedef typename TInputImage::IndexType     IndexType;
00104   typedef typename TInputImage::SizeValueType SizeValueType;
00105 
00108   typedef ZeroFluxNeumannBoundaryCondition< OutputImageType >
00109   DefaultBoundaryConditionType;
00110 
00114   typedef ConstNeighborhoodIterator< OutputImageType,
00115                                      DefaultBoundaryConditionType > NeighborhoodType;
00116 
00117   typedef ListNode< IndexType >            ListNodeType;
00118   typedef ObjectStore< ListNodeType >      ListNodeStorageType;
00119   typedef SparseFieldLayer< ListNodeType > ListType;
00120   typedef typename ListType::Pointer       ListPointerType;
00121 
00123   itkNewMacro(Self);
00124 
00126   typedef typename TOutputImage::RegionType OutputImageRegionType;
00127   typedef typename TInputImage::RegionType  InputImageRegionType;
00128 
00130   itkTypeMacro(CannyEdgeDetectionImageFilter, ImageToImageFilter);
00131 
00133   itkStaticConstMacro(ImageDimension, unsigned int,
00134                       TInputImage::ImageDimension);
00135   itkStaticConstMacro(OutputImageDimension, unsigned int,
00136                       TOutputImage::ImageDimension);
00138 
00140   typedef FixedArray< double, itkGetStaticConstMacro(ImageDimension) > ArrayType;
00141 
00143   itkSetMacro(Variance, ArrayType);
00144   itkGetConstMacro(Variance, const ArrayType);
00145   itkSetMacro(MaximumError, ArrayType);
00146   itkGetConstMacro(MaximumError, const ArrayType);
00148 
00151   void SetVariance(const typename ArrayType::ValueType v)
00152   {
00153     for ( unsigned int i = 0; i < TInputImage::ImageDimension; i++ )
00154       {
00155       if ( m_Variance[i] != v )
00156         {
00157         m_Variance.Fill(v);
00158         this->Modified();
00159         break;
00160         }
00161       }
00162   }
00164 
00167   void SetMaximumError(const typename ArrayType::ValueType v)
00168   {
00169     for ( unsigned int i = 0; i < TInputImage::ImageDimension; i++ )
00170       {
00171       if ( m_MaximumError[i] != v )
00172         {
00173         m_MaximumError.Fill(v);
00174         this->Modified();
00175         break;
00176         }
00177       }
00178   }
00180 
00190 
00191   itkSetMacro(UpperThreshold, OutputImagePixelType);
00192   itkGetConstMacro(UpperThreshold, OutputImagePixelType);
00193 
00194   itkSetMacro(LowerThreshold, OutputImagePixelType);
00195   itkGetConstMacro(LowerThreshold, OutputImagePixelType);
00196 
00197   OutputImageType * GetNonMaximumSuppressionImage()
00198   {
00199     return this->m_MultiplyImageFilter->GetOutput();
00200   }
00201 
00209   virtual void GenerateInputRequestedRegion()
00210   throw( InvalidRequestedRegionError );
00211 
00212 #ifdef ITK_USE_CONCEPT_CHECKING
00213 
00214   itkConceptMacro( InputHasNumericTraitsCheck,
00215                    ( Concept::HasNumericTraits< InputImagePixelType > ) );
00216   itkConceptMacro( OutputHasNumericTraitsCheck,
00217                    ( Concept::HasNumericTraits< OutputImagePixelType > ) );
00218   itkConceptMacro( SameDimensionCheck,
00219                    ( Concept::SameDimension< ImageDimension, OutputImageDimension > ) );
00220   itkConceptMacro( InputIsFloatingPointCheck,
00221                    ( Concept::IsFloatingPoint< InputImagePixelType > ) );
00222   itkConceptMacro( OutputIsFloatingPointCheck,
00223                    ( Concept::IsFloatingPoint< OutputImagePixelType > ) );
00224 
00226 #endif
00227 protected:
00228   CannyEdgeDetectionImageFilter();
00229   void PrintSelf(std::ostream & os, Indent indent) const;
00231 
00232   void GenerateData();
00233 
00234   typedef DiscreteGaussianImageFilter< InputImageType, OutputImageType >
00235   GaussianImageFilterType;
00236   typedef MultiplyImageFilter< OutputImageType,
00237                                OutputImageType, OutputImageType >       MultiplyImageFilterType;
00238 private:
00239   CannyEdgeDetectionImageFilter(const Self &); //purposely not implemented
00240   void operator=(const Self &); //purposely not implemented
00241 
00242   virtual ~CannyEdgeDetectionImageFilter(){}
00243 
00245   struct CannyThreadStruct
00246   {
00247     CannyEdgeDetectionImageFilter *Filter;
00248   };
00249 
00251   void AllocateUpdateBuffer();
00252 
00254   void HysteresisThresholding();
00255 
00257   void FollowEdge(IndexType index);
00258 
00262   void Compute2ndDerivative();
00263 
00272   //  virtual
00273   //  int SplitUpdateContainer(int i, int num, ThreadRegionType& splitRegion);
00274 
00280   void ThreadedCompute2ndDerivative(const OutputImageRegionType &
00281                                     outputRegionForThread, ThreadIdType threadId);
00282 
00286   static ITK_THREAD_RETURN_TYPE
00287   Compute2ndDerivativeThreaderCallback(void *arg);
00288 
00292   OutputImagePixelType ComputeCannyEdge(const NeighborhoodType & it,
00293                                         void *globalData);
00294 
00299   void Compute2ndDerivativePos();
00300 
00306   void ThreadedCompute2ndDerivativePos(const OutputImageRegionType &
00307                                        outputRegionForThread, ThreadIdType threadId);
00308 
00312   static ITK_THREAD_RETURN_TYPE
00313   Compute2ndDerivativePosThreaderCallback(void *arg);
00314 
00316   ArrayType m_Variance;
00317 
00320   ArrayType m_MaximumError;
00321 
00323   OutputImagePixelType m_UpperThreshold;  //should be float here?
00324 
00326   OutputImagePixelType m_LowerThreshold; //should be float here?
00327 
00329   typename OutputImageType::Pointer m_UpdateBuffer1;
00330 
00332   typename GaussianImageFilterType::Pointer m_GaussianFilter;
00333 
00336   typename MultiplyImageFilterType::Pointer m_MultiplyImageFilter;
00337 
00340   DerivativeOperator< OutputImagePixelType, itkGetStaticConstMacro(ImageDimension) >
00341   m_ComputeCannyEdge1stDerivativeOper;
00342   DerivativeOperator< OutputImagePixelType, itkGetStaticConstMacro(ImageDimension) >
00343   m_ComputeCannyEdge2ndDerivativeOper;
00345 
00346   std::slice m_ComputeCannyEdgeSlice[ImageDimension];
00347 
00348   SizeValueType m_Stride[ImageDimension];
00349   SizeValueType m_Center;
00350 
00351   typename ListNodeStorageType::Pointer m_NodeStore;
00352   ListPointerType m_NodeList;
00353 };
00354 } //end of namespace itk
00355 
00356 #ifndef ITK_MANUAL_INSTANTIATION
00357 #include "itkCannyEdgeDetectionImageFilter.hxx"
00358 #endif
00359 
00360 #endif
00361