Orfeo Toolbox  3.16
itkHoughTransform2DCirclesImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkHoughTransform2DCirclesImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2009-04-05 23:09:19 $
7  Version: $Revision: 1.20 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 
18 #ifndef __itkHoughTransform2DCirclesImageFilter_txx
19 #define __itkHoughTransform2DCirclesImageFilter_txx
20 
26 
27 
28 namespace itk
29 {
30 
31 template<typename TInputPixelType, typename TOutputPixelType>
34 {
35  m_Threshold = 0;
36  m_MinimumRadius = 0; // by default
37  m_MaximumRadius = 10; // by default
38  m_SigmaGradient = 1; // Scale of the DoG filter
39  m_DiscRadiusRatio = 1;
40  m_Variance = 10;
41  m_OldModifiedTime = 0;
42  m_OldNumberOfCircles = 0;
43  m_SweepAngle = 0.0;
44  m_NumberOfCircles = 1;
45 }
46 
47 template<typename TInputPixelType, typename TOutputPixelType>
48 void
50 ::SetRadius(double radius)
51 {
52  this->SetMinimumRadius(radius);
53  this->SetMaximumRadius(radius);
54 }
55 
56 template<typename TInputPixelType, typename TOutputPixelType>
57 void
60 {
61  Superclass::EnlargeOutputRequestedRegion(output);
63 }
64 
65 
66 template<typename TInputPixelType, typename TOutputPixelType>
67 void
70 {
71  Superclass::GenerateInputRequestedRegion();
72  if ( this->GetInput() )
73  {
74  InputImagePointer image =
75  const_cast< InputImageType * >( this->GetInput() );
76  image->SetRequestedRegionToLargestPossibleRegion();
77  }
78 }
79 
80 template<typename TInputPixelType, typename TOutputPixelType>
81 void
84 {
85 
86  // Get the input and output pointers
87  InputImageConstPointer inputImage = this->GetInput(0);
88  OutputImagePointer outputImage = this->GetOutput(0);
89 
90  // Allocate the output
91  this->AllocateOutputs();
92  outputImage->FillBuffer(0);
93 
95  typename DoGFunctionType::Pointer DoGFunction = DoGFunctionType::New();
96  DoGFunction->SetInputImage(inputImage);
97  DoGFunction->SetSigma(m_SigmaGradient);
98 
99  m_RadiusImage = OutputImageType::New();
100 
101  m_RadiusImage->SetRegions( outputImage->GetLargestPossibleRegion() );
102  m_RadiusImage->SetOrigin(inputImage->GetOrigin());
103  m_RadiusImage->SetSpacing(inputImage->GetSpacing());
104  m_RadiusImage->SetDirection(inputImage->GetDirection());
105  m_RadiusImage->Allocate();
106  m_RadiusImage->FillBuffer(0);
107 
108  ImageRegionConstIteratorWithIndex< InputImageType > image_it( inputImage, inputImage->GetRequestedRegion() );
109  image_it.Begin();
110 
111  Index<2> index;
112  Point<float,2> point;
113 
114  while( !image_it.IsAtEnd() )
115  {
116  if(image_it.Get()>m_Threshold)
117  {
118  point[0] = image_it.GetIndex()[0];
119  point[1] = image_it.GetIndex()[1];
120  typename DoGFunctionType::VectorType grad = DoGFunction->EvaluateAtIndex(image_it.GetIndex());
121 
122  double Vx = grad[0];
123  double Vy = grad[1];
124 
125  if( (vcl_fabs(Vx)>1) || (vcl_fabs(Vy)>1) ) // if the gradient is not flat
126  {
127  double norm = vcl_sqrt(Vx*Vx+Vy*Vy);
128  Vx /= norm;
129  Vy /= norm;
130 
131  for(double angle = -m_SweepAngle;angle<=m_SweepAngle;angle+=0.05)
132  {
133  double i = m_MinimumRadius;
134  double distance;
135 
136  do
137  {
138  index[0] = (long int)(point[0]-i*(Vx*vcl_cos(angle)+Vy*vcl_sin(angle)));
139  index[1] = (long int)(point[1]-i*(Vx*vcl_sin(angle)+Vy*vcl_cos(angle)));
140 
141  distance = vcl_sqrt((index[1]-point[1])*(index[1]-point[1])
142  +(index[0]-point[0])*(index[0]-point[0]) );
143 
144 
145  if(outputImage->GetRequestedRegion().IsInside( index ))
146  {
147  outputImage->SetPixel(index, outputImage->GetPixel(index)+1);
148  m_RadiusImage->SetPixel(index, (m_RadiusImage->GetPixel(index)+distance));
149  }
150 
151  i=i+1;
152 
153  } while( outputImage->GetRequestedRegion().IsInside( index )
154  && (distance < m_MaximumRadius) );
155  }
156  }
157  }
158  ++image_it;
159  }
160 
161  // Compute the average radius
162  ImageRegionConstIterator< OutputImageType > output_it( outputImage, outputImage->GetLargestPossibleRegion() );
163  ImageRegionIterator< OutputImageType > radius_it( m_RadiusImage, m_RadiusImage->GetLargestPossibleRegion() );
164  output_it.Begin();
165  radius_it.Begin();
166  while( !output_it.IsAtEnd() )
167  {
168  if(output_it.Get()>0)
169  {
170  radius_it.Set(radius_it.Get()/output_it.Get());
171  }
172  ++output_it;
173  ++radius_it;
174  }
175 }
176 
177 
179 template<typename TInputPixelType, typename TOutputPixelType>
182 ::GetCircles(unsigned int n)
183 {
184  if((this->GetMTime() == m_OldModifiedTime) && (n == m_OldNumberOfCircles)) // if the filter has not been updated
185  {
186  return m_CirclesList;
187  }
188 
189  m_CirclesList.clear();
190 
192  typedef Image<float,2> InternalImageType;
193 
194  OutputImagePointer outputImage = OutputImageType::New();
195  outputImage->SetRegions( this->GetOutput(0)->GetLargestPossibleRegion() );
196  outputImage->SetOrigin(this->GetOutput(0)->GetOrigin());
197  outputImage->SetSpacing(this->GetOutput(0)->GetSpacing());
198  outputImage->SetDirection(this->GetOutput(0)->GetDirection());
199  outputImage->Allocate();
200  outputImage->FillBuffer(0);
201 
202  ImageRegionConstIteratorWithIndex< OutputImageType > image_it( this->GetOutput(0), this->GetOutput(0)->GetRequestedRegion() );
203  image_it.GoToBegin();
204 
205  ImageRegionIterator< InternalImageType > it( outputImage, outputImage->GetRequestedRegion() );
206 
207  while( !image_it.IsAtEnd() )
208  {
209  it.Set(image_it.Get());
210  ++image_it;
211  ++it;
212  }
213 
214 
216  typename GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New();
217 
218  gaussianFilter->SetInput(outputImage); // the output is the accumulator image
219  double variance[2];
220  variance[0] = m_Variance;
221  variance[1] = m_Variance;
222  gaussianFilter->SetVariance(variance);
223  gaussianFilter->Update();
224  typename InternalImageType::Pointer postProcessImage = gaussianFilter->GetOutput();
225 
226  typedef MinimumMaximumImageCalculator<InternalImageType> MinMaxCalculatorType;
227  typename MinMaxCalculatorType::Pointer minMaxCalculator = MinMaxCalculatorType::New();
228  ImageRegionIterator<InternalImageType> it_input(postProcessImage,postProcessImage->GetLargestPossibleRegion());
229 
230  Index<2> index;
231 
232  unsigned int circles=0;
233  bool found;
234 
235  const double nPI = 4.0 * vcl_atan( 1.0 );
236 
237  // Find maxima
238  do
239  {
240  minMaxCalculator->SetImage(postProcessImage);
241  minMaxCalculator->ComputeMaximum();
242  InternalImageType::PixelType max = minMaxCalculator->GetMaximum();
243 
244  found = false;
245  for(it_input.GoToBegin();!it_input.IsAtEnd();++it_input)
246  {
247  if(it_input.Get() == max)
248  {
249  // Create a Line Spatial Object
250  CirclePointer Circle = CircleType::New();
251  Circle->SetId(circles);
252  Circle->SetRadius(m_RadiusImage->GetPixel(it_input.GetIndex()));
253 
254  CircleType::VectorType center;
255  center[0] = it_input.GetIndex()[0];
256  center[1] = it_input.GetIndex()[1];
257  Circle->GetObjectToParentTransform()->SetOffset(center);
258  Circle->ComputeBoundingBox();
259 
260  m_CirclesList.push_back(Circle);
261 
262  // Remove a black disc from the hough space domain
263  for(double angle = 0; angle <= 2*nPI; angle += nPI/1000)
264  {
265  for(double length = 0; length < m_DiscRadiusRatio*Circle->GetRadius()[0];length += 1)
266  {
267  index[0] = (long int)(it_input.GetIndex()[0] + length * vcl_cos(angle));
268  index[1] = (long int)(it_input.GetIndex()[1] + length * vcl_sin(angle));
269  if(postProcessImage->GetLargestPossibleRegion().IsInside( index ))
270  {
271  postProcessImage->SetPixel(index,0);
272  }
273  }
274  }
275  minMaxCalculator->SetImage(postProcessImage);
276  minMaxCalculator->ComputeMaximum();
277  max = minMaxCalculator->GetMaximum();
278 
279  circles++;
280  found = true;
281  if(circles == m_NumberOfCircles) break;
282  }
283  }
284  } while((circles<m_NumberOfCircles) && (found));
285 
286  m_OldModifiedTime = this->GetMTime();
287  m_OldNumberOfCircles = m_CirclesList.size();
288  return m_CirclesList;
289 }
290 
291 
293 template<typename TInputPixelType, typename TOutputPixelType>
294 void
296 ::PrintSelf(std::ostream& os, Indent indent) const
297 {
298  Superclass::PrintSelf(os,indent);
299 
300  os << "Threshold: " << m_Threshold << std::endl;
301  os << "Minimum Radius: " << m_MinimumRadius << std::endl;
302  os << "Maximum Radius: " << m_MaximumRadius << std::endl;
303  os << "Derivative Scale : " << m_SigmaGradient << std::endl;
304  os << "Radius Image Information : " << m_RadiusImage << std::endl;
305  os << "Number Of Circles: " << m_NumberOfCircles << std::endl;
306  os << "Disc Radius: " << m_DiscRadiusRatio << std::endl;
307  os << "Accumulator blur variance: " << m_Variance << std::endl;
308  os << "Sweep angle : " << m_SweepAngle << std::endl;
309 }
310 
311 } // end namespace
312 
313 #endif

Generated at Sat Feb 2 2013 23:42:14 for Orfeo Toolbox with doxygen 1.8.1.1