OTB  9.0.0
Orfeo Toolbox
otbTouziEdgeDetectorImageFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbTouziEdgeDetectorImageFilter_hxx
22 #define otbTouziEdgeDetectorImageFilter_hxx
23 
25 
26 #include "itkDataObject.h"
27 #include "itkConstNeighborhoodIterator.h"
28 #include "itkNeighborhoodInnerProduct.h"
29 #include "itkImageRegionIterator.h"
30 #include "itkNeighborhoodAlgorithm.h"
31 #include "itkProgressReporter.h"
32 #include "otbMacro.h"
33 #include "otbMath.h"
34 
35 namespace otb
36 {
37 
41 template <class TInputImage, class TOutputImage, class TOutputImageDirection>
43 {
44  m_Radius.Fill(1);
45 }
46 
47 template <class TInputImage, class TOutputImage, class TOutputImageDirection>
49 {
50  // call the superclass' implementation of this method
51  Superclass::GenerateInputRequestedRegion();
52 
53  // get pointers to the input and output
54  typename Superclass::InputImagePointer inputPtr = const_cast<TInputImage*>(this->GetInput());
55  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
56 
57  if (!inputPtr || !outputPtr)
58  {
59  return;
60  }
61 
62  // get a copy of the input requested region (should equal the output
63  // requested region)
64  typename TInputImage::RegionType inputRequestedRegion;
65  inputRequestedRegion = inputPtr->GetRequestedRegion();
66 
67  // pad the input requested region by the operator radius
68  inputRequestedRegion.PadByRadius(m_Radius);
69 
70  // crop the input requested region at the input's largest possible region
71  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
72  {
73  inputPtr->SetRequestedRegion(inputRequestedRegion);
74  return;
75  }
76  else
77  {
78  // Couldn't crop the region (requested region is outside the largest
79  // possible region). Throw an exception.
80 
81  // store what we tried to request (prior to trying to crop)
82  inputPtr->SetRequestedRegion(inputRequestedRegion);
83 
84  // build an exception
85  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
86  std::ostringstream msg;
87  msg << static_cast<const char*>(this->GetNameOfClass()) << "::GenerateInputRequestedRegion()";
88  e.SetLocation(msg.str());
89  e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
90  e.SetDataObject(inputPtr);
91  throw e;
92  }
93 }
94 
100 template <class TInputImage, class TOutputImage, class TOutputImageDirection>
102 {
103 
104  typename OutputImageDirectionType::RegionType region;
105  typename OutputImageType::Pointer output = this->GetOutput();
106 
107  OutputImageDirectionType* direction = this->GetOutputDirection();
108 
109  region.SetSize(output->GetRequestedRegion().GetSize());
110  region.SetIndex(output->GetRequestedRegion().GetIndex());
111  direction->SetRegions(region);
112  direction->SetOrigin(output->GetOrigin());
113  direction->SetSignedSpacing(output->GetSignedSpacing());
114  direction->Allocate();
115 }
116 
117 template <class TInputImage, class TOutputImage, class TOutputImageDirection>
119  itk::ThreadIdType threadId)
120 {
121  unsigned int i;
122  itk::ZeroFluxNeumannBoundaryCondition<InputImageType> nbc;
123  itk::ConstNeighborhoodIterator<InputImageType> bit;
124  itk::ImageRegionIterator<OutputImageType> it;
125  itk::ImageRegionIterator<OutputImageType> it_dir;
126 
127  // Allocate output
128  typename OutputImageType::Pointer output = this->GetOutput();
129  typename InputImageType::ConstPointer input = this->GetInput();
130  typename OutputImageDirectionType::Pointer outputDir = this->GetOutputDirection();
131 
132  // Find the data-set boundary "faces"
133  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType faceList;
134  typename itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType>::FaceListType::iterator fit;
135 
136  itk::NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<InputImageType> bC;
137  faceList = bC(input, outputRegionForThread, m_Radius);
138 
139  // support progress methods/callbacks
140  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
141 
142  typename TInputImage::IndexType bitIndex;
143 
144  // Initializations
145  // ---------------
146  // Number of direction
147  const int NB_DIR = 4;
148  // Number of region of the filter
149  const int NB_REGION = 2;
150  // Definition of the 4 directions
151  double Theta[NB_DIR];
152 
153  Theta[0] = 0.;
154  Theta[1] = CONST_PI_4;
155  Theta[2] = CONST_PI_2;
156  Theta[3] = 3 * CONST_PI / 4.;
157 
158  // contains for the 4 directions the sum of the pixels belonging to each region
159  double Sum[NB_DIR][NB_REGION];
160  // Mean of region 1
161  double M1;
162  // Mean of region 2
163  double M2;
164  // Result of the filter for each direction
165  double R_theta[NB_DIR];
166  double Sum_R_theta = 0.;
167  // Intensity of the contour
168  double R_contour;
169  // Direction of the contour
170  double Dir_contour = 0.;
171  // sign of the contour
172  int sign;
173 
174  // Pixel location in the input image
175  int x;
176  int y;
177  // Location of the central pixel in the input image
178  int xc;
179  int yc;
180 
181  int cpt = 0;
182 
183  // Process each of the boundary faces. These are N-d regions which border
184  // the edge of the buffer.
185  for (fit = faceList.begin(); fit != faceList.end(); ++fit)
186  {
187 
188  cpt += 1;
189 
190  bit = itk::ConstNeighborhoodIterator<InputImageType>(m_Radius, input, *fit);
191  unsigned int neighborhoodSize = bit.Size();
192 
193  it = itk::ImageRegionIterator<OutputImageType>(output, *fit);
194  it_dir = itk::ImageRegionIterator<OutputImageDirectionType>(outputDir, *fit);
195 
196  bit.OverrideBoundaryCondition(&nbc);
197  bit.GoToBegin();
198 
199  while (!bit.IsAtEnd())
200  {
201 
202  // Location of the pixel central
203  bitIndex = bit.GetIndex();
204 
205  xc = bitIndex[0];
206  yc = bitIndex[1];
207 
208  // Initializations
209  for (int dir = 0; dir < NB_DIR; ++dir)
210  {
211  for (int m = 0; m < NB_REGION; m++)
212  Sum[dir][m] = 0.;
213  }
214 
215  R_contour = -1;
216  Dir_contour = 0.;
217  Sum_R_theta = 0.;
218 
219  // Loop on pixels of the filter
220  for (i = 0; i < neighborhoodSize; ++i)
221  {
222 
223  bitIndex = bit.GetIndex(i);
224  x = bitIndex[0];
225  y = bitIndex[1];
226 
227  // We determine for each direction with which region the pixel belongs.
228 
229  // Horizontal direction
230  if (y < yc)
231  Sum[0][0] += static_cast<double>(bit.GetPixel(i));
232  else if (y > yc)
233  Sum[0][1] += static_cast<double>(bit.GetPixel(i));
234 
235  // Diagonal direction 1
236  if ((y - yc) < (x - xc))
237  Sum[1][0] += static_cast<double>(bit.GetPixel(i));
238  else if ((y - yc) > (x - xc))
239  Sum[1][1] += static_cast<double>(bit.GetPixel(i));
240 
241  // Vertical direction
242  if (x > xc)
243  Sum[2][0] += static_cast<double>(bit.GetPixel(i));
244  else if (x < xc)
245  Sum[2][1] += static_cast<double>(bit.GetPixel(i));
246 
247  // Diagonal direction 2
248  if ((y - yc) > -(x - xc))
249  Sum[3][0] += static_cast<double>(bit.GetPixel(i));
250  else if ((y - yc) < -(x - xc))
251  Sum[3][1] += static_cast<double>(bit.GetPixel(i));
252 
253  } // end of the loop on pixels of the filter
254 
255  // Loop on the 4 directions
256  for (int dir = 0; dir < NB_DIR; ++dir)
257  {
258  // Calculation of the mean of the 2 regions
259  M1 = Sum[dir][0] / static_cast<double>(m_Radius[0] * (2 * m_Radius[0] + 1));
260  M2 = Sum[dir][1] / static_cast<double>(m_Radius[0] * (2 * m_Radius[0] + 1));
261 
262  // Calculation of the intensity of the contour
263  if ((M1 != 0) && (M2 != 0))
264  R_theta[dir] = static_cast<double>(1 - std::min((M1 / M2), (M2 / M1)));
265  else
266  R_theta[dir] = 0.;
267 
268  // Determination of the maximum intensity of the contour
269  R_contour = static_cast<double>(std::max(R_contour, R_theta[dir]));
270 
271  // Determination of the sign of contour
272  if (M2 > M1)
273  sign = +1;
274  else
275  sign = -1;
276 
277  Dir_contour += sign * Theta[dir] * R_theta[dir];
278  Sum_R_theta += R_theta[dir];
279 
280  } // end of the loop on the directions
281 
282  // Assignment of this value to the output pixel
283  it.Set(static_cast<OutputPixelType>(R_contour));
284 
285  // Determination of the direction of the contour
286  if (Sum_R_theta != 0.)
287  Dir_contour = Dir_contour / Sum_R_theta;
288 
289  // Assignment of this value to the "outputdir" pixel
290  it_dir.Set(static_cast<OutputPixelDirectionType>(Dir_contour));
291 
292  ++bit;
293  ++it;
294  ++it_dir;
295  progress.CompletedPixel();
296  }
297  }
298 }
299 
303 template <class TInputImage, class TOutputImage, class TOutputImageDirection>
305 {
306  Superclass::PrintSelf(os, indent);
307  os << indent << "Radius: " << m_Radius << std::endl;
308 }
310 
311 } // end namespace otb
312 
313 #endif
otb::TouziEdgeDetectorImageFilter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbTouziEdgeDetectorImageFilter.hxx:304
otb::CONST_PI
constexpr double CONST_PI
Definition: otbMath.h:49
otbMath.h
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::TouziEdgeDetectorImageFilter::OutputImageDirectionType
Superclass::OutputImageDirectionType OutputImageDirectionType
Definition: otbTouziEdgeDetectorImageFilter.h:84
otb::CONST_PI_4
constexpr double CONST_PI_4
Definition: otbMath.h:51
otb::TouziEdgeDetectorImageFilter::OutputPixelType
OutputImageType::PixelType OutputPixelType
Definition: otbTouziEdgeDetectorImageFilter.h:88
otbMacro.h
otb::TouziEdgeDetectorImageFilter::OutputPixelDirectionType
OutputImageDirectionType::PixelType OutputPixelDirectionType
Definition: otbTouziEdgeDetectorImageFilter.h:89
otb::CONST_PI_2
constexpr double CONST_PI_2
Definition: otbMath.h:50
otb::TouziEdgeDetectorImageFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion() override
Definition: otbTouziEdgeDetectorImageFilter.hxx:48
otb::ImageToModulusAndDirectionImageFilter::OutputImagePointer
OutputImageType::Pointer OutputImagePointer
Definition: otbImageToModulusAndDirectionImageFilter.h:69
otb::TouziEdgeDetectorImageFilter::BeforeThreadedGenerateData
void BeforeThreadedGenerateData() override
Definition: otbTouziEdgeDetectorImageFilter.hxx:101
otb::ImageToModulusAndDirectionImageFilter::InputImagePointer
InputImageType::Pointer InputImagePointer
Definition: otbImageToModulusAndDirectionImageFilter.h:66
otb::TouziEdgeDetectorImageFilter::ThreadedGenerateData
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbTouziEdgeDetectorImageFilter.hxx:118
otb::TouziEdgeDetectorImageFilter::TouziEdgeDetectorImageFilter
TouziEdgeDetectorImageFilter()
Definition: otbTouziEdgeDetectorImageFilter.hxx:42
otb::TouziEdgeDetectorImageFilter::OutputImageRegionType
OutputImageType::RegionType OutputImageRegionType
Definition: otbTouziEdgeDetectorImageFilter.h:87
otbTouziEdgeDetectorImageFilter.h