itkCannyEdgeDetectionImageFilter.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __itkCannyEdgeDetectionImageFilter_h
00018 #define __itkCannyEdgeDetectionImageFilter_h
00019
00020 #include "itkImageToImageFilter.h"
00021 #include "itkImage.h"
00022 #include "itkFixedArray.h"
00023 #include "itkConstNeighborhoodIterator.h"
00024 #include "itkDiscreteGaussianImageFilter.h"
00025 #include "itkMultiplyImageFilter.h"
00026 #include "itkZeroFluxNeumannBoundaryCondition.h"
00027 #include "itkMultiThreader.h"
00028 #include "itkDerivativeOperator.h"
00029 #include "itkSparseFieldLayer.h"
00030 #include "itkObjectStore.h"
00031
00032
00033 namespace itk
00034 {
00035
00036
00037 template <class TValueType>
00038 class ListNode
00039 {
00040 public:
00041 TValueType m_Value;
00042
00043 ListNode *Next;
00044 ListNode *Previous;
00045 };
00046
00047
00089 template<class TInputImage, class TOutputImage>
00090 class ITK_EXPORT CannyEdgeDetectionImageFilter
00091 : public ImageToImageFilter<TInputImage, TOutputImage>
00092 {
00093 public:
00095 typedef CannyEdgeDetectionImageFilter Self;
00096 typedef ImageToImageFilter<TInputImage, TOutputImage> Superclass;
00097
00099 typedef TInputImage InputImageType;
00100 typedef TOutputImage OutputImageType;
00101
00103 typedef SmartPointer<Self> Pointer;
00104 typedef SmartPointer<const Self> ConstPointer;
00105
00107 typedef typename TInputImage::PixelType InputImagePixelType;
00108 typedef typename TOutputImage::PixelType OutputImagePixelType;
00109 typedef typename TInputImage::IndexType IndexType;
00110
00113 typedef ZeroFluxNeumannBoundaryCondition<OutputImageType>
00114 DefaultBoundaryConditionType;
00115
00119 typedef ConstNeighborhoodIterator<OutputImageType,
00120 DefaultBoundaryConditionType> NeighborhoodType;
00121
00122 typedef ListNode<IndexType> ListNodeType;
00123 typedef ObjectStore<ListNodeType> ListNodeStorageType;
00124 typedef SparseFieldLayer<ListNodeType> ListType;
00125 typedef typename ListType::Pointer ListPointerType;
00126
00128 itkNewMacro(Self);
00129
00131 typedef typename TOutputImage::RegionType OutputImageRegionType;
00132
00134 itkTypeMacro(CannyEdgeDetectionImageFilter, ImageToImageFilter);
00135
00137 itkStaticConstMacro(ImageDimension, unsigned int,
00138 TInputImage::ImageDimension);
00139 itkStaticConstMacro(OutputImageDimension, unsigned int,
00140 TOutputImage::ImageDimension);
00142
00144 typedef FixedArray<double, itkGetStaticConstMacro(ImageDimension)> ArrayType;
00145
00147 itkSetMacro(Variance, ArrayType);
00148 itkGetMacro(Variance, const ArrayType);
00149 itkSetMacro(MaximumError, ArrayType);
00150 itkGetMacro(MaximumError, const ArrayType);
00152
00155 void SetVariance(const typename ArrayType::ValueType v)
00156 {
00157 for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
00158 {
00159 if (m_Variance[i] != v)
00160 {
00161 m_Variance.Fill(v);
00162 this->Modified();
00163 break;
00164 }
00165 }
00166 }
00168
00171 void SetMaximumError(const typename ArrayType::ValueType v)
00172 {
00173 for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
00174 {
00175 if (m_MaximumError[i] != v)
00176 {
00177 m_MaximumError.Fill(v);
00178 this->Modified();
00179 break;
00180 }
00181 }
00182 }
00184
00185
00186 void SetThreshold(const OutputImagePixelType th)
00187 {
00188 this->m_Threshold = th;
00189 this->m_UpperThreshold = m_Threshold;
00190 this->m_LowerThreshold = m_Threshold/2.0;
00191 itkLegacyReplaceBodyMacro(SetThreshold, 2.2, SetUpperThreshold);
00192 }
00193
00194 OutputImagePixelType GetThreshold(OutputImagePixelType th)
00195 {
00196 itkLegacyReplaceBodyMacro(GetThreshold, 2.2, GetUpperThreshold);
00197 return this->m_Threshold;
00198 }
00199
00201 itkSetMacro(UpperThreshold, OutputImagePixelType );
00202 itkGetMacro(UpperThreshold, OutputImagePixelType);
00203
00204 itkSetMacro(LowerThreshold, OutputImagePixelType );
00205 itkGetMacro(LowerThreshold, OutputImagePixelType);
00206
00207
00208 itkSetMacro(OutsideValue, OutputImagePixelType);
00209 itkGetMacro(OutsideValue, OutputImagePixelType);
00210
00211 OutputImageType * GetNonMaximumSuppressionImage()
00212 {
00213 return this->m_MultiplyImageFilter->GetOutput();
00214 }
00215
00223 virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError);
00224
00225 #ifdef ITK_USE_CONCEPT_CHECKING
00226
00227 itkConceptMacro(InputHasNumericTraitsCheck,
00228 (Concept::HasNumericTraits<InputImagePixelType>));
00229 itkConceptMacro(OutputHasNumericTraitsCheck,
00230 (Concept::HasNumericTraits<OutputImagePixelType>));
00231 itkConceptMacro(SameDimensionCheck,
00232 (Concept::SameDimension<ImageDimension, OutputImageDimension>));
00233 itkConceptMacro(InputIsFloatingPointCheck,
00234 (Concept::IsFloatingPoint<InputImagePixelType>));
00235 itkConceptMacro(OutputIsFloatingPointCheck,
00236 (Concept::IsFloatingPoint<OutputImagePixelType>));
00237
00239 #endif
00240
00241 protected:
00242 CannyEdgeDetectionImageFilter();
00243 CannyEdgeDetectionImageFilter(const Self&) {}
00244 void PrintSelf(std::ostream& os, Indent indent) const;
00245
00246 void GenerateData();
00247
00248 typedef DiscreteGaussianImageFilter<InputImageType, OutputImageType>
00249 GaussianImageFilterType;
00250 typedef MultiplyImageFilter< OutputImageType,
00251 OutputImageType, OutputImageType> MultiplyImageFilterType;
00252
00253 private:
00254 virtual ~CannyEdgeDetectionImageFilter(){};
00255
00257 struct CannyThreadStruct
00258 {
00259 CannyEdgeDetectionImageFilter *Filter;
00260 };
00261
00263 void AllocateUpdateBuffer();
00264
00266 void HysteresisThresholding();
00267
00269 void FollowEdge(IndexType index);
00270
00272 bool InBounds(IndexType index);
00273
00274
00278 void Compute2ndDerivative();
00279
00288
00289
00290
00296 void ThreadedCompute2ndDerivative(const OutputImageRegionType&
00297 outputRegionForThread, int threadId);
00298
00302 static ITK_THREAD_RETURN_TYPE
00303 Compute2ndDerivativeThreaderCallback( void * arg );
00304
00308 OutputImagePixelType ComputeCannyEdge(const NeighborhoodType &it,
00309 void *globalData );
00310
00315 void Compute2ndDerivativePos();
00316
00322 void ThreadedCompute2ndDerivativePos(const OutputImageRegionType&
00323 outputRegionForThread, int threadId);
00324
00328 static ITK_THREAD_RETURN_TYPE
00329 Compute2ndDerivativePosThreaderCallback( void *arg );
00330
00332 ArrayType m_Variance;
00333
00336 ArrayType m_MaximumError;
00337
00339 OutputImagePixelType m_UpperThreshold;
00340
00342 OutputImagePixelType m_LowerThreshold;
00343
00345 OutputImagePixelType m_Threshold;
00346
00348 OutputImagePixelType m_OutsideValue;
00349
00351 typename OutputImageType::Pointer m_UpdateBuffer1;
00352
00354 typename GaussianImageFilterType::Pointer m_GaussianFilter;
00355
00358 typename MultiplyImageFilterType::Pointer m_MultiplyImageFilter;
00359
00362 DerivativeOperator<OutputImagePixelType,itkGetStaticConstMacro(ImageDimension)>
00363 m_ComputeCannyEdge1stDerivativeOper;
00364 DerivativeOperator<OutputImagePixelType,itkGetStaticConstMacro(ImageDimension)>
00365 m_ComputeCannyEdge2ndDerivativeOper;
00367
00368 std::slice m_ComputeCannyEdgeSlice[ImageDimension];
00369
00370 unsigned long m_Stride[ImageDimension];
00371 unsigned long m_Center;
00372
00373 typename ListNodeStorageType::Pointer m_NodeStore;
00374 ListPointerType m_NodeList;
00375
00376 };
00377
00378 }
00379
00380 #ifndef ITK_MANUAL_INSTANTIATION
00381 #include "itkCannyEdgeDetectionImageFilter.txx"
00382 #endif
00383
00384 #endif
00385