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 "itkZeroFluxNeumannBoundaryCondition.h"
00025 #include "itkMultiThreader.h"
00026 #include "itkDerivativeOperator.h"
00027 #include "itkSparseFieldLayer.h"
00028 #include "itkObjectStore.h"
00029
00030
00031 namespace itk
00032 {
00033
00034
00035 template <class TValueType>
00036 class ListNode
00037 {
00038 public:
00039 TValueType m_Value;
00040 ListNode *Next;
00041 ListNode *Previous;
00042 };
00043
00044
00086 template<class TInputImage, class TOutputImage>
00087 class ITK_EXPORT CannyEdgeDetectionImageFilter
00088 : public ImageToImageFilter<TInputImage, TOutputImage>
00089 {
00090 public:
00092 typedef CannyEdgeDetectionImageFilter Self;
00093 typedef ImageToImageFilter<TInputImage, TOutputImage> Superclass;
00094
00096 typedef TInputImage InputImageType;
00097 typedef TOutputImage OutputImageType;
00098
00100 typedef SmartPointer<Self> Pointer;
00101 typedef SmartPointer<const Self> ConstPointer;
00102
00104 typedef typename TInputImage::PixelType InputImagePixelType;
00105 typedef typename TOutputImage::PixelType OutputImagePixelType;
00106 typedef typename TInputImage::IndexType IndexType;
00107
00110 typedef ZeroFluxNeumannBoundaryCondition<OutputImageType>
00111 DefaultBoundaryConditionType;
00112
00116 typedef ConstNeighborhoodIterator<OutputImageType,
00117 DefaultBoundaryConditionType> NeighborhoodType;
00118
00119 typedef ListNode<IndexType> ListNodeType;
00120 typedef ObjectStore<ListNodeType> ListNodeStorageType;
00121 typedef SparseFieldLayer<ListNodeType> ListType;
00122 typedef typename ListType::Pointer ListPointerType;
00123
00125 itkNewMacro(Self);
00126
00128 typedef typename TOutputImage::RegionType OutputImageRegionType;
00129
00131 itkTypeMacro(CannyEdgeDetectionImageFilter, ImageToImageFilter);
00132
00134 itkStaticConstMacro(ImageDimension, unsigned int,
00135 TInputImage::ImageDimension);
00136
00138 typedef FixedArray<double, itkGetStaticConstMacro(ImageDimension)> ArrayType;
00139
00141 itkSetMacro(Variance, ArrayType);
00142 itkGetMacro(Variance, const ArrayType);
00143 itkSetMacro(MaximumError, ArrayType);
00144 itkGetMacro(MaximumError, const ArrayType);
00145
00148 void SetVariance(const typename ArrayType::ValueType v)
00149 {
00150 for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
00151 {
00152 if (m_Variance[i] != v)
00153 {
00154 m_Variance.Fill(v);
00155 this->Modified();
00156 break;
00157 }
00158 }
00159 }
00160
00163 void SetMaximumError(const typename ArrayType::ValueType v)
00164 {
00165 for (unsigned int i=0; i < TInputImage::ImageDimension; i++)
00166 {
00167 if (m_Variance[i] != v)
00168 {
00169 m_MaximumError.Fill(v);
00170 this->Modified();
00171 break;
00172 }
00173 }
00174 }
00175
00176
00177 void SetThreshold(const OutputImagePixelType th)
00178 {
00179 this->m_Threshold = th;
00180 this->m_UpperThreshold = m_Threshold;
00181 this->m_LowerThreshold = m_Threshold/2.0;
00182 itkLegacyReplaceBody(SetThreshold, 2.2, SetUpperThreshold);
00183 }
00184
00185 OutputImagePixelType GetThreshold(OutputImagePixelType th)
00186 {
00187 itkLegacyReplaceBody(GetThreshold, 2.2, GetUpperThreshold);
00188 return this->m_Threshold;
00189 }
00190
00192 itkSetMacro(UpperThreshold, OutputImagePixelType );
00193 itkGetMacro(UpperThreshold, OutputImagePixelType);
00194
00195 itkSetMacro(LowerThreshold, OutputImagePixelType );
00196 itkGetMacro(LowerThreshold, OutputImagePixelType);
00197
00198
00199 itkSetMacro(OutsideValue, OutputImagePixelType);
00200 itkGetMacro(OutsideValue, OutputImagePixelType);
00201
00209 virtual void GenerateInputRequestedRegion() throw(InvalidRequestedRegionError);
00210
00211 protected:
00212 CannyEdgeDetectionImageFilter();
00213 CannyEdgeDetectionImageFilter(const Self&) {}
00214 void PrintSelf(std::ostream& os, Indent indent) const;
00215
00216 void GenerateData();
00217
00218 private:
00219 virtual ~CannyEdgeDetectionImageFilter(){};
00220
00222 struct CannyThreadStruct
00223 {
00224 CannyEdgeDetectionImageFilter *Filter;
00225 };
00226
00228 void AllocateUpdateBuffer();
00229
00231 void HysteresisThresholding();
00232
00234 void FollowEdge(IndexType index);
00235
00237 bool InBounds(IndexType index);
00238
00239
00243 void Compute2ndDerivative();
00244
00253
00254
00255
00261 void ThreadedCompute2ndDerivative(const OutputImageRegionType&
00262 outputRegionForThread, int threadId);
00263
00267 static ITK_THREAD_RETURN_TYPE
00268 Compute2ndDerivativeThreaderCallback( void * arg );
00269
00273 OutputImagePixelType ComputeCannyEdge(const NeighborhoodType &it,
00274 void *globalData );
00275
00280 void Compute2ndDerivativePos();
00281
00287 void ThreadedCompute2ndDerivativePos(const OutputImageRegionType&
00288 outputRegionForThread, int threadId);
00289
00293 static ITK_THREAD_RETURN_TYPE
00294 Compute2ndDerivativePosThreaderCallback( void *arg );
00295
00297 ArrayType m_Variance;
00298
00301 ArrayType m_MaximumError;
00302
00304 OutputImagePixelType m_UpperThreshold;
00305
00307 OutputImagePixelType m_LowerThreshold;
00308
00310 OutputImagePixelType m_Threshold;
00311
00313 OutputImagePixelType m_OutsideValue;
00314
00316 typename OutputImageType::Pointer m_UpdateBuffer;
00317 typename OutputImageType::Pointer m_UpdateBuffer1;
00318
00321 DerivativeOperator<OutputImagePixelType,itkGetStaticConstMacro(ImageDimension)>
00322 m_ComputeCannyEdge1stDerivativeOper;
00323 DerivativeOperator<OutputImagePixelType,itkGetStaticConstMacro(ImageDimension)>
00324 m_ComputeCannyEdge2ndDerivativeOper;
00325
00326 std::slice m_ComputeCannyEdgeSlice[ImageDimension];
00327
00328 unsigned long m_Stride[ImageDimension];
00329 unsigned long m_Center;
00330
00331 typename ListNodeStorageType::Pointer m_NodeStore;
00332 ListPointerType m_NodeList;
00333
00334 };
00335
00336 }
00337
00338 #ifndef ITK_MANUAL_INSTANTIATION
00339 #include "itkCannyEdgeDetectionImageFilter.txx"
00340 #endif
00341
00342 #endif
00343