00001
00025 #include "inanna/equalization.h"
00026 #include "magic/mclass.h"
00027
00028 impl_dynamic (Equalizer, {Object});
00029 impl_dynamic (HistogramEq, {Equalizer});
00030 impl_dynamic (GaussianEq, {Equalizer});
00031 impl_dynamic (MinmaxEq, {Equalizer});
00032 impl_dynamic (MatrixEqualizer, {Equalizer});
00033
00034
00035 int xmlflag = ios::xalloc();
00036
00037
00038
00040
00041
00042
00043
00044
00045
00047
00048 HistogramEq::HistogramEq (int precision, double floor, double ceiling) {
00049 mHistogram.make (precision);
00050 mMin = floor;
00051 mMax = ceiling;
00052 mLowBound = 1E30;
00053 mUpBound = -1E30;
00054 }
00055
00056 HistogramEq::HistogramEq (const HistogramEq& orig) : Equalizer (orig) {
00057 mHistogram.make (orig.mHistogram.size());
00058 mMin = orig.mMin;
00059 mMax = orig.mMax;
00060 mLowBound = orig.mLowBound;
00061 mUpBound = orig.mUpBound;
00062 }
00063
00064 int HistogramEq::determineDomain (float x, int precision, float lowBound, float upBound) {
00065
00066 if (upBound-lowBound == 0)
00067 return 0;
00068
00069
00070 if (x < lowBound)
00071 return 0;
00072
00073
00074 if (x > upBound)
00075 return precision-1;
00076
00077
00078 return int (((x-lowBound)/(upBound-lowBound))*(precision-1));
00079 }
00080
00081 void HistogramEq::analyze (const Vector& vec, bool additive)
00082 {
00083 if (additive) {
00084
00085
00086
00087
00088
00089 mData.add (new Vector (vec));
00090 } else {
00091
00092 analyze2 (vec);
00093 }
00094 }
00095
00096 void HistogramEq::finalize ()
00097 {
00098
00099 int totlen=0;
00100 for (int i=0; i<mData.size(); i++)
00101 totlen += mData[i].size();
00102
00103
00104 Vector analvec (totlen);
00105 for (int i=0, t=0; i<mData.size(); i++)
00106 for (int j=0; j<mData[i].size(); j++, t++)
00107 analvec[t] = mData[i][j];
00108
00109
00110 mData.make (0);
00111
00112
00113 analyze2 (analvec);
00114 }
00115
00116 void HistogramEq::analyze2 (const Vector& vec)
00117 {
00118 mLowBound = min (vec);
00119 mUpBound = max (vec);
00120
00121
00122 for (int i=0; i<mHistogram.size(); i++)
00123 mHistogram[i] = 0.0;
00124
00125
00126 for (int i=0; i<vec.size(); i++)
00127 if (!is_undef (vec[i]))
00128 mHistogram [determineDomain (vec[i], mHistogram.size(), mLowBound, mUpBound)] += 1;
00129
00130
00131 float sum = 0.0;
00132 float lastsum = 0.0;
00133 int lastpos=0;
00134 for (int i=0; i<mHistogram.size(); i++)
00135 if (mHistogram[i]>0.0) {
00136 sum += mHistogram[i];
00137 if (i>0) {
00138 for (int j=lastpos+1; j<=i; j++)
00139 mHistogram[j] = lastsum+(j-lastpos)/(i-lastpos+0.0)*(sum-lastsum);
00140 lastsum=sum;
00141 } else {
00142 mHistogram[i] = 0.0;
00143 sum=0.0;
00144 }
00145
00146 lastpos=i;
00147 }
00148
00149
00150 for (int i=0; i<mHistogram.size(); i++)
00151 mHistogram[i] = mHistogram[i] / mHistogram[mHistogram.size()-1];
00152 }
00153
00154 void HistogramEq::equalize (Vector& vec) const {
00155
00156
00157 if (mData.size()>0)
00158 const_cast<HistogramEq&>(*this).finalize ();
00159 ASSERTWITH (mHistogram.size(), "Histogram equalizer has not analyzed any data.");
00160
00161
00162 for (int i=0; i<vec.size(); i++)
00163 if (!is_undef (vec[i]))
00164 vec[i] = mMin+(mMax-mMin) * mHistogram[determineDomain (vec[i], mHistogram.size(), mLowBound, mUpBound)];
00165 else if (mHandleMissing)
00166 vec[i] = (mMax+mMin)/2;
00167 }
00168
00169 void HistogramEq::unequalize (Vector& vec) const {
00170
00171
00172 if (mData.size()>0)
00173 const_cast<HistogramEq&>(*this).finalize();
00174 ASSERTWITH (mHistogram.size(), "Histogram equalizer has not analyzed any data.");
00175
00176
00177 for (int i=0; i<vec.size(); i++) {
00178 if (!is_undef (vec[i])) {
00179
00180
00181
00182 double searchvalue01 = (vec[i]-mMin)/(mMax-mMin);
00183 bool found=false;
00184 for (int j=0; j<mHistogram.size()-1; j++)
00185 if ((mHistogram[j]+mHistogram[j+1])/2 > searchvalue01) {
00186
00187
00188
00189 vec[i] = mLowBound+mHistogram[j]*(mUpBound-mLowBound);
00190 found = true;
00191 break;
00192 }
00193
00194
00195
00196 if (!found)
00197 vec[i] = mUpBound;
00198 } else if (mHandleMissing)
00199 vec[i] = mLowBound+mHistogram[mHistogram.size()/2]*(mUpBound-mLowBound);
00200 }
00201 }
00202
00203 TextOStream& HistogramEq::operator>> (TextOStream& out) const
00204 {
00205 out << "<HistogramEq lowBound=" << mLowBound
00206 << " upBound=" << mUpBound
00207 << " min=" << mMin
00208 << " max=" << mMax
00209 << ">";
00210 out << "</HistogramEq>";
00211
00212 return out;
00213 }
00214
00215
00217
00218
00219
00220
00221
00222
00224
00225 GaussianEq::GaussianEq (const GaussianEq& orig)
00226 : Equalizer(orig),
00227 mAverage (orig.mAverage), mStdDev (orig.mStdDev) {
00228 }
00229
00230 void GaussianEq::analyze (const Vector& vec, bool additive) {
00231
00232 float sum=0.0;
00233 int actualPatterns=0;
00234 for (int i=0; i<vec.size(); i++)
00235 if (!is_undef (vec[i])) {
00236 sum += vec[i];
00237 actualPatterns++;
00238 }
00239 mAverage = sum/actualPatterns;
00240
00241
00242 sum=0.0;
00243 for (int i=0; i<vec.size(); i++)
00244 if (!is_undef (vec[i]))
00245 sum += sqr (vec[i]-mAverage);
00246 mStdDev = sqrt (sum / actualPatterns);
00247 }
00248
00249 void GaussianEq::equalize (Vector& vec) const {
00250 for (int i=0; i<vec.size(); i++)
00251 if (!is_undef (vec[i]))
00252 vec[i] = (vec[i] - mAverage)/mStdDev;
00253 else if (mHandleMissing)
00254 vec[i] = 0.0;
00255 }
00256
00257 void GaussianEq::unequalize (Vector& vec) const {
00258 for (int i=0; i<vec.size(); i++)
00259 if (!is_undef (vec[i]))
00260 vec[i] = (vec[i] - mAverage)/mStdDev;
00261 else if (mHandleMissing)
00262 vec[i] = mAverage;
00263 }
00264
00265
00266
00268
00269
00270
00271
00272
00273
00275
00276 MinmaxEq::MinmaxEq (double trgMin, double trgMax)
00277 {
00278 mTrgMin = trgMin;
00279 mTrgMax = trgMax;
00280 mDataMin = 1E30;
00281 mDataMax = -1E30;
00282 }
00283
00284 MinmaxEq::MinmaxEq (const MinmaxEq& orig)
00285 : Equalizer(orig),
00286 mTrgMin (orig.mTrgMin), mTrgMax (orig.mTrgMax),
00287 mDataMin (orig.mDataMin), mDataMax (orig.mDataMax)
00288 {
00289 }
00290
00291
00292
00293
00294
00295 void MinmaxEq::analyze (const Vector& vec, bool additive)
00296 {
00297 mDataMin = additive? min<double>(mDataMin,min (vec)) : min (vec);
00298 mDataMax = additive? max<double>(mDataMax,max (vec)) : max (vec);
00299 }
00300
00301 void MinmaxEq::equalize (Vector& vec) const
00302 {
00303 for (int i=0; i<vec.size(); i++)
00304 if (!is_undef (vec[i]))
00305 vec[i] = mTrgMin + (vec[i] - mDataMin)/(mDataMax-mDataMin)*(mTrgMax-mTrgMin);
00306 else if (mHandleMissing)
00307 vec[i] = (mTrgMax+mTrgMin)/2;
00308 }
00309
00310 void MinmaxEq::unequalize (Vector& vec) const
00311 {
00312 for (int i=0; i<vec.size(); i++)
00313 if (!is_undef (vec[i]))
00314 vec[i] = (vec[i]-mTrgMin)/(mTrgMax-mTrgMin)*(mDataMax-mDataMin)+mDataMin;
00315 else if (mHandleMissing)
00316 vec[i] = (mDataMax+mDataMin)/2;
00317 }
00318
00319 TextOStream& MinmaxEq::operator>> (TextOStream& out) const
00320 {
00321 out << getclassname() << " "
00322 << mDataMin << " " << mDataMax << " "
00323 << mTrgMin << " " << mTrgMax << " ";
00324 return out;
00325 }
00326
00327 TextIStream& MinmaxEq::operator<< (TextIStream& in)
00328 {
00329 in >> mDataMin >> mDataMax >> mTrgMin >> mTrgMax;
00330 return in;
00331 }
00332
00333
00335
00336
00337
00338
00339
00340
00342
00343 MatrixEqualizer::MatrixEqualizer (Equalizer* templ)
00344 {
00345
00346 if (templ)
00347 mPlaneEqualizers.add (templ);
00348 }
00349
00350 void MatrixEqualizer::analyze (const Matrix& mat, bool global)
00351 {
00352
00353 if (!global)
00354 mPlaneEqualizers.resize (mat.cols);
00355 for (int i=0; i<mat.cols; i++) {
00356 if (i>0 && !global)
00357 mPlaneEqualizers.put (mPlaneEqualizers.getp(0)->clone(), i);
00358
00359
00360 Vector plane (mat.rows);
00361 for (int j=0; j<plane.size(); j++)
00362 plane[j] = mat.get (j,i);
00363
00364
00365 mPlaneEqualizers.getp(global? 0:i)->analyze (plane, global);
00366 }
00367 }
00368
00369 void MatrixEqualizer::bothEqualize (Matrix& mat, bool uneq) const
00370 {
00371 for (int i=0; i<mat.cols; i++) {
00372 Vector plane (mat.rows);
00373
00374
00375 for (int j=0; j<plane.size(); j++)
00376 plane[j] = mat.get (j,i);
00377
00378
00379
00380
00381 const Equalizer* eq = mPlaneEqualizers.getp((mPlaneEqualizers.size() == 1 && mat.cols>1)? 0:i);
00382 if (uneq)
00383 eq->unequalize (plane);
00384 else
00385 eq->equalize (plane);
00386
00387
00388 for (int j=0; j<plane.size(); j++)
00389 mat.get (j,i) = plane[j];
00390 }
00391 }
00392
00393 void MatrixEqualizer::equalize (Matrix& mat) const
00394 {
00395 bothEqualize (mat, false);
00396 }
00397
00398 void MatrixEqualizer::unequalize (Matrix& mat) const
00399 {
00400 bothEqualize (mat, true);
00401 }
00402
00403 TextOStream& MatrixEqualizer::operator>> (TextOStream& out) const
00404 {
00405 if (false ) {
00406 out << "<planeEqualizers size="
00407 << mPlaneEqualizers.size() << ">\n";
00408 for (int i=0; i<mPlaneEqualizers.size(); i++) {
00409 out << "\t<equalizer id=" << i
00410 << " class='" << mPlaneEqualizers[i].getclassname() << "'>"
00411 << mPlaneEqualizers[i]
00412 << "</equalizer>\n";
00413 }
00414 out << "</planeEqualizers>\n";
00415 } else {
00416 out << getclassname() << " " << mPlaneEqualizers.size() << " ";
00417 for (int i=0; i<mPlaneEqualizers.size(); i++)
00418 out << mPlaneEqualizers[i];
00419 }
00420 return out;
00421 }
00422
00423 Equalizer* readEqualizer (TextIStream& in)
00424 {
00425
00426 String classname;
00427 in >> classname;
00428
00429
00430 if (Equalizer* obj = dynamic_cast<Equalizer*> (dyncreate (classname))) {
00431 (*obj) << in;
00432 return obj;
00433 } else
00434 throw invalid_format (i18n("Unexpected object class identifier '%1', class Equalizer expected.").arg(classname));
00435 }
00436
00437 TextIStream& MatrixEqualizer::operator<< (TextIStream& in)
00438 {
00439
00440 int size;
00441 in >> size;
00442 mPlaneEqualizers.make(size);
00443
00444 for (int i=0; i<size; i++)
00445 mPlaneEqualizers.put (readEqualizer(in), i);
00446
00447 return in;
00448 }
00449
00450
00451 void MatrixEqualizer::handleMissing (bool enable)
00452 {
00453 mHandleMissing = enable;
00454 for (int i=0; i < mPlaneEqualizers.size(); i++)
00455 mPlaneEqualizers[i].handleMissing (enable);
00456 }
00457