OTB  10.0.0
Orfeo Toolbox
otbComputeGainLutFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2024 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 otbComputeGainLutFilter_hxx
22 #define otbComputeGainLutFilter_hxx
23 
25 #include "itkImageRegionIterator.h"
26 
27 #include <limits>
28 #include <numeric>
29 
30 namespace otb
31 {
32 
33 template <class TInputImage, class TOutputImage>
35 {
36  m_NbBin = 256;
37  m_NbPixel = 0;
38  m_Min = std::numeric_limits<double>::quiet_NaN();
39  m_Max = std::numeric_limits<double>::quiet_NaN();
40  m_Step = -1;
41  this->DynamicMultiThreadingOn();
42 }
43 
44 template <class TInputImage, class TOutputImage>
46 {
47  m_NbBin = this->GetInput()->GetNumberOfComponentsPerPixel();
48  m_Step = static_cast<double>(m_Max - m_Min) / static_cast<double>(m_NbBin - 1);
49 }
50 
51 template <class TInputImage, class TOutputImage>
53 {
54  assert(m_Step > 0);
55  assert(m_NbBin > 0);
56 
57  typename InputImageType::ConstPointer input(this->GetInput());
58  typename OutputImageType::Pointer output(this->GetOutput());
59 
60  itk::ImageRegionConstIterator<InputImageType> it(input, outputRegionForThread);
61 
62  itk::ImageRegionIterator<OutputImageType> oit(output, outputRegionForThread);
63 
64  HistoType target;
65  target.SetSize(m_NbBin);
66 
67  HistoType currentHisto;
68 
69  LutType lut;
70  lut.SetSize(m_NbBin);
71 
72  for (it.GoToBegin(), oit.GoToBegin(); !oit.IsAtEnd() || !it.IsAtEnd(); ++oit, ++it)
73  {
74  currentHisto = it.Get();
75  target.Fill(0);
76  lut.Fill(-1);
77  if (IsValid(currentHisto))
78  {
79  CreateTarget(currentHisto, target);
80  Equalized(currentHisto, target, lut);
81  }
82  oit.Set(lut);
83  }
84  assert(oit.IsAtEnd() && it.IsAtEnd());
85 }
86 
87 template <class TInputImage, class TOutputImage>
88 typename TOutputImage::InternalPixelType ComputeGainLutFilter<TInputImage, TOutputImage>::PostProcess(unsigned int countValue, unsigned int countMapValue)
89 {
90  double denum(countValue * m_Step + m_Min);
91  if (denum == 0)
92  return 0;
93  return static_cast<OutputPixelType>((countMapValue * m_Step + m_Min) / denum);
94 }
95 
96 template <class TInputImage, class TOutputImage>
98 {
99  unsigned int countValue(0), countMapValue(0);
100  lut[countValue] = 1; // Black stays black
101  ++countValue;
102  unsigned int countInput(inputHisto[0] + inputHisto[countValue]);
103  lut[m_NbBin - 1] = 1; // White stays white
104  unsigned int countTarget(targetHisto[countMapValue]);
105 
106  while ((countMapValue < m_NbBin) && countValue < (m_NbBin - 1))
107  {
108  if (countInput > countTarget)
109  {
110  ++countMapValue;
111  countTarget += targetHisto[countMapValue];
112  }
113  else
114  {
115  lut[countValue] = PostProcess(countValue, countMapValue);
116  ++countValue;
117  countInput += inputHisto[countValue];
118  }
119  }
120  for (unsigned int i = 0; i < m_NbBin; i++)
121  {
122  if (lut[i] == -1)
123  {
124  lut[i] = 1;
125  }
126  }
127 }
128 
129 template <class TInputImage, class TOutputImage>
131 {
132  unsigned int nbPixel(0);
133  for (unsigned int i = 0; i < m_NbBin; i++)
134  {
135  nbPixel += inputHisto[i];
136  }
137  unsigned int rest(nbPixel % m_NbBin), height(nbPixel / m_NbBin);
138  targetHisto.Fill(height);
139  for (unsigned int i = 0; i < rest; i++)
140  {
141  ++targetHisto[(m_NbBin - rest) / 2 + i];
142  }
143 }
144 
145 template <class TInputImage, class TOutputImage>
147 {
148  long acc = std::accumulate(&inputHisto[0], &inputHisto[m_NbBin - 1], 0);
149  return acc >= (0.5 * m_NbPixel);
150 }
151 
155 template <class TInputImage, class TOutputImage>
156 void ComputeGainLutFilter<TInputImage, TOutputImage>::PrintSelf(std::ostream& os, itk::Indent indent) const
157 {
158  Superclass::PrintSelf(os, indent);
159  os << indent << "Minimum: " << m_Min << std::endl;
160  os << indent << "Maximum: " << m_Max << std::endl;
161  os << indent << "Step: " << m_Step << std::endl;
162  os << indent << "Number of bin: " << m_NbBin << std::endl;
163  os << indent << "Number of pixel by histogram: " << m_NbPixel << std::endl;
164 }
166 
167 } // End namespace otb
168 
169 #endif
void DynamicThreadedGenerateData(const OutputImageRegionType &outputRegionForThread) override
void PrintSelf(std::ostream &os, itk::Indent indent) const override
bool IsValid(const HistoType &inputHisto)
void Equalized(const HistoType &inputHisto, HistoType &targetHisto, LutType &lut)
OutputImageType::RegionType OutputImageRegionType
OutputImageType::PixelType LutType
void CreateTarget(const HistoType &inputHisto, HistoType &targetHisto)
InputImageType::PixelType HistoType
OutputPixelType PostProcess(unsigned int countMapValue, unsigned int countValue)
OutputImageType::InternalPixelType OutputPixelType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.