17 #ifndef __itkCannyEdgeDetectionImageFilter_txx
18 #define __itkCannyEdgeDetectionImageFilter_txx
23 #include "itkNumericTraits.h"
30 template <
class TInputImage,
class TOutputImage>
37 m_MaximumError.Fill(0.01);
44 m_GaussianFilter = GaussianImageFilterType::New();
45 m_MultiplyImageFilter = MultiplyImageFilterType::New();
46 m_UpdateBuffer1 = OutputImageType::New();
57 m_Center = it.
Size() / 2;
59 for (i = 0; i< ImageDimension; ++i)
64 for (i = 0; i< ImageDimension; ++i)
66 m_ComputeCannyEdgeSlice[i]
67 = std::slice( m_Center - m_Stride[i], 3, m_Stride[i]);
71 m_ComputeCannyEdge1stDerivativeOper.SetDirection(0);
72 m_ComputeCannyEdge1stDerivativeOper.SetOrder(1);
73 m_ComputeCannyEdge1stDerivativeOper.CreateDirectional();
75 m_ComputeCannyEdge2ndDerivativeOper.SetDirection(0);
76 m_ComputeCannyEdge2ndDerivativeOper.SetOrder(2);
77 m_ComputeCannyEdge2ndDerivativeOper.CreateDirectional();
80 m_NodeStore = ListNodeStorageType::New();
81 m_NodeList = ListType::New();
84 template <
class TInputImage,
class TOutputImage>
91 typename TInputImage::ConstPointer input = this->GetInput();
93 m_UpdateBuffer1->CopyInformation( input );
94 m_UpdateBuffer1->SetRequestedRegion(input->GetRequestedRegion());
95 m_UpdateBuffer1->SetBufferedRegion(input->GetBufferedRegion());
96 m_UpdateBuffer1->Allocate();
99 template <
class TInputImage,
class TOutputImage>
105 Superclass::GenerateInputRequestedRegion();
109 const_cast< TInputImage *
>( this->GetInput());
112 if ( !inputPtr || !outputPtr )
119 typename TInputImage::SizeValueType radius = 1;
123 typename TInputImage::RegionType inputRequestedRegion;
124 inputRequestedRegion = inputPtr->GetRequestedRegion();
127 inputRequestedRegion.PadByRadius( radius );
130 if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
132 inputPtr->SetRequestedRegion( inputRequestedRegion );
141 inputPtr->SetRequestedRegion( inputRequestedRegion );
144 InvalidRequestedRegionError e(__FILE__, __LINE__);
146 msg << this->GetNameOfClass()
147 <<
"::GenerateInputRequestedRegion()";
149 e.
SetDescription(
"Requested region is (at least partially) outside the largest possible region.");
155 template<
class TInputImage,
class TOutputImage >
159 outputRegionForThread,
int threadId)
165 void *globalData = 0;
169 typename OutputImageType::Pointer input = m_GaussianFilter->GetOutput();
170 typename OutputImageType::Pointer output = this->GetOutput();
177 FaceListType faceList;
179 faceList = bC(input, outputRegionForThread, radius);
182 FaceListType::iterator fit;
185 ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels(), 100, 0.0f, 0.5f );
189 for (fit=faceList.begin(); fit != faceList.end(); ++fit)
199 it.
Value() = ComputeCannyEdge(bit, globalData);
202 progress.CompletedPixel();
209 template<
class TInputImage,
class TOutputImage >
211 ::OutputImagePixelType
214 void * itkNotUsed(globalData) )
228 for(i = 0; i < ImageDimension; i++)
230 dx[i] = innerProduct(m_ComputeCannyEdgeSlice[i], it,
231 m_ComputeCannyEdge1stDerivativeOper);
232 dxx[i] = innerProduct(m_ComputeCannyEdgeSlice[i], it,
233 m_ComputeCannyEdge2ndDerivativeOper);
240 for(i = 0; i < ImageDimension-1; i++)
242 for(j = i+1; j < ImageDimension; j++)
244 dxy[k] = 0.25 * it.
GetPixel(m_Center - m_Stride[i] - m_Stride[j])
245 - 0.25 * it.
GetPixel(m_Center - m_Stride[i]+ m_Stride[j])
246 -0.25 * it.
GetPixel(m_Center + m_Stride[i] - m_Stride[j])
247 +0.25 * it.
GetPixel(m_Center + m_Stride[i] + m_Stride[j]);
249 deriv += 2.0 * dx[i]*dx[j]*dxy[k];
255 for (i = 0; i < ImageDimension; i++)
257 deriv += dx[i] * dx[i] * dxx[i];
258 gradMag += dx[i] * dx[i];
261 deriv = deriv/gradMag;
267 template<
class TInputImage,
class TOutputImage >
276 this->GetMultiThreader()->SetSingleMethod(this->Compute2ndDerivativeThreaderCallback, &str);
278 this->GetMultiThreader()->SingleMethodExecute();
281 template<
class TInputImage,
class TOutputImage>
288 int total, threadId, threadCount;
302 if (threadId < total)
310 template<
class TInputImage,
class TOutputImage >
316 this->GetOutput()->SetBufferedRegion( this->GetOutput()->GetRequestedRegion() );
317 this->GetOutput()->Allocate();
319 typename InputImageType::ConstPointer input = this->GetInput();
330 this->AllocateUpdateBuffer();
333 m_GaussianFilter->SetVariance(m_Variance);
334 m_GaussianFilter->SetMaximumError(m_MaximumError);
335 m_GaussianFilter->SetInput(input);
337 m_GaussianFilter->Modified();
338 m_GaussianFilter->Update();
344 this->Compute2ndDerivative();
346 this->Compute2ndDerivativePos();
353 zeroCrossFilter->SetInput(this->GetOutput());
354 zeroCrossFilter->Update();
359 m_MultiplyImageFilter->SetInput1(m_UpdateBuffer1);
360 m_MultiplyImageFilter->SetInput2(zeroCrossFilter->GetOutput());
364 m_MultiplyImageFilter->GraftOutput( m_GaussianFilter->GetOutput() );
365 m_MultiplyImageFilter->Update();
368 this->HysteresisThresholding();
371 template<
class TInputImage,
class TOutputImage >
379 typename OutputImageType::Pointer input = m_MultiplyImageFilter->GetOutput();
390 this->GetOutput()->GetRequestedRegion());
398 while(!oit.IsAtEnd())
402 if(value > m_UpperThreshold)
404 node = m_NodeStore->Borrow();
405 node->
m_Value = oit.GetIndex();
406 m_NodeList->PushFront(node);
407 FollowEdge(oit.GetIndex());
414 template<
class TInputImage,
class TOutputImage >
422 typename OutputImageType::Pointer input = m_MultiplyImageFilter->GetOutput();
434 input, input->GetRequestedRegion());
436 this->GetOutput()->GetRequestedRegion());
444 node = m_NodeList->Front();
445 m_NodeList->PopFront();
446 m_NodeStore->Return(node);
450 int nSize = m_Center * 2 +1;
451 while(!m_NodeList->Empty())
454 node = m_NodeList->Front();
456 m_NodeList->PopFront();
457 m_NodeStore->Return(node);
460 oit.SetLocation(cIndex);
461 uit.SetIndex(cIndex);
465 for(
int i = 0; i < nSize; i++)
468 uit.SetIndex(nIndex);
469 if(inputRegion.IsInside(nIndex))
473 node = m_NodeStore->Borrow();
475 m_NodeList->PushFront(node);
477 uit.SetIndex(nIndex);
486 template<
class TInputImage,
class TOutputImage >
502 typename OutputImageType::Pointer input1 = this->GetOutput();
503 typename OutputImageType::Pointer input = m_GaussianFilter->GetOutput();
505 typename InputImageType::Pointer output = m_UpdateBuffer1;
513 FaceListType faceList;
515 faceList = bC(input, outputRegionForThread, radius);
518 FaceListType::iterator fit;
521 ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels(), 100, 0.5f, 0.5f);
538 for (fit=faceList.begin(); fit != faceList.end(); ++fit)
555 for (
unsigned int i = 0; i < ImageDimension; i++)
557 dx[i] = IP(m_ComputeCannyEdgeSlice[i], bit,
558 m_ComputeCannyEdge1stDerivativeOper);
559 gradMag += dx[i] * dx[i];
561 dx1[i] = IP(m_ComputeCannyEdgeSlice[i], bit1,
562 m_ComputeCannyEdge1stDerivativeOper);
565 gradMag = vcl_sqrt((
double)gradMag);
567 for (
unsigned int i = 0; i < ImageDimension; i++)
572 directional[i] = dx[i]/gradMag;
576 derivPos += dx1[i] * directional[i];
579 it.Value() = ((derivPos <= zero));
580 it.Value() = it.Get() * gradMag;
584 progress.CompletedPixel();
591 template<
class TInputImage,
class TOutputImage >
600 this->GetMultiThreader()->SetSingleMethod(this->Compute2ndDerivativePosThreaderCallback, &str);
602 this->GetMultiThreader()->SingleMethodExecute();
605 template<
class TInputImage,
class TOutputImage>
612 int total, threadId, threadCount;
627 if (threadId < total)
635 template <
class TInputImage,
class TOutputImage>
640 Superclass::PrintSelf(os,indent);
642 os <<
"Variance: " << m_Variance << std::endl;
643 os <<
"MaximumError: " << m_MaximumError << std::endl;
644 os << indent <<
"Threshold: "
647 os << indent <<
"UpperThreshold: "
650 os << indent <<
"LowerThreshold: "
653 os << indent <<
"OutsideValue: "
657 << m_Center << std::endl;
659 << m_Stride << std::endl;
660 os <<
"Gaussian Filter: " << std::endl;
662 os <<
"Multiply image Filter: " << std::endl;
664 os <<
"UpdateBuffer1: " << std::endl;