OTB  9.0.0
Orfeo Toolbox
otbImageToEdgePathFilter.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 otbImageToEdgePathFilter_hxx
22 #define otbImageToEdgePathFilter_hxx
23 
25 #include "otbMacro.h"
26 #include "itkConstantPadImageFilter.h"
27 #include "itkConstShapedNeighborhoodIterator.h"
28 #include "itkImageRegionConstIteratorWithIndex.h"
29 
30 namespace otb
31 {
32 /*
33  * Constructor.
34  */
35 template <class TInputImage, class TOutputPath>
37 {
38  m_ForegroundValue = PixelType(255);
39 }
43 template <class TInputImage, class TOutputPath>
45 {
46 
47  const InputImageType* inputImage = this->GetInput();
48  OutputPathType* outputPath = this->GetOutput();
49 
50  otbMsgDebugMacro(<< "Foreground value : " << m_ForegroundValue);
51 
52  PixelType initPadConstant(0);
53  if (initPadConstant == m_ForegroundValue)
54  {
55  initPadConstant = 1;
56  }
57 
58  typedef itk::ConstantPadImageFilter<InputImageType, InputImageType> PadFilterType;
59  typedef itk::ConstShapedNeighborhoodIterator<InputImageType> IteratorType;
60  typedef itk::ImageRegionConstIteratorWithIndex<InputImageType> LinearIteratorType;
61 
62  // Padding to deal with near the border objects.
63  typename PadFilterType::Pointer pad = PadFilterType::New();
64  pad->SetInput(inputImage);
65  pad->SetConstant(initPadConstant);
66  SizeType padSize;
67  padSize[0] = 1;
68  padSize[1] = 1;
69  pad->SetPadUpperBound(padSize);
70  pad->SetPadLowerBound(padSize);
71  pad->Update();
72  // Iterate on the image to get a starting point
73  LinearIteratorType linIter(pad->GetOutput(), pad->GetOutput()->GetLargestPossibleRegion());
74  linIter.GoToBegin();
75  bool flag = true;
76  while (flag && !linIter.IsAtEnd())
77  {
78  if (linIter.Get() == m_ForegroundValue)
79  {
80  flag = false;
81  }
82  else
83  {
84  ++linIter;
85  }
86  }
87  typename InputImageType::IndexType start = linIter.GetIndex();
88  // outputPath->AddVertex(start);
89 
90  // Neighborhood definition
91  typename IteratorType::RadiusType radius;
92  radius.Fill(1);
93  IteratorType it(radius, pad->GetOutput(), pad->GetOutput()->GetLargestPossibleRegion());
94  const typename IteratorType::OffsetType LEFT = {{-1, 0}};
95  const typename IteratorType::OffsetType RIGHT = {{1, 0}};
96  const typename IteratorType::OffsetType UP = {{0, -1}};
97  const typename IteratorType::OffsetType DOWN = {{0, 1}};
98  const typename IteratorType::OffsetType LEFTUP = {{-1, -1}};
99  const typename IteratorType::OffsetType RIGHTDOWN = {{1, 1}};
100  const typename IteratorType::OffsetType RIGHTUP = {{1, -1}};
101  const typename IteratorType::OffsetType LEFTDOWN = {{-1, 1}};
102  const typename IteratorType::OffsetType CENTER = {{0, 0}};
103  it.ClearActiveList();
104  it.ActivateOffset(LEFT);
105  it.ActivateOffset(RIGHT);
106  it.ActivateOffset(UP);
107  it.ActivateOffset(DOWN);
108  it.ActivateOffset(CENTER);
109  it.ActivateOffset(RIGHTUP);
110  it.ActivateOffset(RIGHTDOWN);
111  it.ActivateOffset(LEFTUP);
112  it.ActivateOffset(LEFTDOWN);
113  // The rotation vector allows getting the clock-wise next pixel
114  std::vector<typename IteratorType::OffsetType> rotation;
115  rotation.push_back(RIGHT);
116  rotation.push_back(RIGHTDOWN);
117  rotation.push_back(DOWN);
118  rotation.push_back(LEFTDOWN);
119  rotation.push_back(LEFT);
120  rotation.push_back(LEFTUP);
121  rotation.push_back(UP);
122  rotation.push_back(RIGHTUP);
123  // Set up the iterator
124  it.SetLocation(start);
125 
126  ContinuousIndexType newVertex = it.GetIndex(CENTER);
127  if (it.GetPixel(RIGHT) == m_ForegroundValue)
128  newVertex[0] -= 0.5;
129  if (it.GetPixel(LEFT) == m_ForegroundValue)
130  newVertex[0] += 0.5;
131  if (it.GetPixel(UP) == m_ForegroundValue)
132  newVertex[1] += 0.5;
133  if (it.GetPixel(DOWN) == m_ForegroundValue)
134  newVertex[1] -= 0.5;
135  outputPath->AddVertex(newVertex);
136 
137  otbMsgDebugMacro(<< "START: " << start);
138  // stopping flag
139  flag = true;
140  int nbMove = 0;
141  // nexstart gives a clue of where to begin searching in next step of the search
142  int nextStart = 0;
143  // While the search has not eended
144  while (flag)
145  {
146  // move is used to walk the neighnorhood clock-wise
147  int move = nextStart;
148  // edgeFound indicate that the edge has been found.
149  bool EdgeFound = false;
150  // LastWasPositive indicate whether the previous pixel belong to the object or not
151  bool LastWasPositive(false);
152  // While unexplored pixels remain and no edge was found
153  while ((move < nextStart + 8) && (!EdgeFound))
154  {
155  // otbMsgDevMacro(<<"SEARCH: "<<move%8<<" "<<it.GetPixel(rotation[move%8])<<" LAST: "<<LastWasPositive);
156  // If last pixel was not in the object and the current is, we have found the edge
157  if ((!LastWasPositive) && (it.GetPixel(rotation[move % 8]) == m_ForegroundValue))
158  {
159  EdgeFound = true;
160  }
161  else
162  {
163  // Else goes on
164  LastWasPositive = (it.GetPixel(rotation[move % 8]) == m_ForegroundValue);
165  move++;
166  }
167  }
168  // Once the search has been completed, if an edge pixel was found
169  if (EdgeFound)
170  {
171  // Update the output path
172  it += rotation[move % 8];
173  nextStart = (move + 5) % 8;
174  newVertex = it.GetIndex(CENTER);
175  if (it.GetPixel(RIGHT) == m_ForegroundValue)
176  newVertex[0] -= 0.5;
177  if (it.GetPixel(LEFT) == m_ForegroundValue)
178  newVertex[0] += 0.5;
179  if (it.GetPixel(UP) == m_ForegroundValue)
180  newVertex[1] += 0.5;
181  if (it.GetPixel(DOWN) == m_ForegroundValue)
182  newVertex[1] -= 0.5;
183  outputPath->AddVertex(newVertex);
184  otbMsgDebugMacro(<< newVertex);
185  // If we came back to our start point after a sufficient number of moves
186  if ((it.GetIndex(CENTER) == start) && (nbMove >= 2))
187  {
188  // search end
189  flag = false;
190  }
191  else
192  {
193  // else
194  for (int i = 0; i < 8; ++i)
195  {
196  // If we came back near our starting pointer after a sufficient number of moves
197  if ((it.GetIndex(rotation[i]) == start) && (nbMove >= 2))
198  {
199  // search end
200  flag = false;
201  }
202  }
203  }
204  }
205  // else
206  else
207  {
208  // search ended, no pixel can be added to the edge path.
209  flag = false;
210  }
211  nbMove++;
212  }
213 }
214 template <class TInputImage, class TOutputPath>
215 void ImageToEdgePathFilter<TInputImage, TOutputPath>::PrintSelf(std::ostream& os, itk::Indent indent) const
216 {
217  Superclass::PrintSelf(os, indent);
218  os << "Foreground value : " << m_ForegroundValue << std::endl;
219 }
220 } // end namespace otb
221 
222 #endif
otbImageToEdgePathFilter.h
otb::ImageToEdgePathFilter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbImageToEdgePathFilter.hxx:215
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ImageToEdgePathFilter::OutputPathType
Superclass::OutputPathType OutputPathType
Definition: otbImageToEdgePathFilter.h:75
otb::ImageToEdgePathFilter::GenerateData
void GenerateData() override
Definition: otbImageToEdgePathFilter.hxx:44
otbMacro.h
otb::ImageToEdgePathFilter::ImageToEdgePathFilter
ImageToEdgePathFilter()
Definition: otbImageToEdgePathFilter.hxx:36
otb::ImageToEdgePathFilter::InputImageType
Superclass::InputImageType InputImageType
Template parameters typedef.
Definition: otbImageToEdgePathFilter.h:70
otb::ImageToEdgePathFilter::PixelType
InputImageType::PixelType PixelType
Definition: otbImageToEdgePathFilter.h:79
otbMsgDebugMacro
#define otbMsgDebugMacro(x)
Definition: otbMacro.h:62
otb::ImageToEdgePathFilter::SizeType
InputImageType::SizeType SizeType
Definition: otbImageToEdgePathFilter.h:80
otb::ImageToEdgePathFilter::ContinuousIndexType
OutputPathType::ContinuousIndexType ContinuousIndexType
Definition: otbImageToEdgePathFilter.h:77