OTB  6.7.0
Orfeo Toolbox
otbListSampleToHistogramListGenerator.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2019 Centre National d'Etudes Spatiales (CNES)
4  *
5  * This file is part of Orfeo Toolbox
6  *
7  * https://www.orfeo-toolbox.org/
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef otbListSampleToHistogramListGenerator_hxx
23 #define otbListSampleToHistogramListGenerator_hxx
24 
26 #include "itkArray.h"
27 #include "otbMacro.h"
28 
29 namespace otb
30 {
31 
32 template<class TListSample,
33  class THistogramMeasurement,
34  class TFrequencyContainer>
35 ListSampleToHistogramListGenerator<TListSample,
36  THistogramMeasurement,
37  TFrequencyContainer>
39  : m_Size(10),
40  m_MarginalScale(100),
41  m_AutoMinMax(true),
42  m_NoDataFlag(false),
43  m_NoDataValue(itk::NumericTraits<THistogramMeasurement>::Zero)
44 {
45  m_Size.Fill(255);
46 
49 
50  this->itk::ProcessObject::SetNthOutput(0, this->MakeOutput(0).GetPointer());
51 }
52 
53 // Set the input ListSample
54 template<class TListSample, class THistogramMeasurement, class TFrequencyContainer>
55 void
58 {
59  // Process object is not const-correct so the const_cast is required here
61  const_cast<ListSampleType*>(inputlist));
62 
63 }
64 
65 // Get the input ListSample
66 template<class TListSample, class THistogramMeasurement, class TFrequencyContainer>
68 ::ListSampleType*
71 {
72  if (this->GetNumberOfInputs() < 1)
73  {
74  return nullptr;
75  }
76  return static_cast<const ListSampleType* >
77  (this->itk::ProcessObject::GetInput(0) );
78 }
79 
80 // Get the output
81 template<class TListSample, class THistogramMeasurement, class TFrequencyContainer>
83 ::HistogramListType*
86 {
87  return dynamic_cast<HistogramListType*>(this->itk::ProcessObject::GetOutput(0));
88 }
89 
90 // MakeOutput implementation
91 template<class TListSample, class THistogramMeasurement, class TFrequencyContainer>
93 ::DataObjectPointer
96 {
97  DataObjectPointer output;
98  output = static_cast<itk::DataObject*>(HistogramListType::New().GetPointer());
99  return output;
100 }
101 
102 // GenerateData
103 template<class TListSample,
104  class THistogramMeasurement,
105  class TFrequencyContainer>
106 void
108  THistogramMeasurement,
109  TFrequencyContainer>
110 ::GenerateData()
111 {
112  otbMsgDebugMacro(<< "ListSampleToHistogramListGenerator::GenerateData(): Entering");
113 
114  // Get the input ListSample
115  const ListSampleType* inputList = this->GetListSample();
116 
117  // Get a pointer on the output
118  typename HistogramListType::Pointer histogramList = const_cast<HistogramListType*>(this->GetOutput());
119 
120  if (!m_AutoMinMax)
121  {
122  if (m_HistogramMin.GetSize() != inputList->GetMeasurementVectorSize())
123  {
124  itkExceptionMacro("Sample list measurement vectors and histogram min have different dimensions !");
125  }
126  if (m_HistogramMax.GetSize() != inputList->GetMeasurementVectorSize())
127  {
128  itkExceptionMacro("Sample list measurement vectors and histogram max have different dimensions !");
129  }
130  }
131  typename TListSample::MeasurementVectorType lower(inputList->GetMeasurementVectorSize());
132  typename TListSample::MeasurementVectorType upper(inputList->GetMeasurementVectorSize());
133 
134  typename TListSample::MeasurementVectorType h_upper(inputList->GetMeasurementVectorSize());
135  typename TListSample::MeasurementVectorType h_lower(inputList->GetMeasurementVectorSize());
136 
137  bool clipBinsAtEnds = true;
138 
139  // must test for the list size to avoid making FindSampleBound() segfault.
140  // Also, the min and max can't be found automatically in that case. We can
141  // only return an empty histogram
142  if (m_AutoMinMax && inputList->Size() != 0)
143  {
144  itk::Statistics::Algorithm::FindSampleBound<ListSampleType>(inputList, inputList->Begin(),
145  inputList->End(), lower, upper);
146  float margin;
147 
148  for (unsigned int i = 0; i < inputList->GetMeasurementVectorSize(); ++i)
149  {
151  {
152  margin =
153  ((THistogramMeasurement) (upper[i] - lower[i]) /
154  (THistogramMeasurement) m_Size[0]) /
155  (THistogramMeasurement) m_MarginalScale;
156  h_upper[i] = (THistogramMeasurement) (upper[i] + margin);
157  if (h_upper[i] <= upper[i])
158  {
159  // an overflow has occurred therefore set upper to upper
160  h_upper[i] = upper[i];
161  // Histogram measurement type would force the clipping the max value.
162  // Therefore we must call the following to include the max value:
163  clipBinsAtEnds = false;
164  // The above function is okay since here we are within the autoMinMax
165  // computation and clearly the user intended to include min and max.
166  }
167  }
168  else
169  {
170  h_upper[i] = ((THistogramMeasurement) upper[i]) +
172  if (h_upper[i] <= upper[i])
173  {
174  // an overflow has occurred therefore set upper to upper
175  h_upper[i] = upper[i];
176  // Histogram measurement type would force the clipping the max value.
177  // Therefore we must call the following to include the max value:
178  clipBinsAtEnds = false;
179  // The above function is okay since here we are within the autoMinMax
180  // computation and clearly the user intended to include min and max.
181  }
182  }
183  h_lower[i] = (THistogramMeasurement) lower[i];
184  }
185  }
186  else
187  {
188  h_lower = m_HistogramMin;
189  h_upper = m_HistogramMax;
190  }
191 
192  // Clearing previous histograms
193  histogramList->Clear();
194 
195  // For each dimension
196  for (unsigned int comp = 0; comp < inputList->GetMeasurementVectorSize(); ++comp)
197  {
198  // initialize the Histogram object using the sizes and
199  // the upper and lower bound from the FindSampleBound function
200  typename HistogramType::MeasurementVectorType comp_lower(inputList->GetMeasurementVectorSize());
201  typename HistogramType::MeasurementVectorType comp_upper(inputList->GetMeasurementVectorSize());
202 
203  comp_lower[0] = h_lower[comp];
204  comp_upper[0] = h_upper[comp];
205 
207  << "ListSampleToHistogramListGenerator::GenerateData(): Initializing histogram " << comp << " with (size= " <<
208  m_Size << ", lower = " << comp_lower << ", upper = " << comp_upper << ")");
209 
210  // Create a new histogrma for this component : size of the
211  // measurement vector is : 1
212  histogramList->PushBack(HistogramType::New());
213  histogramList->Back()->SetMeasurementVectorSize(1);
214  histogramList->Back()->SetClipBinsAtEnds(clipBinsAtEnds);
215  histogramList->Back()->Initialize(m_Size, comp_lower, comp_upper);
216 
217  typename TListSample::ConstIterator iter = inputList->Begin();
218  typename TListSample::ConstIterator last = inputList->End();
219  typename HistogramType::IndexType index;
220  typename HistogramType::MeasurementVectorType hvector(inputList->GetMeasurementVectorSize());
221 
222  while (iter != last)
223  {
224  hvector[0] = static_cast<THistogramMeasurement>(iter.GetMeasurementVector()[comp]);
225  histogramList->Back()->GetIndex(hvector, index);
226  if( (!m_NoDataFlag) || hvector[0]!=m_NoDataValue )
227  {
228 
229 
230  if (!histogramList->Back()->IsIndexOutOfBounds(index))
231  {
232  // if the measurement vector is out of bound then
233  // the GetIndex method has returned an index set to the max size of
234  // the invalid dimension - even if the hvector is less than the minimum
235  // bin value.
236  // If the index isn't valid, we don't increase the frequency.
237  // See the comments in Histogram->GetIndex() for more info.
238  histogramList->Back()->IncreaseFrequencyOfIndex(index, 1);
239  }
240  }
241  ++iter;
242  }
243  }
244  otbMsgDebugMacro(<< "ListSampleToHistogramListGenerator::GenerateData(): Leaving");
245 }
246 
247 template<class TListSample,
248  class THistogramMeasurement,
249  class TFrequencyContainer>
250 void
252  THistogramMeasurement,
253  TFrequencyContainer>
254 ::PrintSelf(std::ostream& os, itk::Indent indent) const
255 {
256  Superclass::PrintSelf(os, indent);
257  os << indent << "AutoMinMax: " << m_AutoMinMax << std::endl;
258  os << indent << "Size: " << m_Size << std::endl;
259  os << indent << "MarginalScale: " << m_MarginalScale << std::endl;
260  os << indent << "HistogramMin: " << m_HistogramMin << std::endl;
261  os << indent << "HistogramMax: " << m_HistogramMax << std::endl;
262 }
263 
264 } // end of namespace itk
265 
266 #endif
virtual void SetNumberOfRequiredInputs(DataObjectPointerArraySizeType)
virtual void SetNumberOfRequiredOutputs(DataObjectPointerArraySizeType _arg)
void Fill(TValue const &v)
#define otbMsgDebugMacro(x)
Definition: otbMacro.h:64
This class is a generic all-purpose wrapping around an std::vector<itk::SmartPointer<ObjectType> >...
Definition: otbObjectList.h:40
DataObjectPointerArray::size_type DataObjectPointerArraySizeType
Superclass::MeasurementVectorType MeasurementVectorType
Generates a list of 1D Histograms from a ListSample This class is similar to ListSampleToVariableDime...
DataObject * GetInput(const DataObjectIdentifierType &key)
virtual void SetNthInput(DataObjectPointerArraySizeType num, DataObject *input)
virtual void SetNthOutput(DataObjectPointerArraySizeType num, DataObject *output)
DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override
#define otbMsgDevMacro(x)
Definition: otbMacro.h:66
DataObject * GetOutput(const DataObjectIdentifierType &key)