Orfeo Toolbox  3.16
otbStandardRenderingFunction.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #ifndef __otbStandardRenderingFunction_h
19 #define __otbStandardRenderingFunction_h
20 
21 #include <cassert>
22 #include <iomanip>
23 #include <vector>
24 
25 #include "otbMacro.h"
26 #include "otbI18n.h"
30 #include "otbRenderingFunction.h"
31 
32 #include "itkMetaDataDictionary.h"
33 
34 namespace otb
35 {
36 
37 namespace Function
38 {
39 
44 template <class TInputPixel, class TOutputPixel>
45 class Identity
46 {
47 public:
49  virtual ~Identity(){}
50  bool operator !=(const Identity&) const
51  {
52  return false;
53  }
54  bool operator ==(const Identity& other) const
55  {
56  return !(*this != other);
57  }
58 
59  inline TOutputPixel operator ()(const TInputPixel& A) const
60  {
61  return static_cast<TOutputPixel>(A);
62  }
63 };
64 
80 template <class TPixel, class TRGBPixel,
81  class TPixelRepresentationFunction = ChannelSelectorFunctor<TPixel>,
82  class TTransferFunction = Identity<
83  typename itk::NumericTraits<typename itk::NumericTraits<TPixel>::ValueType>::RealType,
84  typename itk::NumericTraits<typename itk::NumericTraits<TPixel>::ValueType>::RealType
85  > >
87  : public RenderingFunction<TPixel, TRGBPixel>
88 {
89 public:
95 
98 
100  itkNewMacro(Self);
101 
103  typedef TRGBPixel OutputPixelType;
104  typedef typename OutputPixelType::ValueType OutputValueType;
105  typedef TPixel PixelType;
106  typedef typename itk::NumericTraits<PixelType>::ValueType ScalarType;
110  typedef typename itk::NumericTraits<ScalarType>::RealType RealScalarType;
113 
115  typedef std::vector<RealScalarType> ExtremaVectorType;
116  typedef TTransferFunction TransferFunctionType;
117  typedef TPixelRepresentationFunction PixelRepresentationFunctionType;
118  typedef typename PixelRepresentationFunctionType::Pointer PixelRepresentationFunctionPointerType;
119  typedef typename PixelRepresentationFunctionType::ChannelListType ChannelListType;
120 
122 
127  {
128  return (*m_PixelRepresentationFunction)(spixel);
129  }
130 
139  {
140  if ((spixel.Size() != 1) && (spixel.Size() != 3) && (spixel.Size() != 2) && (spixel.Size() != 4))
141  {
142  itkExceptionMacro(<< "the PixelRepresentation function should give an output of "
143  << "size 1, 3 or 4 otherwise I don't know how to make an RGB of it !");
144  }
145  if (spixel.Size() != m_TransferedMinimum.size())
146  {
147  itkExceptionMacro(<< " m_TransferedMinimum and pixel size do not correspond"
148  << " spixel.Size(): " << spixel.Size()
149  << " m_TransferedMinimum.size(): " << m_TransferedMinimum.size());
150  }
151  OutputPixelType output(255);
152 
153 // otbMsgDevMacro(<<"StandardRenderingFunction::EvaluateTransferFunction "
154 // << "m_TransferFunction(spixel[0])" << m_TransferFunction(spixel[0])
155 // << ", m_TransferedMinimum[0] " << m_TransferedMinimum[0]
156 // << ", m_TransferedMaximum[0] " << m_TransferedMaximum[0])
157 
158  if (spixel.Size() == 1)
159  {
161  spixel[0]), m_TransferedMinimum[0], m_TransferedMaximum[0]);
162  output[0] = value;
163  output[1] = value;
164  output[2] = value;
165  }
166  else
167  {
171  }
172 
173  if ((spixel.Size() == 4) && (output.Size() == 4))
174  {
175  assert((spixel[3] >= 0) && (spixel[3] <= 255));
176  output[3] = static_cast<OutputValueType>(spixel[3]); //just copy the alpha channel
177  }
178 
179  return output;
180  }
181 
182  virtual unsigned int GetPixelRepresentationSize() const
183  {
184  return m_PixelRepresentationFunction->GetOutputSize();
185  }
186 
187  virtual void Initialize(const MetaDataDictionaryType& metadatadictionary) //FIXME should disappear and be automatic (IsModified())
188  {
189  if ((this->GetMTime() > m_UTime) || (this->GetPixelRepresentationFunction()->GetMTime() > m_UTime))
190  //NOTE: we assume that Transfer function have no parameters
191  {
192  if ((this->GetListSample()).IsNotNull())
193  {
194  //the size of the Vector was unknown at construction time for the
195  //m_PixelRepresentationFunction, now, we may get a better default
196  if (m_PixelRepresentationFunction->IsUsingDefaultParameters())
197  {
198  //RGB rendering needs at least 3 channels
199  if (this->GetListSample()->GetMeasurementVectorSize() >= 3)
200  {
201  typedef otb::ImageMetadataInterfaceBase ImageMetadataInterfaceType;
202  ImageMetadataInterfaceType::Pointer metadataInterface = ImageMetadataInterfaceFactory::CreateIMI(
203  metadatadictionary);
204  std::vector<unsigned int> defaultDisplay = metadataInterface->GetDefaultDisplay();
205  m_PixelRepresentationFunction->SetRedChannelIndex(defaultDisplay[0]);
206  m_PixelRepresentationFunction->SetGreenChannelIndex(defaultDisplay[1]);
207  m_PixelRepresentationFunction->SetBlueChannelIndex(defaultDisplay[2]);
208  }
209  }
210  }
211 
212  unsigned int nbComps = m_PixelRepresentationFunction->GetOutputSize();
213  if (m_AutoMinMax)
214  {
215  //FIXME check what happens if the m_PixelRepresentationFunction is modified AFTER the Initialize.
216 
218  << "Initialize(): " << nbComps << " components, quantile= " << 100 * m_AutoMinMaxQuantile << " %");
219 
220  // For each components, use the histogram to compute min and max
221  m_Minimum.clear();
222  m_Maximum.clear();
223 
224  // Comment the condition cause if we change the channel list order
225  // this condition doesn't allow us to recompute the histograms
226  //if (this->GetHistogramList().IsNull())
227  //{
228  this->RenderHistogram();
229  // itkExceptionMacro( << "To Compute min/max automatically, Histogram should be "
230  // <<"provided to the rendering function with SetHistogramList()" );
231  //}
232  for (unsigned int comp = 0; comp < nbComps; ++comp)
233  {
234  // Compute quantiles
235  m_Minimum.push_back(
236  static_cast<ScalarType> (this->GetHistogramList()->GetNthElement(comp)->Quantile(0,
238  m_Maximum.push_back(static_cast<ScalarType> (this->GetHistogramList()->GetNthElement(comp)->Quantile(0, 1
239  -
241  }
242  }
243  else
244  {
245  if (m_Minimum.empty())
246  {
247  m_Minimum.resize(nbComps, 0);
248  }
249  if (m_Maximum.empty())
250  {
251  m_Maximum.resize(nbComps, 255);
252  }
253  }
254 
255  typename ExtremaVectorType::const_iterator minIt = this->m_Minimum.begin();
256  typename ExtremaVectorType::const_iterator maxIt = this->m_Maximum.begin();
257 
258  m_TransferedMinimum.clear();
259  m_TransferedMaximum.clear();
260 
261  while (minIt != this->m_Minimum.end() && maxIt != this->m_Maximum.end())
262  {
263  const double v1 = this->m_TransferFunction(*minIt);
264  const double v2 = this->m_TransferFunction(*maxIt);
265  m_TransferedMinimum.push_back(static_cast<ScalarType> (std::min(v1, v2)));
266  m_TransferedMaximum.push_back(static_cast<ScalarType> (std::max(v1, v2)));
267  ++minIt;
268  ++maxIt;
269  }
270 
271  m_UTime.Modified();
272  }
273  }
274 
275  const std::string Describe(const PixelType& spixel) const
276  {
277  std::ostringstream oss;
278  oss << m_PixelRepresentationFunction->GetDescription() << ": ";
279  typename PixelRepresentationFunctionType::ChannelListType channels;
280  channels = m_PixelRepresentationFunction->GetChannelList();
281 
282  for (unsigned int i = 0; i < channels.size(); ++i)
283  {
284  //Describe the channel selection (numbering starts with 1)
285  oss << channels[i] + 1 << " ";
286  }
287  oss << std::endl;
288 
289  // unsigned int inputChannels = VisualizationPixelTraits::PixelSize(spixel);
290 
291  InternalPixelType spixelRepresentation = this->EvaluatePixelRepresentation(spixel);
292  OutputPixelType spixelDisplay = this->EvaluateTransferFunction(spixelRepresentation);
293  oss << otbGetTextMacro("Pixel value") << ": "
294  << static_cast<typename itk::NumericTraits<PixelType>::PrintType>(spixel) << std::endl;
295  oss << otbGetTextMacro("Value computed") << ": "
296  << static_cast<typename itk::NumericTraits<InternalPixelType>::PrintType>(spixelRepresentation) << std::endl;
297  oss << otbGetTextMacro("Value displayed") << ": " << std::endl;
298  oss << otbGetTextMacro("R") << " " << std::setw(3)
299  << static_cast<typename itk::NumericTraits<OutputValueType>::PrintType>(spixelDisplay[0]) << ", ";
300  oss << otbGetTextMacro("G") << " " << std::setw(3)
301  << static_cast<typename itk::NumericTraits<OutputValueType>::PrintType>(spixelDisplay[1]) << ", ";
302  oss << otbGetTextMacro("B") << " " << std::setw(3)
303  << static_cast<typename itk::NumericTraits<OutputValueType>::PrintType>(spixelDisplay[2]);
304  if (spixelDisplay.Size() == 4)
305  {
306  oss << ", ";
307  oss << otbGetTextMacro("A") << " " << std::setw(3)
308  << static_cast<typename itk::NumericTraits<OutputValueType>::PrintType>(spixelDisplay[3]);
309  }
310  oss << std::endl;
311  return oss.str();
312  }
313 
317  virtual void SetParameters(const ParametersType& parameters)
318  {
319  //Clear the min and max vectors
320  m_Minimum.clear();
321  m_Maximum.clear();
322 
323  if (parameters.Size() % 2 != 0)
324  {
325  itkExceptionMacro(<< "Min And Max should be provided for every band to display");
326  }
327 
328  for (unsigned int i = 0; i < parameters.Size(); ++i)
329  {
330  m_Minimum.push_back(parameters[i]);
331  ++i;
332  m_Maximum.push_back(parameters[i]);
333  }
334  m_AutoMinMax = false;
336  otbMsgDevMacro(<< "StandardRenderingFunction::SetParameters: " << m_Minimum.size() << "; " << m_Maximum.size());
337  this->Modified();
338  }
339 
344  {
345  unsigned int nbBands = m_PixelRepresentationFunction->GetOutputSize();
346  ParametersType param;
347  param.SetSize(2 * nbBands);
348 
349  // Edit the parameters as [minBand0, maxBand0, minBand1, maxBand1, ...]
350  for (unsigned int i = 0; i < nbBands; ++i)
351  {
352  // Min Band
353  param.SetElement(2 * i, /*TransferedMinimum*/ m_Minimum[i]);
354  // Max Band
355  param.SetElement(2 * i + 1, /*TransferedMaximum*/ m_Maximum[i]);
356  }
357  return param;
358  }
359 
360  virtual void SetChannelList(std::vector<unsigned int>& channels)
361  {
362  if (m_PixelRepresentationFunction->GetChannelList() != channels)
363  {
364  m_PixelRepresentationFunction->SetChannelList(channels);
365  this->Modified();
366  }
367  }
368 
369  virtual std::vector<unsigned int> GetChannelList()
370  {
371  return m_PixelRepresentationFunction->GetChannelList();
372  }
373 
376  {
377  return m_TransferFunction;
378  }
381  {
383  }
384 
386  virtual void SetAutoMinMax(bool val)
387  {
388  m_AutoMinMax = val;
389  this->Modified();
390  }
391  itkGetMacro(AutoMinMax, bool);
392  itkBooleanMacro(AutoMinMax);
393 
394  itkGetMacro(AutoMinMaxQuantile, double);
395 
396 protected:
402  {
403  }
406 
411  {
412  if (input > max)
413  {
414  return 255;
415  }
416  else if (input < min)
417  {
418  return 0;
419  }
420  else
421  {
422  return static_cast<OutputValueType> (vcl_floor(
423  255. * (static_cast<double> (input) - static_cast<double> (min))
424  / (static_cast<double> (max) - static_cast<double> (min))
425  + 0.5));
426 
427  }
428  }
429 
431  {
432  if (m_Minimum.size() != m_Maximum.size())
433  {
434  itkExceptionMacro(<< "m_Minimum and m_Maximum should have the same size");
435  }
436  m_TransferedMinimum.clear();
437  m_TransferedMaximum.clear();
438  for (unsigned int i = 0; i < m_Minimum.size(); ++i)
439  {
442  }
443  }
444 
448 
457 
459 
462 
463 private:
464  StandardRenderingFunction(const Self&); //purposely not implemented
465  void operator =(const Self&); //purposely not implemented
466 
470 
471  unsigned int m_RedChannelIndex;
472  unsigned int m_GreenChannelIndex;
473  unsigned int m_BlueChannelIndex;
474 
477 
480 
482 };
483 } // end namespace Functor
484 } // end namespace otb
485 
486 #endif

Generated at Sun Feb 3 2013 00:48:36 for Orfeo Toolbox with doxygen 1.8.1.1