Histogram.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "SIFT/Histogram.H"
00039 #include "Image/DrawOps.H"
00040
00041
00042 Histogram::Histogram(const int size) :
00043 itsHistogram(size)
00044 { clear(); }
00045
00046
00047 Histogram::Histogram(const float* input, const int size) :
00048 itsHistogram(size)
00049 {
00050 for (int i = 0; i < size; i++) itsHistogram[i] = input[i];
00051 }
00052
00053
00054 Histogram::Histogram(std::vector<Histogram> histograms)
00055 {
00056 for(uint i = 0; i < histograms.size(); i++)
00057 {
00058 for (uint j = 0; j < histograms[i].size(); j++)
00059 itsHistogram.push_back(histograms[i][j]);
00060 }
00061 }
00062
00063
00064 Histogram::Histogram(const Image<byte>& img) :
00065 itsHistogram(256)
00066 {
00067 Image<float> hi1(img.getWidth(), img.getHeight(), ZEROS);
00068
00069 int count1 = 0, count2 = 0;
00070 const int w = img.getWidth(); int h = img.getHeight();
00071 for (int i = 0; i < w; i++)
00072 for (int j = 0; j < h; j++)
00073 {
00074 if (img.getVal(i, j) < 1)
00075 { hi1.setVal(i, j, -255); ++ count1; }
00076 else if (img.getVal(i, j) > 254)
00077 { hi1.setVal(i, j, 255); ++ count2; }
00078 itsHistogram[img.getVal(i, j)] += 1.0F;
00079 }
00080 }
00081
00082
00083 Histogram::~Histogram()
00084 { }
00085
00086
00087 void Histogram::addValue(const uint index, const float value)
00088 {
00089 if (index < itsHistogram.size())
00090 itsHistogram[index] += value;
00091 else
00092 LFATAL("Index %d out of range [0..%"ZU"]",
00093 index, itsHistogram.size()-1);
00094 }
00095
00096
00097 void Histogram::addValueInterp(const float index, const float value)
00098 {
00099 ASSERT(index >= 0.0F && index < float(itsHistogram.size()));
00100 const uint i0 = uint(index);
00101 const float di = index - float(i0);
00102 uint i1 = i0 + 1; if (i1 >= itsHistogram.size()) i1 = 0;
00103
00104 itsHistogram[i0] += value * (1.0F - di);
00105 itsHistogram[i1] += value * di;
00106 }
00107
00108
00109 void Histogram::fill(const Image<byte>& img)
00110 {
00111
00112 itsHistogram.clear();
00113 itsHistogram.resize(256);
00114
00115 int w = img.getWidth(); int h = img.getHeight();
00116 for (int i = 0; i < w; i++)
00117 for (int j = 0; j < h; j++)
00118 itsHistogram[img.getVal(i, j)] += 1.0F;
00119 }
00120
00121
00122 Image<byte> Histogram::getHistogramImage(const int w, const int h,
00123 const float mini, const float maxi)
00124 {
00125 if (uint(w) < itsHistogram.size())
00126 LFATAL("not enough width to display the histogram properly");
00127 int dw = w / itsHistogram.size();
00128
00129 Image<byte> res(w, h, ZEROS);
00130
00131
00132
00133 for (int j = 0; j < 10; j++)
00134 drawLine(res, Point2D<int>(0, int(j * 0.1F * h)),
00135 Point2D<int>(w-1, int(j * 0.1F * h)), byte(64));
00136 drawLine(res, Point2D<int>(0, h-1), Point2D<int>(w-1, h-1), byte(64));
00137
00138 float minii = mini, maxii = maxi;
00139 if (maxi == -1.0F) { minii = findMin(); maxii = findMax(); }
00140
00141
00142 if (maxii == minii) minii = maxii - 1.0F;
00143
00144 float range = maxii - minii;
00145
00146 for (uint i = 0; i < itsHistogram.size(); i++)
00147 {
00148 int t = abs(h - int((itsHistogram[i] - minii) / range * float(h)));
00149
00150
00151 if (t < h-1)
00152 {
00153 for (int j = 0; j < dw; j++)
00154 drawLine(res,
00155 Point2D<int>(dw * i + j, t),
00156 Point2D<int>(dw * i + j, h - 1),
00157 byte(255));
00158
00159 }
00160 }
00161
00162 return res;
00163 }
00164
00165
00166
00167 float Histogram::getValue(const uint index) const
00168 {
00169 if (index < itsHistogram.size()) return itsHistogram[index];
00170 LFATAL("Index %d out of range [0..%"ZU"]",
00171 index, itsHistogram.size());
00172 return 0.0F;
00173 }
00174
00175
00176 float Histogram::operator[](const uint index) const
00177 {
00178 ASSERT(index < itsHistogram.size());
00179 return itsHistogram[index];
00180 }
00181
00182
00183 void Histogram::smooth()
00184 {
00185 std::vector<float> vect(itsHistogram.size());
00186 const uint siz = itsHistogram.size();
00187
00188 for (uint n = 0 ; n < siz ; n++)
00189 {
00190 float val0 = itsHistogram[ (n-1+siz) % siz ];
00191 float val1 = itsHistogram[ (n +siz) % siz ];
00192 float val2 = itsHistogram[ (n+1+siz) % siz ];
00193
00194 vect[n] = 0.25F * (val0 + 2.0F*val1 + val2);
00195 }
00196
00197 for (uint n = 0 ; n < siz ; n++) itsHistogram[n] = vect[n];
00198 }
00199
00200
00201 void Histogram::smooth(Image<double> kernel)
00202 {
00203 ASSERT(kernel.getWidth() == 1 || kernel.getHeight() == 1);
00204 int ksize = kernel.getSize();
00205 int hksize = ksize/2;
00206
00207 int size = itsHistogram.size();
00208 std::vector<float> vect(size);
00209
00210
00211
00212
00213
00214
00215
00216
00217 for (int i = 0; i < size; i++)
00218 {
00219 float total = 0.0; float tweight = 0.0;
00220 for (int j = -hksize; j <= hksize; j++)
00221 {
00222 int k = i+j; int l = j+hksize;
00223 if(k >= 0 && k < size)
00224 {
00225 float weight = kernel.getVal(l);
00226 total += itsHistogram[k]*weight;
00227 tweight += weight;
00228 }
00229 vect[i] = total;
00230 }
00231
00232
00233 }
00234 for (int i = 0; i < size; i++) itsHistogram[i] = vect[i];
00235
00236
00237
00238
00239
00240
00241
00242 }
00243
00244
00245 float Histogram::findMax() const
00246 {
00247 float maxi = itsHistogram[0];
00248 for (uint n = 1 ; n < itsHistogram.size() ; n++)
00249 if (itsHistogram[n] > maxi) maxi = itsHistogram[n];
00250 return maxi;
00251 }
00252
00253
00254 void Histogram::findMax(int &max_loc, float &max_val)
00255 {
00256 max_val = itsHistogram[0];
00257 max_loc = 0;
00258
00259 for (uint n = 1 ; n < itsHistogram.size() ; n++)
00260 if (itsHistogram[n] > max_val){
00261 max_val = itsHistogram[n];
00262 max_loc = n;
00263 }
00264 }
00265
00266
00267 float Histogram::findMin() const
00268 {
00269 float mini = itsHistogram[0];
00270 for (uint n = 1 ; n < itsHistogram.size() ; n++)
00271 if (itsHistogram[n] < mini) mini = itsHistogram[n];
00272 return mini;
00273 }
00274
00275
00276 void Histogram::findMinMax(double &min, double &max)
00277 {
00278 max = itsHistogram[0];
00279 min = max;
00280 for (uint n = 1 ; n < itsHistogram.size() ; n++)
00281 {
00282 if (itsHistogram[n] > max) max = itsHistogram[n];
00283 if (itsHistogram[n] < min) min = itsHistogram[n];
00284 }
00285 }
00286
00287
00288
00289 void Histogram::clear()
00290 {
00291 int size = itsHistogram.size();
00292 itsHistogram.clear();
00293 itsHistogram.resize(size, 0);
00294 }
00295
00296
00297 void Histogram::resize(uint size)
00298 {
00299 itsHistogram.clear();
00300 itsHistogram.resize(size);
00301 }
00302
00303
00304 int Histogram::getSize()
00305 {
00306 return itsHistogram.size();
00307 }
00308
00309 uint Histogram::size() const
00310 {
00311 return itsHistogram.size();
00312 }
00313
00314
00315 void Histogram::normalize(double sum)
00316 {
00317 if (sum == -1)
00318 {
00319 sum = 0;
00320 for(uint i=0; i<itsHistogram.size(); i++)
00321 sum += itsHistogram[i];
00322 }
00323
00324 for(uint i=0; i<itsHistogram.size(); i++)
00325 itsHistogram[i] /= sum;
00326 }
00327
00328
00329 double Histogram::getDistance(const Histogram& hist)
00330 {
00331 if (hist.size() > itsHistogram.size())
00332 LFATAL("Incomputable histograms");
00333 double sum = 0;
00334
00335 for(uint i=0; i<itsHistogram.size(); i++)
00336 {
00337
00338 sum += fabs(itsHistogram[i]-hist[i]);
00339
00340
00341
00342
00343 }
00344
00345 return sum;
00346 }
00347
00348
00349 float Histogram::getChiSqDiff(Histogram hist2)
00350 {
00351 ASSERT(itsHistogram.size() == hist2.size());
00352
00353
00354 float diff = 0.0;
00355 for(uint i = 0; i < hist2.size(); i++)
00356 {
00357 float dif = itsHistogram[i] - hist2[i];
00358 float sum = itsHistogram[i] + hist2[i];
00359 if(sum != 0.0F) diff += (dif*dif)/sum;
00360
00361
00362
00363 }
00364 diff = diff/2.0;
00365
00366 return diff;
00367 }
00368
00369
00370 void Histogram::divide(float div)
00371 {
00372 for(uint i = 0; i < itsHistogram.size(); i++)
00373 {
00374
00375 itsHistogram[i] = itsHistogram[i]/div;
00376
00377 }
00378 }
00379
00380
00381
00382
00383
00384