OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimHistoMatchRemapper.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: ossimHistoMatchRemapper.cpp 15833 2009-10-29 01:41:53Z eshirschorn $
15 #include <ossim/base/ossimDpt.h>
17 
20 {
21  theBlankTile = NULL;
22 }
23 
25  const vector<double>& targetMeanPerBand,
26  const vector<double>& targetSigmaPerBand,
27  const vector<double>& inputMeanPerBand,
28  const vector<double>& inputSigmaPerBand)
29  : ossimImageSourceFilter(inputSource),
30  theTargetMeanPerBand(targetMeanPerBand),
31  theTargetSigmaPerBand(targetSigmaPerBand),
32  theInputMeanPerBand(inputMeanPerBand),
33  theInputSigmaPerBand(inputSigmaPerBand)
34 {
35  theBlankTile = NULL;
36 }
37 
38 
40 {
41 }
42 
44  const ossimIrect& tileRect,
45  ossim_uint32 resLevel)
46 {
49  {
50  tile = theInputConnection->getTile(tileRect, resLevel);
51  }
52  if(!tile.valid())
53  {
54  return NULL;
55  }
56  if((tile.valid() &&
57  ((tile->getDataObjectStatus()==OSSIM_NULL) ||
58  (tile->getDataObjectStatus()==OSSIM_EMPTY))))
59 
60  {
61  return tile;
62  }
63 
64  theBlankTile->setOrigin(tileRect.ul());
65  ossim_uint32 numberOfBands = (ossim_uint32)theInputMeanPerBand.size();
66 
67  numberOfBands = numberOfBands>tile->getNumberOfBands()?tile->getNumberOfBands():numberOfBands;
68  double result = 0;
69  if(isSourceEnabled())
70  {
71  long offsetBound = (long)(tile->getWidth()*tile->getHeight());
72  if(tile->getScalarType() == OSSIM_UCHAR)
73  {
74  for(ossim_uint32 band = 0; band < numberOfBands; ++band)
75  {
76  unsigned char* buf = static_cast<unsigned char*>(tile->getBuf(band));
77  for(long offset=0; offset < offsetBound;++offset)
78  {
79  // if the input has no deviation we will just
80  // do a shift to the target mean
81  if(fabs(theInputSigmaPerBand[band]) < FLT_EPSILON)
82  {
83  result = transLean(buf[offset],
84  theInputMeanPerBand[band],
86  0,
87  255);
88  }
89  else
90  {
91  result = transLeanStretch(buf[offset],
92  theInputMeanPerBand[band],
96  0,
97  255);
98  }
99  result = ((result>255)?255:result);
100  result = ((result<0)?0:result);
101 
102  buf[offset] = (unsigned char)result;
103  }
104  }
105  }
106  }
107 
108  return tile;
109 }
110 
112 {
113  if(!theInputConnection)
114  {
115  return;
116  }
117  theBlankTile = new ossimImageData(this,
120 }
121 
123 {
124  return theInputMeanPerBand;
125 }
126 
128 {
129  return theInputSigmaPerBand;
130 }
131 
133 {
134  return theTargetMeanPerBand;
135 }
136 
138 {
139  return theTargetSigmaPerBand;
140 }
141 
142 void ossimHistoMatchRemapper::setInputMeanValues(const vector<double>& newValues)
143 {
144  theInputMeanPerBand = newValues;
145 }
146 
147 void ossimHistoMatchRemapper::setInputSigmaValues(const vector<double>& newValues)
148 {
149  theInputSigmaPerBand = newValues;
150 }
151 
152 void ossimHistoMatchRemapper::setTargetMeanValues(const vector<double>& newValues)
153 {
154  theTargetMeanPerBand = newValues;
155 }
156 
157 void ossimHistoMatchRemapper::setTargetSigmaValues(const vector<double>& newValues)
158 {
159  theTargetSigmaPerBand = newValues;
160 }
161 
162 double ossimHistoMatchRemapper::transLean // returns vOut
163 (
164  double vIn
165  , double vBias
166  , double vTarget
167  , double vMin
168  , double vMax
169 )
170 {
171  // max change
172  const double vDelta = vTarget - vBias;
173  double weight=0.0;
174 
175  // weight max change dependend on proximity to end points
176  if (vIn <= vBias)
177  {
178  weight = fabs((vIn - vMin) / (vBias - vMin));
179  }
180  else
181  {
182  weight = fabs((vMax - vIn) / (vMax - vBias));
183  }
184  return (vIn + (vDelta * weight));
185 };
186 
187 double ossimHistoMatchRemapper::transLeanStretch // returns vOut
188  (
189  double vIn
190  , double vBias
191  , double vBiasStretch
192  , double vTarget
193  , double vTargetStretch
194  , double vMin
195  , double vMax
196  )
197 {
198 
199  // line segment end points
200  const double x1 = vMin;
201  const double x2 = vBias - vBiasStretch;
202  const double x3 = vBias + vBiasStretch;
203  const double x4 = vMax;
204  const double y1 = 0.0;
205  const double y2 = (vTarget + vTargetStretch) - (vBias + vBiasStretch);
206  const double y3 = (vTarget - vTargetStretch) - (vBias - vBiasStretch);
207  const double y4 = 0.0;
208 
209 
210  // perform appropriate linear lookup operation based on input value
211  double vOut = vIn;
212  if (vIn <= x2)
213  {
214  vOut = (vIn - x1) * (y2-y1)/(x2-x1) + y1 + vIn;
215  }
216  else
217  if (vIn <= x3)
218  {
219  vOut = (vIn - x2) * (y3-y2)/(x3-x2) + y2 + vIn;
220  }
221  else
222  {
223  vOut = (vIn - x3) * (y4-y3)/(x4-x3) + y3 + vIn;
224  }
225 
226  return vOut;
227 }
228 
230  const char* prefix)
231 {
232  theTargetMeanPerBand.clear();
233  theTargetSigmaPerBand.clear();
234  theInputMeanPerBand.clear();
235  theInputSigmaPerBand.clear();
236  ossim_uint32 result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "target_mean[0-9]");
237  ossim_uint32 numberOfMatches=0;
238  ossim_uint32 index=0;
239 
240  // load target mean
241  while(numberOfMatches < result)
242  {
243  ossimString key = prefix;
244  key += ossimString("target_mean");
245  key += ossimString::toString(index);
246  const char* lookup = kwl.find(key.c_str());
247  if(lookup)
248  {
249  theTargetMeanPerBand.push_back(ossimString(lookup).toDouble());
250  ++numberOfMatches;
251  }
252  ++index;
253  }
254  numberOfMatches = 0;
255  index = 0;
256  result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "target_sigma[0-9]");
257  // load target sigma
258  while(numberOfMatches < result)
259  {
260  ossimString key = prefix;
261  key += ossimString("target_sigma");
262  key += ossimString::toString(index);
263  const char* lookup = kwl.find(key.c_str());
264  if(lookup)
265  {
266  theTargetSigmaPerBand.push_back(ossimString(lookup).toDouble());
267  ++numberOfMatches;
268  }
269  ++index;
270  }
271 
272  numberOfMatches = 0;
273  index = 0;
274  result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "input_mean[0-9]");
275  // load input mean
276  while(numberOfMatches < result)
277  {
278  ossimString key = prefix;
279  key += ossimString("input_mean");
280  key += ossimString::toString(index);
281  const char* lookup = kwl.find(key.c_str());
282  if(lookup)
283  {
284  theInputMeanPerBand.push_back(ossimString(lookup).toDouble());
285  ++numberOfMatches;
286  }
287  ++index;
288  }
289 
290  numberOfMatches = 0;
291  index = 0;
292  result = kwl.getNumberOfSubstringKeys(ossimString(prefix) + "input_sigma[0-9]");
293  // load input sigma
294  while(numberOfMatches < result)
295  {
296  ossimString key = prefix;
297  key += ossimString("input_sigma");
298  key += ossimString::toString(index);
299  const char* lookup = kwl.find(key.c_str());
300  if(lookup)
301  {
302  theInputSigmaPerBand.push_back(ossimString(lookup).toDouble());
303  ++numberOfMatches;
304  }
305  ++index;
306  }
307 
308  return true;
309 }
310 
312  const char* prefix)
313 {
314  ossim_uint32 index = 1;
315  for(index=1;index <= theTargetMeanPerBand.size();++index)
316  {
317  ossimString key = ossimString("target_mean") + ossimString::toString(index);
318  kwl.add(prefix,
319  key.c_str(),
320  theTargetMeanPerBand[index-1],
321  true);
322  }
323  for(index=1;index <= theTargetSigmaPerBand.size();++index)
324  {
325  ossimString key = ossimString("target_sigma") + ossimString::toString(index);
326  kwl.add(prefix,
327  key.c_str(),
328  theTargetSigmaPerBand[index-1],
329  true);
330  }
331  for(index=1;index <= theInputMeanPerBand.size();++index)
332  {
333  ossimString key = ossimString("input_mean") + ossimString::toString(index);
334  kwl.add(prefix,
335  key.c_str(),
336  theInputMeanPerBand[index-1],
337  true);
338  }
339  for(index=1;index <= theInputSigmaPerBand.size();++index)
340  {
341  ossimString key = ossimString("input_sigma") + ossimString::toString(index);
342  kwl.add(prefix,
343  key.c_str(),
344  theInputSigmaPerBand[index-1],
345  true);
346  }
347  return true;
348 }
349 
virtual ossim_uint32 getWidth() const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
const vector< double > & getTargetMeanValues() const
double transLean(double vIn, double vBias, double vTarget, double vMin, double vMax)
transLean
virtual ossim_uint32 getNumberOfBands() const
ossim_uint32 getNumberOfSubstringKeys(const ossimString &regularExpression) const
vector< double > theInputMeanPerBand
vector< double > theTargetMeanPerBand
Represents serializable keyword/value map.
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
static ossimString toString(bool aValue)
Numeric to string methods.
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
void setInputSigmaValues(const vector< double > &newValues)
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
void setInputMeanValues(const vector< double > &newValues)
const vector< double > & getInputSigmaValues() const
void setTargetSigmaValues(const vector< double > &newValues)
#define FLT_EPSILON
ossimImageSource * theInputConnection
unsigned int ossim_uint32
vector< double > theInputSigmaPerBand
const vector< double > & getTargetSigmaValues() const
vector< double > theTargetSigmaPerBand
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 void setOrigin(const ossimIpt &origin)
const vector< double > & getInputMeanValues() const
double transLeanStretch(double vIn, double vBias, double vBiasStretch, double vTarget, double vTargetStretch, double vMin, double vMax)
transLeanStretch
virtual ossimScalarType getScalarType() const
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual const void * getBuf() const
ossimRefPtr< ossimImageData > theBlankTile
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=NULL)
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
8 bit unsigned iteger
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
void setTargetMeanValues(const vector< double > &newValues)