Orfeo Toolbox  3.16
otbBinaryFunctorNeighborhoodJoinHistogramImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #ifndef __otbBinaryFunctorNeighborhoodJoinHistogramImageFilter_txx
19 #define __otbBinaryFunctorNeighborhoodJoinHistogramImageFilter_txx
20 
22 #include "itkImageRegionIterator.h"
25 #include "itkProgressReporter.h"
26 
27 namespace otb
28 {
29 
33 template <class TInputImage1, class TInputImage2,
34  class TOutputImage, class TFunction>
37 {
38  this->SetNumberOfRequiredInputs(2);
39  m_Radius = 3;
40  m_HistogramSize.Fill(256);
41  m_UsePaddingValue = false;
42  m_UpperBoundIncreaseFactor = 0.001;
43 }
44 
48 template <class TInputImage1, class TInputImage2,
49  class TOutputImage, class TFunction>
50 void
52 ::SetInput1(const TInputImage1 * image1)
53 {
54  // Process object is not const-correct so the const casting is required.
55  this->SetNthInput(0, const_cast<TInputImage1 *>(image1));
56 }
57 
61 template <class TInputImage1, class TInputImage2,
62  class TOutputImage, class TFunction>
63 void
65 ::SetInput2(const TInputImage2 * image2)
66 {
67  // Process object is not const-correct so the const casting is required.
68  this->SetNthInput(1, const_cast<TInputImage2 *>(image2));
69 }
70 
71 template <class TInputImage1, class TInputImage2,
72  class TOutputImage, class TFunction>
73 const TInputImage1 *
76 {
77  if (this->GetNumberOfInputs() < 1)
78  {
79  return 0;
80  }
81  return static_cast<const TInputImage1 *>(this->itk::ProcessObject::GetInput(0));
82 }
83 
84 template <class TInputImage1, class TInputImage2,
85  class TOutputImage, class TFunction>
86 const TInputImage2 *
89 {
90  if (this->GetNumberOfInputs() < 2)
91  {
92  return 0;
93  }
94  return static_cast<const TInputImage2 *>(this->itk::ProcessObject::GetInput(1));
95 }
96 
97 template <class TInputImage1, class TInputImage2,
98  class TOutputImage, class TFunction>
99 void
102 {
103  // call the superclass' implementation of this method
104  Superclass::GenerateInputRequestedRegion();
105 
106  // get pointers to the input and output
107  Input1ImagePointer inputPtr1 =
108  const_cast<TInputImage1 *>(this->GetInput1());
109  Input2ImagePointer inputPtr2 =
110  const_cast<TInputImage2 *>(this->GetInput2());
111  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
112 
113  if (!inputPtr1 || !inputPtr2 || !outputPtr)
114  {
115  return;
116  }
117  // get a copy of the input requested region (should equal the output
118  // requested region)
119  typename TInputImage1::RegionType inputRequestedRegion1, inputRequestedRegion2;
120  inputRequestedRegion1 = inputPtr1->GetRequestedRegion();
121 
122  // pad the input requested region by the operator radius
123  inputRequestedRegion1.PadByRadius(m_Radius);
124  inputRequestedRegion2 = inputRequestedRegion1;
125 
126  // crop the input requested region at the input's largest possible region
127  if (inputRequestedRegion1.Crop(inputPtr1->GetLargestPossibleRegion()))
128  {
129  inputPtr1->SetRequestedRegion(inputRequestedRegion1);
130  }
131  else
132  {
133  // Couldn't crop the region (requested region is outside the largest
134  // possible region). Throw an exception.
135 
136  // store what we tried to request (prior to trying to crop)
137  inputPtr1->SetRequestedRegion(inputRequestedRegion1);
138 
139  // build an exception
140  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
141  std::ostringstream msg;
142  msg << this->GetNameOfClass()
143  << "::GenerateInputRequestedRegion()";
144  e.SetLocation(msg.str().c_str());
145  e.SetDescription("Requested region is (at least partially) outside the largest possible region of image 1.");
146  e.SetDataObject(inputPtr1);
147  throw e;
148  }
149  if (inputRequestedRegion2.Crop(inputPtr2->GetLargestPossibleRegion()))
150  {
151  inputPtr2->SetRequestedRegion(inputRequestedRegion2);
152  }
153  else
154  {
155  // Couldn't crop the region (requested region is outside the largest
156  // possible region). Throw an exception.
157 
158  // store what we tried to request (prior to trying to crop)
159  inputPtr2->SetRequestedRegion(inputRequestedRegion2);
160 
161  // build an exception
162  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
163  std::ostringstream msg;
164  msg << this->GetNameOfClass()
165  << "::GenerateInputRequestedRegion()";
166  e.SetLocation(msg.str().c_str());
167  e.SetDescription("Requested region is (at least partially) outside the largest possible region of image 1.");
168  e.SetDataObject(inputPtr2);
169  throw e;
170  }
171  return;
172 }
173 
177 template <class TInputImage1, class TInputImage2,
178  class TOutputImage, class TFunction>
180 ::HistogramType::Pointer
183 {
184  // Calculate min and max image values in input1 image.
185  Input1ImageConstPointer pInput1Image
186  = dynamic_cast<const TInputImage1*>(ProcessObjectType::GetInput(0));
187 
188  Input1ImagePixelType minInput1, maxInput1;
190  pInput1Image->GetBufferedRegion());
191  fiIt.GoToBegin();
192  minInput1 = fiIt.Value();
193  maxInput1 = fiIt.Value();
194  ++fiIt;
195  while (!fiIt.IsAtEnd())
196  {
197  Input1ImagePixelType value = fiIt.Value();
198 
199  if (value < minInput1)
200  {
201  minInput1 = value;
202  }
203  else if (value > maxInput1)
204  {
205  maxInput1 = value;
206  }
207 
208  ++fiIt;
209  }
210 
211  // Calculate min and max image values in input2 image.
212  Input2ImageConstPointer pInput2Image
213  = dynamic_cast<const TInputImage2*>(ProcessObjectType::GetInput(1));
214  Input2ImagePixelType minInput2, maxInput2;
216  pInput2Image->GetBufferedRegion());
217  miIt.GoToBegin();
218  minInput2 = miIt.Value();
219  maxInput2 = miIt.Value();
220  ++miIt;
221  while (!miIt.IsAtEnd())
222  {
223  Input2ImagePixelType value = miIt.Value();
224 
225  if (value < minInput2)
226  {
227  minInput2 = value;
228  }
229  else if (value > maxInput2)
230  {
231  maxInput2 = value;
232  }
233  ++miIt;
234  }
235 
236  // Initialize the upper and lower bounds of the histogram.
237  m_LowerBound[0] = minInput1;
238  m_LowerBound[1] = minInput2;
239  m_UpperBound[0] =
240  maxInput1 + (maxInput1 - minInput1) * m_UpperBoundIncreaseFactor;
241  m_UpperBound[1] =
242  maxInput2 + (maxInput2 - minInput2) * m_UpperBoundIncreaseFactor;
243 
246 
247  typename Input1ImageType::RegionType input1Region;
248  typename Input1ImageType::RegionType input2Region;
249 
250  input1Region = pInput1Image->GetRequestedRegion();
251  Input1IteratorType ti1(pInput1Image, input1Region);
252 
253  input2Region = pInput2Image->GetRequestedRegion();
254  Input2IteratorType ti2(pInput2Image, input2Region);
255 
256  typename HistogramType::Pointer histogram = HistogramType::New();
257 
258  histogram->Initialize(m_HistogramSize, m_LowerBound, m_UpperBound);
259 
260  ti1.GoToBegin();
261  ti2.GoToBegin();
262  while (!ti1.IsAtEnd() && !ti2.IsAtEnd())
263  {
264 
265  typename HistogramType::MeasurementVectorType sample;
266  sample[0] = ti1.Get();
267  sample[1] = ti2.Get();
268  if (sample[0] != itk::NumericTraits<Input1ImagePixelType>::Zero &&
269  sample[1] != itk::NumericTraits<Input2ImagePixelType>::Zero) histogram->IncreaseFrequency(sample, 1);
270 
271  ++ti1;
272  ++ti2;
273  }
274 
275  return histogram;
276 
277 }
278 
282 template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction>
283 void
285 ::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
286  int threadId)
287 {
288 
289  //this->Initialize();
290 
291  typename HistogramType::Pointer histogram = ComputeHistogram();
292 
293  //m_Functor->SetHistogram(m_Histogram);
294 // unsigned int i;
297 
298 // We use dynamic_cast since inputs are stored as DataObjects. The
299 // ImageToJoinHistogramImageFilter::GetInput(int) always returns a pointer to a
300 // TInputImage1 so it cannot be used for the second input.
301  Input1ImageConstPointer inputPtr1
302  = dynamic_cast<const TInputImage1*>(ProcessObjectType::GetInput(0));
303  Input2ImageConstPointer inputPtr2
304  = dynamic_cast<const TInputImage2*>(ProcessObjectType::GetInput(1));
305  OutputImagePointer outputPtr = this->GetOutput(0);
306 
307  RadiusType1 r1;
308  r1.Fill(m_Radius);
309  NeighborhoodIteratorType1 neighInputIt1;
310 
311  RadiusType2 r2;
312  r2.Fill(m_Radius);
313  NeighborhoodIteratorType2 neighInputIt2;
314 
316 
317  // Find the data-set boundary "faces"
320  faceList1 = bC1(inputPtr1, outputRegionForThread, r1);
321 
324  faceList2 = bC2(inputPtr2, outputRegionForThread, r2);
325 
328 
329  // support progress methods/callbacks
330  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
331 
332  // Process each of the boundary faces. These are N-d regions which border
333  // the edge of the buffer.
334  for (fit1 = faceList1.begin(), fit2 = faceList2.begin();
335  fit1 != faceList1.end() && fit2 != faceList2.end();
336  ++fit1, ++fit2)
337  {
338  neighInputIt1 = itk::ConstNeighborhoodIterator<TInputImage1>(r1, inputPtr1, *fit1);
339  neighInputIt2 = itk::ConstNeighborhoodIterator<TInputImage2>(r1, inputPtr2, *fit2);
340  outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, outputRegionForThread);
341 
342  outputIt = itk::ImageRegionIterator<TOutputImage>(outputPtr, *fit1);
343  neighInputIt1.OverrideBoundaryCondition(&nbc1);
344  neighInputIt1.GoToBegin();
345  neighInputIt2.OverrideBoundaryCondition(&nbc2);
346  neighInputIt2.GoToBegin();
347 
348  while (!outputIt.IsAtEnd())
349  {
350 
351  outputIt.Set(m_Functor(neighInputIt1, neighInputIt2, histogram));
352 
353  ++neighInputIt1;
354  ++neighInputIt2;
355  ++outputIt;
356  progress.CompletedPixel();
357  }
358  }
359 
360 }
361 
362 } // end namespace otb
363 
364 #endif

Generated at Sun Feb 3 2013 00:17:42 for Orfeo Toolbox with doxygen 1.8.1.1