OTB  9.0.0
Orfeo Toolbox
otbContinuousMinimumMaximumImageCalculator.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 
22 #ifndef otbContinuousMinimumMaximumImageCalculator_hxx
23 #define otbContinuousMinimumMaximumImageCalculator_hxx
24 
26 #include "itkImageRegionConstIteratorWithIndex.h"
27 
28 namespace otb
29 {
30 
31 /*
32  * Constructor
33  */
34 template <class TInputImage>
36  :
37  m_Minimum(itk::NumericTraits<PixelType>::max()),
38  m_Maximum(itk::NumericTraits<PixelType>::NonpositiveMin()),
39  m_Image(TInputImage::New()),
40  m_RegionSetByUser(false)
41 {
42  m_IndexOfMinimum.Fill(0);
43  m_IndexOfMaximum.Fill(0);
44 }
45 
46 /*
47  * Compute Min and Max of m_Image
48  */
49 template <class TInputImage>
51 {
52  if (!m_RegionSetByUser)
53  {
54  m_Region = m_Image->GetRequestedRegion();
55  }
56 
57  itk::ImageRegionConstIteratorWithIndex<TInputImage> it(m_Image, m_Region);
58  m_Maximum = itk::NumericTraits<PixelType>::NonpositiveMin();
59  m_Minimum = itk::NumericTraits<PixelType>::max();
60 
61  while (!it.IsAtEnd())
62  {
63  const RealPixelType value = it.Get();
64  if (value > static_cast<RealPixelType>(m_Maximum))
65  {
66  m_Maximum = static_cast<PixelType>(value);
67  m_IndexOfMaximum = it.GetIndex();
68  }
69  if (value < static_cast<RealPixelType>(m_Minimum))
70  {
71  m_Minimum = static_cast<PixelType>(value);
72  m_IndexOfMinimum = it.GetIndex();
73  }
74  ++it;
75  }
76 
77  IndexType indexNeighbor;
78 
79  { // Continuous Minimum calculation
80  // Compute horizontal offset
81  indexNeighbor[0] = m_IndexOfMinimum[0] - 1;
82  indexNeighbor[1] = m_IndexOfMinimum[1];
83  it.SetIndex(indexNeighbor);
84  const RealPixelType leftValue = it.Get();
85  indexNeighbor[0] = m_IndexOfMinimum[0] + 1;
86  indexNeighbor[1] = m_IndexOfMinimum[1];
87  it.SetIndex(indexNeighbor);
88  const RealPixelType rightValue = it.Get();
89 
90  double hOffset = -(rightValue - leftValue) / (2 * (rightValue + leftValue - 2 * m_Minimum));
91 
92  // Compute vertical offset
93  indexNeighbor[0] = m_IndexOfMinimum[0];
94  indexNeighbor[1] = m_IndexOfMinimum[1] - 1;
95  it.SetIndex(indexNeighbor);
96  const RealPixelType topValue = it.Get();
97  indexNeighbor[0] = m_IndexOfMinimum[0];
98  indexNeighbor[1] = m_IndexOfMinimum[1] + 1;
99  it.SetIndex(indexNeighbor);
100  const RealPixelType bottomValue = it.Get();
101 
102  double vOffset = -(bottomValue - topValue) / (2 * (bottomValue + topValue - 2 * m_Minimum));
103 
104  m_ContinuousIndexOfMinimum[0] = m_IndexOfMinimum[0] + hOffset;
105  m_ContinuousIndexOfMinimum[1] = m_IndexOfMinimum[1] + vOffset;
106  }
107 
108  { // Continuous Maximum calculation
109  // Compute horizontal offset
110  indexNeighbor[0] = m_IndexOfMaximum[0] - 1;
111  indexNeighbor[1] = m_IndexOfMaximum[1];
112  it.SetIndex(indexNeighbor);
113  const RealPixelType leftValue = it.Get();
114  indexNeighbor[0] = m_IndexOfMaximum[0] + 1;
115  indexNeighbor[1] = m_IndexOfMaximum[1];
116  it.SetIndex(indexNeighbor);
117  const RealPixelType rightValue = it.Get();
118 
119  double hOffset = -(rightValue - leftValue) / (2 * (rightValue + leftValue - 2 * m_Maximum));
120 
121  // Compute vertical offset
122  indexNeighbor[0] = m_IndexOfMaximum[0];
123  indexNeighbor[1] = m_IndexOfMaximum[1] - 1;
124  it.SetIndex(indexNeighbor);
125  const RealPixelType topValue = it.Get();
126  indexNeighbor[0] = m_IndexOfMaximum[0];
127  indexNeighbor[1] = m_IndexOfMaximum[1] + 1;
128  it.SetIndex(indexNeighbor);
129  const RealPixelType bottomValue = it.Get();
130 
131  double vOffset = -(bottomValue - topValue) / (2 * (bottomValue + topValue - 2 * m_Maximum));
132 
133  m_ContinuousIndexOfMaximum[0] = m_IndexOfMaximum[0] + hOffset;
134  m_ContinuousIndexOfMaximum[1] = m_IndexOfMaximum[1] + vOffset;
135  }
136 }
137 
138 /*
139  * Compute the minimum intensity value of the image
140  */
141 template <class TInputImage>
143 {
144  if (!m_RegionSetByUser)
145  {
146  m_Region = m_Image->GetRequestedRegion();
147  }
148  itk::ImageRegionConstIteratorWithIndex<TInputImage> it(m_Image, m_Region);
149  m_Minimum = itk::NumericTraits<PixelType>::max();
150 
151  while (!it.IsAtEnd())
152  {
153  const RealPixelType value = it.Get();
154  if (value < static_cast<RealPixelType>(m_Minimum))
155  {
156  m_Minimum = static_cast<PixelType>(value);
157  m_IndexOfMinimum = it.GetIndex();
158  }
159  ++it;
160  }
161 
162  IndexType indexNeighbor;
163 
164  // Compute horizontal offset
165  indexNeighbor[0] = m_IndexOfMinimum[0] - 1;
166  indexNeighbor[1] = m_IndexOfMinimum[1];
167  it.SetIndex(indexNeighbor);
168  const RealPixelType leftValue = it.Get();
169  indexNeighbor[0] = m_IndexOfMinimum[0] + 1;
170  indexNeighbor[1] = m_IndexOfMinimum[1];
171  it.SetIndex(indexNeighbor);
172  const RealPixelType rightValue = it.Get();
173 
174  double hOffset = -(rightValue - leftValue) / (2 * (rightValue + leftValue - 2 * m_Minimum));
175 
176  // Compute vertical offset
177  indexNeighbor[0] = m_IndexOfMinimum[0];
178  indexNeighbor[1] = m_IndexOfMinimum[1] - 1;
179  it.SetIndex(indexNeighbor);
180  const RealPixelType topValue = it.Get();
181  indexNeighbor[0] = m_IndexOfMinimum[0];
182  indexNeighbor[1] = m_IndexOfMinimum[1] + 1;
183  it.SetIndex(indexNeighbor);
184  const RealPixelType bottomValue = it.Get();
185 
186  double vOffset = -(bottomValue - topValue) / (2 * (bottomValue + topValue - 2 * m_Minimum));
187 
188  m_ContinuousIndexOfMinimum[0] = m_IndexOfMinimum[0] + hOffset;
189  m_ContinuousIndexOfMinimum[1] = m_IndexOfMinimum[1] + vOffset;
190 }
191 
192 /*
193  * Compute the maximum intensity value of the image
194  */
195 template <class TInputImage>
197 {
198  if (!m_RegionSetByUser)
199  {
200  m_Region = m_Image->GetRequestedRegion();
201  }
202  itk::ImageRegionConstIteratorWithIndex<TInputImage> it(m_Image, m_Region);
203  m_Maximum = itk::NumericTraits<PixelType>::NonpositiveMin();
204 
205  while (!it.IsAtEnd())
206  {
207  const RealPixelType value = it.Get();
208  if (value > static_cast<RealPixelType>(m_Maximum))
209  {
210  m_Maximum = static_cast<PixelType>(value);
211  m_IndexOfMaximum = it.GetIndex();
212  }
213  ++it;
214  }
215 
216  // Solve equations a, b, c
217  // y0 = a*x0^2 + b*x0 +c
218  // y1 = a*x1^2 + b*x1 +c
219  // y2 = a*x2^2 + b*x2 +c
220  //
221  // y0 = a - b +c
222  // y1 = c
223  // y2 = a + b +c
224  //
225  //
226  // Max is at -b/2a
227  // -(y2-y0)/(2*(y0+y2-2y1))
228  IndexType indexNeighbor;
229 
230  // Compute horizontal offset
231  indexNeighbor[0] = m_IndexOfMaximum[0] - 1;
232  indexNeighbor[1] = m_IndexOfMaximum[1];
233  it.SetIndex(indexNeighbor);
234  const RealPixelType leftValue = it.Get();
235  indexNeighbor[0] = m_IndexOfMaximum[0] + 1;
236  indexNeighbor[1] = m_IndexOfMaximum[1];
237  it.SetIndex(indexNeighbor);
238  const RealPixelType rightValue = it.Get();
239 
240  double hOffset = -(rightValue - leftValue) / (2 * (rightValue + leftValue - 2 * m_Maximum));
241 
242  // Compute vertical offset
243  indexNeighbor[0] = m_IndexOfMaximum[0];
244  indexNeighbor[1] = m_IndexOfMaximum[1] - 1;
245  it.SetIndex(indexNeighbor);
246  const RealPixelType topValue = it.Get();
247  indexNeighbor[0] = m_IndexOfMaximum[0];
248  indexNeighbor[1] = m_IndexOfMaximum[1] + 1;
249  it.SetIndex(indexNeighbor);
250  const RealPixelType bottomValue = it.Get();
251 
252  double vOffset = -(bottomValue - topValue) / (2 * (bottomValue + topValue - 2 * m_Maximum));
253 
254  m_ContinuousIndexOfMaximum[0] = m_IndexOfMaximum[0] + hOffset;
255  m_ContinuousIndexOfMaximum[1] = m_IndexOfMaximum[1] + vOffset;
256 }
257 
258 template <class TInputImage>
260 {
261  m_Region = region;
262  m_RegionSetByUser = true;
263 }
264 
265 template <class TInputImage>
266 void ContinuousMinimumMaximumImageCalculator<TInputImage>::PrintSelf(std::ostream& os, itk::Indent indent) const
267 {
268  Superclass::PrintSelf(os, indent);
269 
270  os << indent << "Minimum: " << static_cast<typename itk::NumericTraits<PixelType>::PrintType>(m_Minimum) << std::endl;
271  os << indent << "Maximum: " << static_cast<typename itk::NumericTraits<PixelType>::PrintType>(m_Maximum) << std::endl;
272  os << indent << "Index of Minimum: " << m_IndexOfMinimum << std::endl;
273  os << indent << "Index of Maximum: " << m_IndexOfMaximum << std::endl;
274  os << indent << "Continuous Index of Minimum: " << m_ContinuousIndexOfMinimum << std::endl;
275  os << indent << "Continuous Index of Maximum: " << m_ContinuousIndexOfMaximum << std::endl;
276 
277  os << indent << "Image: " << std::endl;
278  m_Image->Print(os, indent.GetNextIndent());
279  os << indent << "Region: " << std::endl;
280  m_Region.Print(os, indent.GetNextIndent());
281  os << indent << "Region set by User: " << m_RegionSetByUser << std::endl;
282 }
283 
284 } // end namespace otb
285 
286 #endif
otb::ContinuousMinimumMaximumImageCalculator::RealPixelType
itk::NumericTraits< PixelType >::RealType RealPixelType
Definition: otbContinuousMinimumMaximumImageCalculator.h:93
otb::ContinuousMinimumMaximumImageCalculator::ComputeMinimum
void ComputeMinimum(void)
Definition: otbContinuousMinimumMaximumImageCalculator.hxx:142
otb::ContinuousMinimumMaximumImageCalculator::m_IndexOfMaximum
IndexType m_IndexOfMaximum
Definition: otbContinuousMinimumMaximumImageCalculator.h:148
otb::ContinuousMinimumMaximumImageCalculator::ComputeMaximum
void ComputeMaximum(void)
Definition: otbContinuousMinimumMaximumImageCalculator.hxx:196
otb::ContinuousMinimumMaximumImageCalculator::Compute
void Compute(void)
Definition: otbContinuousMinimumMaximumImageCalculator.hxx:50
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::ContinuousMinimumMaximumImageCalculator::SetRegion
void SetRegion(const RegionType &region)
Definition: otbContinuousMinimumMaximumImageCalculator.hxx:259
otbContinuousMinimumMaximumImageCalculator.h
otb::ContinuousMinimumMaximumImageCalculator::ContinuousMinimumMaximumImageCalculator
ContinuousMinimumMaximumImageCalculator()
Definition: otbContinuousMinimumMaximumImageCalculator.hxx:35
otb::ContinuousMinimumMaximumImageCalculator::m_IndexOfMinimum
IndexType m_IndexOfMinimum
Definition: otbContinuousMinimumMaximumImageCalculator.h:147
otb::ContinuousMinimumMaximumImageCalculator::PixelType
TInputImage::PixelType PixelType
Definition: otbContinuousMinimumMaximumImageCalculator.h:90
otb::ContinuousMinimumMaximumImageCalculator::IndexType
TInputImage::IndexType IndexType
Definition: otbContinuousMinimumMaximumImageCalculator.h:96
itk
Definition: otbNoDataHelper.h:31
otb::ContinuousMinimumMaximumImageCalculator::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbContinuousMinimumMaximumImageCalculator.hxx:266
otb::ContinuousMinimumMaximumImageCalculator::RegionType
TInputImage::RegionType RegionType
Definition: otbContinuousMinimumMaximumImageCalculator.h:102