OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimHistogramEqualization.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossimHistogramEqualization.cpp 14110 2009-03-14 15:46:40Z dburken $
16 #include <ossim/base/ossimCommon.h>
19 #include <ossim/base/ossimTrace.h>
21 
23 
24 static const ossimKeyword HISTOGRAM_INVERSE_FLAG_KW("inverse_flag",
25  "specifies whether the inverse should be done for the getTile");
26 
27 static ossimTrace traceDebug("ossimHistogramEqualization:debug");
28 
31  theTile(NULL),
32  theAccumulationHistogram(NULL),
33  theInverseFlag(false)
34 {
35 }
36 
39  : ossimImageSourceHistogramFilter(inputSource, histogram),
40  theTile(0),
41  theAccumulationHistogram(0),
42  theInverseFlag(false)
43 {
44  if(getHistogram().valid())
45  {
48  }
49 }
50 
53  bool inverseFlag)
54  : ossimImageSourceHistogramFilter(inputSource, histogram),
55  theTile(NULL),
56  theAccumulationHistogram(0),
57  theInverseFlag(inverseFlag)
58 {
59  if(getHistogram().valid())
60  {
63  }
64 }
65 
67 {
68  deleteLuts();
69 }
70 
72  const ossimIrect& tileRect,
73  ossim_uint32 resLevel)
74 {
76  {
77  return NULL;
78  }
79 
81  resLevel);
82 
83  if(!inputTile.valid()) return inputTile;
84 
85  if (!isSourceEnabled())
86  {
87  return inputTile;
88  }
89 
90  if(!theTile.valid())
91  {
92  allocate(); // First time through...
93  }
94 
95  // if (!theTile) throw exception!
96 
97  // Set the origin, resize if needed of the output tile.
99  inputTile->getNumberOfBands());
100 
101  if( !inputTile.valid() ||
102  inputTile->getDataObjectStatus() == OSSIM_NULL ||
103  inputTile->getDataObjectStatus() == OSSIM_EMPTY )
104  {
105  return theTile;
106  }
107 
109  {
111  }
112  if(theForwardLut.size() == 0 ||
113  theInverseLut.size() == 0)
114  {
115  initializeLuts();
116  }
117  if((theForwardLut.size() == 0) ||
118  (theInverseLut.size() == 0))
119  {
120  return inputTile;
121  }
122 
123  switch(inputTile->getScalarType())
124  {
125  case OSSIM_UCHAR:
126  {
127  return runEqualizationAlgorithm(static_cast<ossim_uint8>(0),
128  inputTile);
129  }
130  case OSSIM_USHORT11:
131  case OSSIM_USHORT12:
132  case OSSIM_USHORT13:
133  case OSSIM_USHORT14:
134  case OSSIM_USHORT15:
135  case OSSIM_UINT16:
136  {
137  return runEqualizationAlgorithm(static_cast<ossim_uint16>(0),
138  inputTile);
139  }
140  case OSSIM_SINT16:
141  {
142  return runEqualizationAlgorithm(static_cast<ossim_sint16>(0),
143  inputTile);
144  }
145  case OSSIM_UINT32:
146  {
147  return runEqualizationAlgorithm(static_cast<ossim_uint32>(0),
148  inputTile);
149  }
150  case OSSIM_SINT32:
151  {
152  return runEqualizationAlgorithm(static_cast<ossim_sint32>(0),
153  inputTile);
154  }
155  case OSSIM_FLOAT32:
156  {
157  return runEqualizationAlgorithm(static_cast<ossim_float32>(0),
158  inputTile);
159  }
160  case OSSIM_FLOAT64:
161  {
162  return runEqualizationAlgorithm(static_cast<ossim_float64>(0),
163  inputTile);
164  }
165  default:
166  {
168  << "ossimHistogramEqualization::getTile WARNING: Unsupported scalar type."
169  << endl;
170  break;
171  }
172  }
173 
174  return inputTile;
175 }
176 
178 {
181  initializeLuts();
182 }
183 
185  const char* prefix)const
186 {
187  bool result = ossimImageSourceHistogramFilter::saveState(kwl, prefix);
188 
189  kwl.add(prefix,
190  HISTOGRAM_INVERSE_FLAG_KW,
192  true);
193 
194  return result;
195 }
196 
198  const char* prefix)
199 {
200  static const char MODULE[] = "ossimHistogramEqualization::loadState";
201 
202  if (traceDebug())
203  {
205  << " Entered..."
206  << "\nprefix: " << prefix << endl;
207  }
208 
209  const char* lookup = kwl.find(prefix,
210  HISTOGRAM_INVERSE_FLAG_KW);
211  if(lookup)
212  {
213  theInverseFlag = ossimString(lookup).toBool();
214  }
216  {
217 // computeAccumulationHistogram();
218 // initializeLuts();
219  }
220  else
221  {
222  return false;
223  }
224 
225  if (traceDebug())
226  {
227  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG:" << MODULE;
229  ossimNotify(ossimNotifyLevel_DEBUG) << "\nExited..." << endl;
230  }
231 
232  return true;
233 }
234 
236 {
237  if(getHistogram().valid())
238  {
240  }
241 }
242 
243 template <class T>
245 {
246 
248  !getHistogram())
249  {
250  return tile;
251  }
252 
253  // for now we will always pull from res 0 information
255 
256  if(histo.valid())
257  {
258  ossim_uint32 maxBands = ( (histo->getNumberOfBands() >
259  tile->getNumberOfBands())?
260  tile->getNumberOfBands():
261  histo->getNumberOfBands());
262 
263  long offsetUpperBound = tile->getHeight()*tile->getWidth();
264 
265  for(ossim_uint32 band = 0; band < maxBands; ++band)
266  {
267  ossimRefPtr<ossimHistogram> bandHisto = histo->getHistogram(band);
268  T* buf = static_cast<T*>(tile->getBuf(band));
269  double *histoLut = band<theForwardLut.size()?theForwardLut[band]:NULL;
270  ossim_uint32 actualBand = theBandList[band];
271  if(bandHisto.valid())
272  {
273  if(buf&&histoLut&&(actualBand < histo->getNumberOfBands()))
274  {
275  if(theInverseFlag)
276  {
277  histoLut = theInverseLut[actualBand];
278  }
279  if(histoLut)
280  {
281  if(tile->getDataObjectStatus() == OSSIM_FULL)
282  {
283  T minPix = (T)tile->getMinPix(actualBand);
284  T maxPix = (T)tile->getMaxPix(actualBand);
285  for(long offset = 0; offset < offsetUpperBound; ++offset)
286  {
287  ossim_int32 idx = bandHisto->GetIndex(buf[offset]);
288 
289  if(idx>=0)
290  {
291  T value = (T)(histoLut[idx]);
292 
293  //---
294  // Assign clamping to min max.
295  //
296  // ESH 03/2009 -- Clamping to within min-max fixed
297  //---
298  buf[offset] = value < minPix ? minPix :
299  (value > maxPix ? maxPix : value);
300  }
301  }
302  }
303  else
304  {
305  T minPix = (T)tile->getMinPix(actualBand);
306  T maxPix = (T)tile->getMaxPix(actualBand);
307  T nullPix = (T)tile->getNullPix(actualBand);
308  for(long offset = 0; offset < offsetUpperBound; ++offset)
309  {
310  ossim_int32 idx = bandHisto->GetIndex(buf[offset]);
311 
312  if((buf[offset]!=nullPix)&&(idx>=0))
313  {
314  T value = (T)(histoLut[idx]);
315 
316  //---
317  // Assign clamping to min max.
318  //
319  // ESH 03/2009 -- Clamping to within min-max fixed
320  //---
321  buf[offset] = value < minPix ? minPix :
322  (value > maxPix ? maxPix : value);
323  }
324  else
325  {
326  buf[offset] = nullPix;
327  }
328  }
329  }
330  }
331  }
332  }
333  }
334 
335  tile->validate();
336  }
337 
338  return tile;
339 }
340 
342 {
343  // Base class will recapture "theInputConnection".
345  if(theTile.valid())
346  {
347  theTile = NULL;
348  }
349 }
350 
352 {
353  theBandList.clear();
354 
355  if(theTile.valid())
356  {
357  theTile = NULL;
358  }
359 
361  {
364  if(theTile.valid())
365  {
366  theTile->initialize();
367  }
368  }
369 }
370 
372 {
373  if(theForwardLut.size() != 0 ||
374  theInverseLut.size() != 0)
375  {
376  deleteLuts();
377  }
379  {
380  return;
381  }
384  ossimKeywordlist kwl;
386 
387  if(accumHisto.valid()&&histogram.valid())
388  {
389  long maxBands = accumHisto->getNumberOfBands();
390 
391  for(long band = 0; band < maxBands; ++band)
392  {
393  // first we grab pointers to the histogram and the accumulation
394  // histogram
395  ossimRefPtr<ossimHistogram> h = accumHisto->getHistogram(band);
396  ossimRefPtr<ossimHistogram> h2 = histogram->getHistogram(band);
397 
398  if(h.valid()&&h2.valid())
399  {
400  // lets get the number of indices.
401  ossim_uint32 numberOfIndices = (ossim_uint32)h2->GetRes();
402  vector<double> countForInverse(numberOfIndices);
403 
404  theForwardLut.push_back(new double[numberOfIndices]);
405  theInverseLut.push_back(new double[numberOfIndices]);
406 
407  // let's grab the counts array
408  const float* histoCounts = h->GetCounts();
409 
410 // double maxIntensity = h2->GetMaxVal();
411  double maxIntensity = h2->GetRangeMax();
412  double maxCount = h->GetMaxCount();
413 
414  // now pre compute the transforms
415  double *forwardLut = theForwardLut[band];
416  double *inverseLut = theInverseLut[band];
417 
418 // double minIntensity = h2->GetMinVal();
419  double minIntensity = h2->GetRangeMin();
420  double delta = maxIntensity-minIntensity;
421  ossim_uint32 idx = 0;
422 
423  // clear out the inverse
424  //
425  for(idx = 0; idx < numberOfIndices; ++ idx)
426  {
427  inverseLut[idx] = ossim::nan();
428  }
429  for(idx = 0; idx < numberOfIndices; ++ idx)
430  {
431  forwardLut[idx] = minIntensity + (histoCounts[idx]/maxCount)*delta;
432 
433  ossim_int32 inverseIdx = h2->GetIndex(forwardLut[idx]);
434  if(inverseIdx >= 0)
435  {
436  inverseLut[inverseIdx] = minIntensity + delta*(idx/(ossim_float32)numberOfIndices);
437  }
438  }
439 
440  // now solve the inverse lut
441  //
442  ossim_uint32 idxStart = 0;
443  ossim_uint32 idxEnd = 0;
444 
445  while((ossim::isnan(inverseLut[idxEnd]))&&(idxEnd <numberOfIndices)){ ++idxEnd;}
446  if((idxStart!=idxEnd)&&(idxEnd<numberOfIndices))
447  {
448  std::fill(inverseLut,
449  inverseLut+idxEnd,
450  inverseLut[idxEnd]);
451  }
452  idxStart = numberOfIndices-1;
453  while((ossim::isnan(inverseLut[idxStart]))&&(idxStart > 0)){ --idxStart;}
454  if(idxStart !=0)
455  {
456  std::fill(inverseLut+idxStart,
457  inverseLut+numberOfIndices,
458  inverseLut[idxStart]);
459  }
460 
461  idxStart = 0;
462  idxEnd = 0;
463  ossim_float32 valueStart = 0.0;
464  ossim_float32 valueEnd = 0.0;
465 
466  while(idxStart < numberOfIndices)
467  {
468  idxEnd = idxStart;
469  if(ossim::isnan(inverseLut[idxStart]))
470  {
471  while(ossim::isnan(inverseLut[idxEnd])&&(idxEnd < (numberOfIndices-1))) ++idxEnd;
472  double length = (idxEnd-idxStart)+1;
473  valueEnd = inverseLut[idxEnd];
474  double deltaVal = (valueEnd-valueStart);
475  ossim_uint32 tempIdx = idxStart;
476  ossim_float32 count = 1.0;
477  double t = 0.0;
478  while(tempIdx < idxEnd)
479  {
480  t = (count/length);
481  t = t>1.0?1.0:t;
482  inverseLut[tempIdx] = valueStart + deltaVal*t;
483  ++count;
484  ++tempIdx;
485  }
486  idxStart = idxEnd;
487  valueStart = valueEnd;
488  }
489  else
490  {
491  valueStart = inverseLut[idxStart];
492  ++idxStart;
493  }
494  }
495  }
496  }
497  }
498 }
499 
501 {
503 }
504 
506 {
507  return theInverseFlag;
508 }
509 
511 {
512  theInverseFlag = inverseFlag;
513 }
514 
516 {
517  long band = 0;
518 
519  for(band = 0; band < (long)theForwardLut.size(); ++band)
520  {
521  delete [] theForwardLut[band];
522  }
523  theForwardLut.clear();
524 
525  for(band = 0; band < (long)theInverseLut.size(); ++band)
526  {
527  delete [] theInverseLut[band];
528  }
529 
530  theInverseLut.clear();
531 }
532 
534 {
535  return theFilename;
536 }
537 
539 {
540  // Base class...
542 }
16 bit unsigned integer (15 bits used)
virtual ossim_uint32 getWidth() const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
float GetRangeMin() const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=NULL)
Method to the load (recreate) the state of an object from a keyword list.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=NULL)
Method to the load (recreate) the state of an object from a keyword list.
virtual const ossim_float64 * getMaxPix() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=NULL) const
Method to save the state of an object to a keyword list.
ossimRefPtr< ossimImageData > runEqualizationAlgorithm(T dummyVariable, ossimRefPtr< ossimImageData > tile)
virtual ossim_uint32 getNumberOfBands() const
64 bit floating point
16 bit unsigned integer
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
Represents serializable keyword/value map.
bool valid() const
Definition: ossimRefPtr.h:75
float GetRangeMax() const
ossimRefPtr< ossimMultiResLevelHistogram > theAccumulationHistogram
const char * find(const char *key) const
float ossim_float32
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
virtual void setHistogram(ossimRefPtr< ossimMultiResLevelHistogram > histogram)
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
16 bit signed integer
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
16 bit unsigned integer (13 bits used)
32 bit floating point
virtual ossimRefPtr< ossimMultiResLevelHistogram > getHistogram()
32 bit unsigned integer
virtual void initialize()
Initialize the data buffer.
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
int GetRes() const
virtual void setHistogram(ossimRefPtr< ossimMultiResLevelHistogram > histogram)
virtual void getOutputBandList(std::vector< ossim_uint32 > &bandList) const
Initializes bandList.
ossim_uint32 getNumberOfBands() const
static ossimImageDataFactory * instance()
virtual ossimDataObjectStatus validate() const
virtual void setImageRectangleAndBands(const ossimIrect &rect, ossim_uint32 numberOfBands)
32 bit signed integer
bool toBool() const
String to numeric methods.
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
ossimImageSource * theInputConnection
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
virtual int GetIndex(float) const
ossimRefPtr< ossimHistogram > getHistogram(ossim_int32 band)
virtual ossimIrect getImageRectangle() const
float GetMaxCount() const
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=NULL) const
Method to save the state of an object to a keyword list.
virtual const ossim_float64 * getMinPix() const
std::vector< ossim_uint32 > theBandList
virtual ossimScalarType getScalarType() const
virtual void setInverseFlag(bool inverseFlag)
16 bit unsigned integer (11 bits used)
ossimRefPtr< ossimImageData > theTile
void allocate()
Called on first getTile, will initialize all data needed.
virtual const void * getBuf() const
float * GetCounts()
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossimRefPtr< ossimMultiBandHistogram > getMultiBandHistogram(ossim_uint32 resLevel) const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
ossimRefPtr< ossimMultiResLevelHistogram > createAccumulationLessThanEqual() const
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
8 bit unsigned iteger
int ossim_int32
virtual const ossimFilename & getHistogramFilename() const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91