00001
00017 #include "vetHist.h"
00018 #include <math.h>
00019
00020 #include <stdio.h>
00021 #include <fstream>
00022
00023
00024
00025 vetHist::vetHist()
00026 {
00027 freqHist = NULL;
00028 probHist = NULL;
00029 reset();
00030 }
00031
00032 vetHist::vetHist(int MinValue, int MaxValue)
00033 {
00034 freqHist = NULL;
00035 probHist = NULL;
00036 reset(MinValue, MaxValue);
00037 }
00038
00039
00040 vetHist::vetHist(vetFrameYUV420& img, vetFrameYUV420::ChannelYUV channel)
00041 {
00042 freqHist = NULL;
00043 probHist = NULL;
00044
00045 fromImage(img, channel);
00046 }
00047
00048 vetHist::vetHist(vetFrameRGB24& img, vetFrameRGB24::ChannelRGB channel)
00049 {
00050 freqHist = NULL;
00051 probHist = NULL;
00052
00053 fromImage(img, channel);
00054 }
00055
00056 vetHist::~vetHist()
00057 {
00058
00059 if ( freqHist != NULL )
00060 delete [] freqHist;
00061
00062 if ( probHist != NULL )
00063 delete [] probHist;
00064
00065
00066 }
00067
00068
00069
00070 VETRESULT vetHist::reset()
00071 {
00072
00073 valMax = 0;
00074 valMin = 0;
00075 valBandwidth = 0;
00076 valCount = 0;
00077
00078 valSum = 0;
00079 valSum2 = 0;
00080
00081
00082 if ( freqHist != NULL )
00083 delete [] freqHist;
00084
00085 freqMax = 0;
00086 freqMin = 0;
00087
00088 if ( probHist != NULL )
00089 delete [] probHist;
00090
00091 probMax = 0;
00092 probMin = 0;
00093
00094 return VETRET_OK;
00095 }
00096
00097
00098 VETRESULT vetHist::reset(int MinValue, int MaxValue)
00099 {
00100 reset();
00101 valMax = MaxValue;
00102 valMin = MinValue;
00103 valCount = 0;
00104
00105 valBandwidth = abs(valMax - valMin+1);
00106
00107 if ( freqHist != NULL )
00108 delete [] freqHist;
00109 freqHist = new unsigned int[valBandwidth];
00110
00111 freqMax = 0;
00112 freqMin = 0;
00113
00114 if ( probHist != NULL )
00115 delete [] probHist;
00116 probHist = new float[valBandwidth];
00117
00118 probMax = 0;
00119 probMin = 0;
00120
00121 for (int i=0; i < valBandwidth; i++)
00122 {
00123 probHist[i] = 0.0;
00124 freqHist[i] = 0;
00125 }
00126
00127 return VETRET_OK;
00128 }
00129
00130 VETRESULT vetHist::addValue(int data)
00131 {
00132 if ( data < valMin || data > valMax)
00133 return VETRET_PARAM_ERR;
00134
00135 if ( valBandwidth == 0 )
00136 return VETRET_ILLEGAL_USE;
00137
00138 int offset = data - valMin;
00139
00140 freqHist[offset]++;
00141 valCount++;
00142
00143 valSum += data;
00144 valSum2 += data * data;
00145
00146
00147 if ( freqMax < freqHist[offset])
00148 freqMax = freqHist[offset];
00149
00150 if ( freqMin > freqHist[offset])
00151 freqMin = freqHist[offset];
00152
00153 return VETRET_OK;
00154 }
00155
00156 VETRESULT vetHist::addData(int *data, int size)
00157 {
00158
00159 if ( data == NULL || size == 0)
00160 return VETRET_PARAM_ERR;
00161
00162 if ( valBandwidth == 0 )
00163 return VETRET_ILLEGAL_USE;
00164
00165 int offset;
00166 for (int i=0; i<size; i++)
00167 {
00168 offset = data[i] - valMin;
00169
00170 freqHist[offset]++;
00171 valCount++;
00172
00173 valSum += data[i];
00174 valSum2 += data[i] * data[i];
00175
00176 if ( freqMax < freqHist[offset])
00177 freqMax = freqHist[offset];
00178
00179 if ( freqMin > freqHist[offset])
00180 freqMin = freqHist[offset];
00181 }
00182
00183 return VETRET_OK;
00184
00185 }
00186
00187
00188 VETRESULT vetHist::fromImage(vetFrameYUV420& img, vetFrameYUV420::ChannelYUV channel)
00189 {
00190 reset( 0, (int)pow((float)2.0, (float) (1<<sizeof(int)) ) );
00191
00192 unsigned int offset;
00193 unsigned int start, end;
00194
00195 if ( channel == vetFrameYUV420::Lum )
00196 {
00197 start = 0;
00198 end = img.width*img.height;
00199 }
00200 else if ( channel == vetFrameYUV420::Cb )
00201 {
00202 start = img.width*img.height;
00203 end = (unsigned int)(img.width*img.height*1.25);
00204 }
00205 else if ( channel == vetFrameYUV420::Cr )
00206 {
00207 start = img.width*img.height;
00208 end = (unsigned int)(img.width*img.height*1.5);
00209 }
00210 else
00211 {
00212 reset();
00213 return VETRET_PARAM_ERR;
00214 }
00215 for (unsigned int i=start; i<end; i++)
00216 {
00217
00218 offset = img.data[i];
00219
00220 freqHist[offset]++;
00221 valCount++;
00222
00223 valSum += offset;
00224 valSum2 += offset * offset;
00225
00226 if ( freqMax < freqHist[offset])
00227 freqMax = freqHist[offset];
00228
00229 if ( freqMin > freqHist[offset])
00230 freqMin = freqHist[offset];
00231
00232 }
00233
00234 extractProbs();
00235
00236 return VETRET_OK;
00237
00238 }
00239
00240
00241 VETRESULT vetHist::fromImage(vetFrameRGB24& img, vetFrameRGB24::ChannelRGB channel)
00242 {
00243
00244 reset( 0, 255 );
00245
00246
00247
00248
00249 int offset;
00250
00251 for (unsigned int i=0; i<img.width*img.height; i++)
00252 {
00253 offset = (unsigned int)img.data[i][channel];
00254
00255 freqHist[offset]++;
00256 valCount++;
00257
00258 valSum += offset;
00259 valSum2 += offset * offset;
00260
00261 if ( freqMax < freqHist[offset])
00262 freqMax = freqHist[offset];
00263
00264 if ( freqMin > freqHist[offset])
00265 freqMin = freqHist[offset];
00266
00267 }
00268
00269 extractProbs();
00270
00271 return VETRET_OK;
00272 }
00273
00274
00275
00276
00277 VETRESULT vetHist::extractProbs()
00281 {
00282 if ( freqHist == NULL || probHist == NULL )
00283 return VETRET_ILLEGAL_USE;
00284
00285 if ( valBandwidth == 0 )
00286 return VETRET_ILLEGAL_USE;
00287
00288
00289 probMax = 0;
00290 probMin = 1;
00291
00292 for (int i=0; i < valBandwidth; i++)
00293 {
00294 probHist[i] = (float)freqHist[i] / (float)valCount;
00295
00296 if ( probHist[i] > probMax )
00297 probMax = probHist[i];
00298
00299 if ( probHist[i] < probMin )
00300 probMin = probHist[i];
00301
00302 }
00303
00304 return VETRET_OK;
00305 }
00306
00307
00308
00309
00310 float vetHist::extractDifference(vetHist *compareHist)
00317 {
00318
00319 if ( valBandwidth == 0 )
00320 return VETRET_ILLEGAL_USE;
00321
00322 extractProbs();
00323 compareHist->extractProbs();
00324
00325 float diffTmp = 0;
00326 float diff = 0;
00327
00328 for (int i=0; i < valBandwidth; i++)
00329 {
00330 diffTmp = probHist[i] - compareHist->probHist[i];
00331
00332 if ( diffTmp < 0.0 )
00333 diff -= diffTmp;
00334 else
00335 diff += diffTmp;
00336
00337 }
00338
00339 return diff;
00340 }
00341
00342
00343 float vetHist::getMean() const
00344 {
00345 return valSum/(double)valCount;
00346 }
00347
00348 float vetHist::getVariance() const
00349 {
00350 float n = (double)valCount;
00351 return (n*valSum2 - valSum*valSum)/(n*n);
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 unsigned char graphBackground[] = { 12,23
00375
00376 };
00377
00378 VETRESULT vetHist::drawGraph(vetFrameRGB24& img)
00379 {
00380
00381 unsigned int upperBorder = 35;
00382 unsigned int bottomBorder = 45;
00383 unsigned int leftBorder = 100;
00384 bool fillCol = true;
00385
00386 if (img.width < leftBorder+255)
00387 return VETRET_ILLEGAL_USE;
00388
00389 if ( freqHist == NULL )
00390 return VETRET_ILLEGAL_USE;
00391
00392 PixelRGB24 black(0,0,0);
00393 PixelRGB24 grey(192,192,192);
00394 PixelRGB24 back(255,255,255);
00395
00396 img.clearWith(back);
00397
00398 unsigned int y;
00399 float scale = (float)(img.height-(upperBorder+bottomBorder)) / (float)freqMax;
00400 unsigned int offset = img.height * img.width - bottomBorder * img.width + leftBorder;
00401
00402 printf("value %d\n" , offset);
00403
00404 for (unsigned int x=0; x<255; x++)
00405 {
00406 y = (unsigned int)( (float)freqHist[x] * scale);
00407
00408
00409
00410 img.data[offset + x - y * img.width] = black;
00411
00412 if (fillCol)
00413 while (y++ < (img.height-upperBorder-bottomBorder))
00414 img.data[offset + x - y * img.width] = grey;
00415
00416 }
00417
00418 return VETRET_OK;
00419 }
00420
00421
00422
00423
00424 VETRESULT vetHist::saveToXML(const char* filename)
00428 {
00429 FILE *fp;
00430 int ret = VETRET_OK;
00431
00432 if ( valBandwidth == 0 )
00433 return VETRET_INTERNAL_ERR;
00434
00435 if ( (fp = fopen(filename, "w")) == NULL )
00436 return VETRET_PARAM_ERR;
00437
00438 ret = extractProbs();
00439
00440 if ( ret != VETRET_OK )
00441 return ret;
00442
00443 if( fprintf(fp, "<?xml version=\"1.0\" ?>\n\n") == EOF )
00444 {
00445 fclose(fp);
00446 return VETRET_INTERNAL_ERR;
00447 }
00448
00449 if( fprintf(fp, "<histogram value-count=\"%i\" min-value=\"%i\" max-value=\"%i\">\n", valCount, valMin, valMax) == EOF )
00450 {
00451 fclose(fp);
00452 return VETRET_INTERNAL_ERR;
00453 }
00454
00455 if (!extractProbs())
00456 for (int i=0; i < valBandwidth; i++)
00457 {
00458 if ( fprintf(fp, " <prob index=\"%u\">%f</prob>\n", i, probHist[i]) == EOF)
00459 ret = VETRET_INTERNAL_ERR;
00460 }
00461 else
00462 ret = VETRET_INTERNAL_ERR;
00463
00464 if ( fprintf(fp, "</histogram>\n") == EOF)
00465 ret = VETRET_INTERNAL_ERR;
00466
00467 fclose(fp);
00468
00469 return ret;
00470 }
00471
00472
00473 VETRESULT vetHist::loadFromXML(const char* filename)
00477 {
00478 FILE *fp;
00479 int ret = VETRET_OK;
00480
00481 if ( (fp=fopen(filename,"r")) == NULL )
00482 return VETRET_PARAM_ERR;
00483
00484 int n;
00485
00486
00487
00488 float xmlversion = 0;
00489
00490 n = fscanf(fp, "<?xml version=\"%f\" ?>\n\n", &xmlversion);
00491
00492 if (xmlversion == 0)
00493 throw "Incompatible hst file format";
00494
00495
00496
00497
00498 n = fscanf(fp, "<histogram value-count=\"%i\" min-value=\"%i\" max-value=\"%i\">\n", &valCount, &valMin, &valMax);
00499
00500 if (n != 4)
00501 throw "error in hst file, unable to import data.";
00502
00503 reset(valMin, valMax);
00504
00505 unsigned int i = 0;
00506 float p = 0;
00507
00508 while (n == 2)
00509 {
00510 n = fscanf(fp, " <prob index=\"%u\">%f</prob>\n", &i, &p);
00511 probHist[i] = p;
00512 }
00513
00514
00515 char last[2];
00516 n = fscanf(fp, "/histogram%[>]", last);
00517
00518 if (n != 1)
00519 throw "Reading hst file.";
00520
00521 fclose(fp);
00522
00523 return ret;
00524 }