00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _VISUALHISTOGRAMDESC_H_
00019 #define _VISUALHISTOGRAMDESC_H_
00020
00021 #include "Object.h"
00022 #include <iostream>
00023 #include <math.h>
00024 #include "VisualFeatureDesc.h"
00025 #include "VisualROI.h"
00026 #include "Vector.h"
00027
00028 namespace RobotFlow {
00029
00030 typedef enum
00031 {
00032 e_VISUALHIST_BhattacharyyaCoeff = 0,
00033 e_VISUALHIST_BhattacharyyaDist,
00034 e_VISUALHIST_HistIntersection,
00035 e_VISUALHIST_EuclideanDist,
00036
00037 e_VISUALHIST_unknownSimilarity
00038 } e_VISUALHIST_similarityType;
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 template <class BinType, class FeatType>
00051 class VisualHistogramDesc : public VisualFeatureDesc<BinType>
00052 {
00053 public:
00054 static const double k_VISUALHIST_2DIVPI;
00055
00056 VisualHistogramDesc()
00057 : VisualFeatureDesc<BinType>(e_VISUALDESCRIPTOR_histogram),
00058 m_simType(e_VISUALHIST_unknownSimilarity),
00059 m_valid(false),
00060 m_normFlag(false),
00061 m_numDimensions(0),
00062 m_numBins(NULL),
00063 m_binsWidth(NULL),
00064 m_bins(NULL)
00065 {
00066 }
00067
00068 VisualHistogramDesc(e_VISUALHIST_similarityType i_simType,
00069 bool i_normFlag, unsigned int i_numDimensions,
00070 const FD::Vector<int> *i_numBins)
00071 : VisualFeatureDesc<BinType>(e_VISUALDESCRIPTOR_histogram),
00072 m_simType(i_simType),
00073 m_valid(true),
00074 m_normFlag(i_normFlag),
00075 m_numDimensions(i_numDimensions),
00076 m_numBins(NULL),
00077 m_binsWidth(NULL),
00078 m_bins(NULL)
00079 {
00080 unsigned int totalBins = 1;
00081 m_numBins = new int[m_numDimensions];
00082
00083 for(int d=0; d<m_numDimensions; d++) {
00084 m_numBins[d] = (*i_numBins)[d];
00085 totalBins *= m_numBins[d];
00086 }
00087
00088 m_totalBins = totalBins;
00089 m_bins = new BinType[m_totalBins];
00090
00091 m_binsWidth = new FeatType[m_numDimensions];
00092 m_lastMaxVal = (FeatType)0;
00093
00094 SetSimilarityFct();
00095
00096 SetAdaptFct();
00097 }
00098
00099 VisualHistogramDesc(const VisualHistogramDesc<BinType,FeatType> &i_ref)
00100 : m_numBins(NULL),
00101 m_binsWidth(NULL),
00102 m_bins(NULL)
00103 {
00104 this->SetType(i_ref.GetType());
00105 m_valid = i_ref.m_valid;
00106 m_simType = i_ref.m_simType;
00107 m_normFlag = i_ref.m_normFlag;
00108
00109 SetSimilarityFct();
00110
00111 SetAdaptFct();
00112
00113 m_numDimensions = i_ref.m_numDimensions;
00114 m_numBins = new int[m_numDimensions];
00115 m_totalBins = i_ref.m_totalBins;
00116 m_bins = new BinType[m_totalBins];
00117 m_binsWidth = new FeatType[m_numDimensions];
00118
00119 m_lastMaxVal = i_ref.m_lastMaxVal;
00120
00121 for (int i=0; i<m_numDimensions; ++i) {
00122 m_binsWidth[i] = i_ref.m_binsWidth[i];
00123 }
00124
00125 for(int d=0; d<m_numDimensions; d++) {
00126 m_numBins[d] = i_ref.m_numBins[d];
00127 }
00128
00129 for (int b=0; b<m_totalBins; b++) {
00130 m_bins[b] = i_ref.m_bins[b];
00131 }
00132 }
00133
00134 ~VisualHistogramDesc()
00135 {
00136 delete [] m_numBins;
00137 delete [] m_binsWidth;
00138 delete [] m_bins;
00139 }
00140
00141 VisualHistogramDesc<BinType,FeatType> & operator =(const VisualHistogramDesc<BinType,FeatType> &i_ref)
00142 {
00143
00144 if (&i_ref == this) {
00145 return *this;
00146 }
00147
00148 this->SetType(i_ref.GetType());
00149 m_simType = i_ref.m_simType;
00150 m_valid = i_ref.m_valid;
00151 m_normFlag = i_ref.m_normFlag;
00152
00153 SetSimilarityFct();
00154
00155 SetAdaptFct();
00156
00157
00158 if (m_numDimensions != i_ref.m_numDimensions) {
00159 delete [] m_numBins;
00160 delete [] m_binsWidth;
00161
00162 m_numDimensions = i_ref.m_numDimensions;
00163 m_numBins = new int[m_numDimensions];
00164 m_binsWidth = new FeatType[m_numDimensions];
00165 }
00166
00167 if (m_totalBins != i_ref.m_totalBins) {
00168 delete [] m_bins;
00169 m_totalBins = i_ref.m_totalBins;
00170 m_bins = new BinType[m_totalBins];
00171 }
00172
00173 m_lastMaxVal = i_ref.m_lastMaxVal;
00174
00175 for (int i=0; i<m_numDimensions; ++i) {
00176 m_binsWidth[i] = i_ref.m_binsWidth[i];
00177 }
00178
00179 for(int d=0; d<m_numDimensions; d++) {
00180 m_numBins[d] = i_ref.m_numBins[d];
00181 }
00182
00183 for (int b=0; b<m_totalBins; b++) {
00184 m_bins[b] = i_ref.m_bins[b];
00185 }
00186
00187 return *this;
00188 }
00189
00190 VisualHistogramDesc<BinType,FeatType>* clone() const
00191 {
00192 return new VisualHistogramDesc<BinType,FeatType>(*this);
00193 }
00194
00195
00196 void printOn(std::ostream &out) const
00197 {
00198 int b, d;
00199 out << "<VisualHistogramDesc " << std::endl;
00200 out << "<NumDimensions " << m_numDimensions << " >" << std::endl;
00201 out << "<TotalBins " << m_totalBins << " >" << std::endl;
00202 out << "<SimilarityType " << (int)m_simType << " >" << std::endl;
00203 out << "<Validity " << (int)m_valid << " >" << std::endl;
00204 out << "<NormFlag " << (int)m_normFlag << " >" << std::endl;
00205 out << "<LastMaxVal " << m_lastMaxVal << " >" << std::endl;
00206
00207 out << "<NumBins " << std::endl;
00208 for (d=0; d<m_numDimensions; d++) {
00209 out << m_numBins[d] << " ";
00210 }
00211 out << " >" << std::endl;
00212
00213 out << "<BinsWidth " << std::endl;
00214 for (d=0; d<m_numDimensions; d++) {
00215 out << m_binsWidth[d] << " ";
00216 }
00217 out << " >" << std::endl;
00218
00219 out << "<Bins " << std::endl;
00220 for (b=0; b<m_totalBins; ++b) {
00221 out << m_bins[b] << " ";
00222 }
00223 out << " >" << std::endl;
00224
00225 out << " >" << std::endl;
00226 }
00227
00228
00229 void readFrom(std::istream &in)
00230 {
00231 std::string tag;
00232
00233 while (1) {
00234 char ch;
00235 in >> ch;
00236
00237 if (ch == '>') {
00238 break;
00239 }
00240 else if (ch != '<') {
00241 throw new FD::GeneralException ("VisualHistogramDesc::readFrom : Parse error: '<' expected",__FILE__,__LINE__);
00242 }
00243
00244 in >> tag;
00245
00246 if (tag == "VisualHistogramDesc") {
00247 continue;
00248 }
00249 else if (tag == "NumDimensions") {
00250 in >> m_numDimensions;
00251
00252 if (m_numDimensions < 1) {
00253 throw new FD::GeneralException ("VisualHistogramDesc::readFrom : invalid number of dimensions",__FILE__,__LINE__);
00254 }
00255 }
00256 else if (tag == "TotalBins") {
00257 in >> m_totalBins;
00258
00259 if (m_totalBins < 1) {
00260 throw new FD::GeneralException ("VisualHistogramDesc::readFrom : invalid total number of bins",__FILE__,__LINE__);
00261 }
00262 }
00263 else if (tag == "SimilarityType") {
00264 int val;
00265 in >> val;
00266 m_simType = e_VISUALHIST_similarityType(val);
00267
00268 SetSimilarityFct();
00269 }
00270 else if (tag == "Validity") {
00271 int val;
00272 in >> val;
00273 m_valid = bool(val);
00274 }
00275 else if (tag == "NormFlag") {
00276 int val;
00277 in >> val;
00278 m_normFlag = bool(val);
00279
00280 SetAdaptFct();
00281 }
00282 else if (tag == "LastMaxVal") {
00283 in >> m_lastMaxVal;
00284 }
00285 else if (tag == "NumBins") {
00286
00287 delete [] m_numBins;
00288 m_numBins = new int[m_numDimensions];
00289
00290 for (int d=0; d<m_numDimensions; d++) {
00291 in >> m_numBins[d];
00292 }
00293 }
00294 else if (tag == "BinsWidth") {
00295
00296 delete [] m_binsWidth;
00297 m_binsWidth = new FeatType[m_numDimensions];
00298
00299 for (int d=0; d<m_numDimensions; d++) {
00300 in >> m_binsWidth[d];
00301 }
00302 }
00303 else if (tag == "Bins") {
00304
00305 delete [] m_bins;
00306 m_bins = new BinType[m_totalBins];
00307
00308 for (int b=0; b<m_totalBins; b++) {
00309 in >> m_bins[b];
00310 }
00311 }
00312 else {
00313 throw new FD::GeneralException ("VisualHistogramDesc::readFrom : Unknown argument: " + tag,__FILE__,__LINE__);
00314 }
00315
00316 if (!in) {
00317 throw new FD::GeneralException ("VisualHistogramDesc::readFrom : Parse error trying to build " + tag,__FILE__,__LINE__);
00318 }
00319
00320 in >> tag;
00321 if (tag != ">") {
00322 throw new FD::GeneralException ("VisualHistogramDesc::readFrom : Parse error: '>' expected ",__FILE__,__LINE__);
00323 }
00324 }
00325 }
00326
00327 double Similarity(const BinType *i_candidate, unsigned int i_size) const
00328 {
00329 try {
00330 if (m_totalBins != i_size ) {
00331 throw new FD::GeneralException ("VisualHistogramDesc::Similarity : number of histogram bins differs from current descriptor",__FILE__,__LINE__);
00332 }
00333
00334 if (!m_valid) {
00335
00336 return 0.0;
00337 }
00338
00339
00340 return (this->*m_similarityFct)(i_candidate);
00341 }
00342 catch (FD::BaseException *e) {
00343 throw e->add(new FD::GeneralException("Exception caught in VisualHistogramDesc::Similarity:",__FILE__,__LINE__));
00344 }
00345 }
00346
00347 void Adapt(const BinType *i_candidate, unsigned int i_size, double i_rate)
00348 {
00349 try {
00350 if (m_totalBins != i_size ) {
00351 throw new FD::GeneralException ("VisualHistogramDesc::Adapt : number of histogram bins differs from current descriptor",__FILE__,__LINE__);
00352 }
00353
00354 if (i_rate < 0.0 || i_rate > 1.0) {
00355 throw new FD::GeneralException ("VisualHistogramDesc::Adapt : adaptation rate must be in the interval [0.0,1.0]",__FILE__,__LINE__);
00356 }
00357
00358 if (i_rate == 0.0) {
00359
00360 return;
00361 }
00362
00363 if (i_rate == 1.0) {
00364 SetFeatures(i_candidate, i_size);
00365 return;
00366 }
00367
00368
00369 (this->*m_adaptFct)(i_candidate, i_rate);
00370 }
00371 catch (FD::BaseException *e) {
00372 throw e->add(new FD::GeneralException("Exception caught in VisualHistogramDesc::Adapt:",__FILE__,__LINE__));
00373 }
00374 }
00375
00376 void ComputeHistStd(const FeatType* i_featMap, FeatType i_maxValPlusOne,
00377 BinType i_binIncScale, int i_width, int i_height, const VisualROI *i_roi)
00378 {
00379 if (!m_bins) {
00380 throw new FD::GeneralException ("VisualHistogramDesc::ComputeHistStd : histogram bins must be initialized.",__FILE__,__LINE__);
00381 }
00382
00383 int hx=i_roi->GetHSX(), hy=i_roi->GetHSY();
00384 int xCen = i_roi->GetXCen();
00385 int yCen = i_roi->GetYCen();
00386 const FeatType *p_features;
00387 const unsigned char *p_mask = i_roi->GetCstMask();
00388 int val, fact, indx, maskLeftOffset, maskRightOffset;
00389 int x, y, i, j, numFeatures, xLeftOffset, xRightOffset, yTopOffset, yBottomOffset;
00390 BinType weightSum = (BinType)0;
00391
00392 if (m_lastMaxVal != i_maxValPlusOne) {
00393 m_lastMaxVal = i_maxValPlusOne;
00394
00395 for (i=0; i<m_numDimensions; ++i) {
00396 m_binsWidth[i] = (FeatType)((double)i_maxValPlusOne/(double)m_numBins[i] + 0.5);
00397 }
00398 }
00399
00400 for (i=0; i<m_totalBins; ++i) {
00401 m_bins[i] = (BinType)(0);
00402 }
00403
00404
00405 if (xCen-hx < 0) {
00406 xLeftOffset = 0;
00407 maskLeftOffset = hx-xCen;
00408 }
00409 else {
00410 xLeftOffset = xCen-hx;
00411 maskLeftOffset = 0;
00412 }
00413
00414 if (xCen+hx > i_width-1) {
00415 xRightOffset = i_width-1;
00416 maskRightOffset = xCen+hx - i_width-1;
00417 }
00418 else {
00419 xRightOffset = xCen+hx;
00420 maskRightOffset = 0;
00421 }
00422
00423 if (yCen-hy < 0) {
00424 yTopOffset = 0;
00425 p_mask += (hy-yCen)*(2*hx+1);
00426 }
00427 else {
00428 yTopOffset = yCen-hy;
00429 }
00430
00431 if (yCen+hy > i_height-1) {
00432 yBottomOffset = i_height-1;
00433 }
00434 else {
00435 yBottomOffset = yCen+hy;
00436 }
00437
00438 p_features = (const FeatType *)(i_featMap + m_numDimensions*(yTopOffset*i_width + xLeftOffset));
00439
00440
00441
00442 for (y=yTopOffset; y<=yBottomOffset; y++) {
00443 numFeatures = 0;
00444 p_mask += maskLeftOffset;
00445
00446 for (x=xLeftOffset; x<=xRightOffset; x++) {
00447 if (*p_mask++) {
00448 indx = 0;
00449
00450 for (i=0; i<m_numDimensions; ++i) {
00451 fact = 1;
00452
00453 val = (*p_features)/m_binsWidth[i];
00454 p_features++;
00455
00456 for (j=i; j>0; --j) {
00457 fact *= m_numBins[j-1];
00458 }
00459
00460 indx += val*fact;
00461 }
00462
00463 if (indx < 0 || indx >= m_totalBins) {
00464 throw new FD::GeneralException ("VisualHistogramDesc::ComputeHistStd : invalid histogram bin index",__FILE__,__LINE__);
00465 }
00466
00467 m_bins[indx]++;
00468 weightSum++;
00469 }
00470 else {
00471 p_features += m_numDimensions;
00472 }
00473
00474 numFeatures++;
00475 }
00476
00477 p_features += m_numDimensions*(i_width-numFeatures);
00478 p_mask += maskRightOffset;
00479 }
00480
00481 if (m_normFlag) {
00482 NormalizeBins(weightSum);
00483 }
00484 }
00485
00486 void ComputeKernelWeightedHist(const FeatType* i_featMap, FeatType i_maxValPlusOne,
00487 BinType i_binIncScale, int i_width, int i_height, const VisualROI *i_roi)
00488 {
00489 if (!m_bins) {
00490 throw new FD::GeneralException ("VisualHistogramDesc::ComputeKernelWeightedHist : histogram bins must be initialized.",__FILE__,__LINE__);
00491 }
00492
00493 int hx=i_roi->GetHSX(), hy=i_roi->GetHSY();
00494 int xCen = i_roi->GetXCen();
00495 int yCen = i_roi->GetYCen();
00496 const FeatType *p_features;
00497 const unsigned char *p_mask = i_roi->GetCstMask();
00498 int val, fact, indx, maskLeftOffset, maskRightOffset;
00499 int x, y, i, j, numFeatures, xLeftOffset, xRightOffset, yTopOffset, yBottomOffset;
00500 double xnorm, ynorm, weight;
00501 BinType weightSum = (BinType)0;
00502
00503 if (m_lastMaxVal != i_maxValPlusOne) {
00504 m_lastMaxVal = i_maxValPlusOne;
00505
00506 for (i=0; i<m_numDimensions; ++i) {
00507 m_binsWidth[i] = (FeatType)round((double)i_maxValPlusOne/(double)m_numBins[i] + 0.5);
00508 }
00509 }
00510
00511 for (i=0; i<m_totalBins; ++i) {
00512 m_bins[i] = (BinType)(0);
00513 }
00514
00515
00516 if (xCen-hx < 0) {
00517 xLeftOffset = 0;
00518 maskLeftOffset = hx-xCen;
00519 }
00520 else {
00521 xLeftOffset = xCen-hx;
00522 maskLeftOffset = 0;
00523 }
00524
00525 if (xCen+hx > i_width-1) {
00526 xRightOffset = i_width-1;
00527 maskRightOffset = xCen+hx - i_width-1;
00528 }
00529 else {
00530 xRightOffset = xCen+hx;
00531 maskRightOffset = 0;
00532 }
00533
00534 if (yCen-hy < 0) {
00535 yTopOffset = 0;
00536 p_mask += (hy-yCen)*(2*hx+1);
00537 }
00538 else {
00539 yTopOffset = yCen-hy;
00540 }
00541
00542 if (yCen+hy > i_height-1) {
00543 yBottomOffset = i_height-1;
00544 }
00545 else {
00546 yBottomOffset = yCen+hy;
00547 }
00548
00549 p_features = (const FeatType *)(i_featMap + m_numDimensions*(yTopOffset*i_width + xLeftOffset));
00550
00551
00552
00553
00554
00555 for (y=yTopOffset; y<=yBottomOffset; y++) {
00556 numFeatures = 0;
00557 p_mask += maskLeftOffset;
00558
00559 for (x=xLeftOffset; x<=xRightOffset; x++) {
00560 if (*p_mask++) {
00561 indx = 0;
00562
00563 for (i=0; i<m_numDimensions; ++i) {
00564 fact = 1;
00565
00566 val = (*p_features)/m_binsWidth[i];
00567 p_features++;
00568
00569 for (j=i; j>0; --j) {
00570 fact *= m_numBins[j-1];
00571 }
00572
00573 indx += val*fact;
00574 }
00575
00576 if (indx < 0 || indx >= m_totalBins) {
00577 throw new FD::GeneralException ("VisualHistogramDesc::ComputeKernelWeightedHist : invalid histogram bin index",__FILE__,__LINE__);
00578 }
00579
00580
00581
00582 xnorm = (double)(x-xCen)/(double)(hx);
00583 ynorm = (double)(y-yCen)/(double)(hy);
00584
00585
00586
00587 weight = EpanechKernel(xnorm*xnorm + ynorm*ynorm);
00588 BinType histWeight = (BinType)(weight*(double)(i_binIncScale));
00589 weightSum += histWeight;
00590
00591 m_bins[indx] += histWeight;
00592 }
00593 else {
00594 p_features += m_numDimensions;
00595 }
00596
00597 numFeatures++;
00598 }
00599
00600 p_features += m_numDimensions*(i_width-numFeatures);
00601 p_mask += maskRightOffset;
00602 }
00603
00604 if (m_normFlag && weightSum) {
00605 NormalizeBins(weightSum);
00606 }
00607 }
00608
00609 void ComputeMSLocation(const FeatType* i_featMap, FeatType i_maxValPlusOne,
00610 BinType i_binIncScale, int i_width, int i_height, const VisualROI *i_roi,
00611 const BinType *i_refBins, double i_cueWeight, FD::Vector<double> *o_msLoc)
00612 {
00613 if (!m_bins) {
00614 throw new FD::GeneralException ("VisualHistogramDesc::ComputeMSLocation : histogram bins must be initialized.",__FILE__,__LINE__);
00615 }
00616
00617 int hx=i_roi->GetHSX(), hy=i_roi->GetHSY();
00618 int xCen = i_roi->GetXCen();
00619 int yCen = i_roi->GetYCen();
00620 const FeatType *p_features;
00621 const unsigned char *p_mask = i_roi->GetCstMask();
00622 int val, fact, indx, maskLeftOffset, maskRightOffset;
00623 int x, y, i, j, numFeatures, xLeftOffset, xRightOffset, yTopOffset, yBottomOffset;
00624 double xnorm, ynorm;
00625 double tmpRef, tmpCand, posWeight, kernWeight;
00626 double numeratorX=0.0, numeratorY=0.0, denominator=0.0;
00627
00628
00629 if (xCen-hx < 0) {
00630 xLeftOffset = 0;
00631 maskLeftOffset = hx-xCen;
00632 }
00633 else {
00634 xLeftOffset = xCen-hx;
00635 maskLeftOffset = 0;
00636 }
00637
00638 if (xCen+hx > i_width-1) {
00639 xRightOffset = i_width-1;
00640 maskRightOffset = xCen+hx - i_width-1;
00641 }
00642 else {
00643 xRightOffset = xCen+hx;
00644 maskRightOffset = 0;
00645 }
00646
00647 if (yCen-hy < 0) {
00648 yTopOffset = 0;
00649 p_mask += (hy-yCen)*(2*hx+1);
00650 }
00651 else {
00652 yTopOffset = yCen-hy;
00653 }
00654
00655 if (yCen+hy > i_height-1) {
00656 yBottomOffset = i_height-1;
00657 }
00658 else {
00659 yBottomOffset = yCen+hy;
00660 }
00661
00662 p_features = (const FeatType *)(i_featMap + m_numDimensions*(yTopOffset*i_width + xLeftOffset));
00663
00664 for (y=yTopOffset; y<=yBottomOffset; y++) {
00665 numFeatures = 0;
00666 p_mask += maskLeftOffset;
00667
00668 for (x=xLeftOffset; x<=xRightOffset; x++) {
00669 if (*p_mask++) {
00670 indx = 0;
00671
00672 for (i=0; i<m_numDimensions; ++i) {
00673 fact = 1;
00674
00675 val = (*p_features)/m_binsWidth[i];
00676 p_features++;
00677
00678 for (j=i; j>0; --j) {
00679 fact *= m_numBins[j-1];
00680 }
00681
00682 indx += val*fact;
00683 }
00684
00685 if (indx < 0 || indx >= m_totalBins) {
00686 throw new FD::GeneralException ("VisualHistogramDesc::ComputeMSLocation : invalid histogram bin index",__FILE__,__LINE__);
00687 }
00688
00689
00690
00691 xnorm = (double)(x-xCen)/(double)(hx);
00692 ynorm = (double)(y-yCen)/(double)(hy);
00693
00694 tmpRef = (double)(i_refBins[indx]);
00695 tmpCand = (double)(m_bins[indx]);
00696
00697 if (tmpCand > 0.0) {
00698 posWeight = sqrt(tmpRef/tmpCand);
00699 kernWeight = DerivedEpanechKernel(xnorm*xnorm + ynorm*ynorm);
00700
00701 numeratorX += posWeight*kernWeight*x;
00702 numeratorY += posWeight*kernWeight*y;
00703 denominator += posWeight*kernWeight;
00704 }
00705 }
00706 else {
00707 p_features += m_numDimensions;
00708 }
00709
00710 numFeatures++;
00711 }
00712
00713 p_features += m_numDimensions*(i_width-numFeatures);
00714 p_mask += maskRightOffset;
00715 }
00716
00717 if (denominator > 0.0) {
00718
00719 (*o_msLoc)[0] = i_cueWeight*(numeratorX/denominator);
00720
00721 (*o_msLoc)[1] = i_cueWeight*(numeratorY/denominator);
00722 }
00723 else {
00724
00725
00726
00727 (*o_msLoc)[0] = xCen;
00728
00729 (*o_msLoc)[1] = yCen;
00730 }
00731 }
00732
00733 unsigned int GetNumDimensions() const
00734 {
00735 return m_numDimensions;
00736 }
00737
00738 unsigned int GetSize() const
00739 {
00740 return m_totalBins;
00741 }
00742
00743 unsigned int *GetNumBinsPtr()
00744 {
00745 return (const unsigned int *)m_numBins;
00746 }
00747
00748 const unsigned int *GetCstNumBinsPtr() const
00749 {
00750 return (const unsigned int *)m_numBins;
00751 }
00752
00753 FeatType *GetBinsWidthPtr()
00754 {
00755 return m_binsWidth;
00756 }
00757
00758 const FeatType *GetCstBinsWidthPtr() const
00759 {
00760 return (const FeatType *)m_binsWidth;
00761 }
00762
00763 BinType *GetFeatures()
00764 {
00765 return m_bins;
00766 }
00767
00768 const BinType *GetCstFeatures() const
00769 {
00770 return (const BinType *)m_bins;
00771 }
00772
00773 bool GetValidity() const
00774 {
00775 return m_valid;
00776 }
00777
00778
00779 void SetSize(unsigned int i_size)
00780 {
00781 delete [] m_bins;
00782 m_totalBins = i_size;
00783 m_bins = new BinType[m_totalBins];
00784 }
00785
00786
00787 void SetBins(unsigned int i_numDimensions,
00788 unsigned int *i_numBins)
00789 {
00790 m_numDimensions = i_numDimensions;
00791 unsigned int totalBins = 1;
00792
00793 delete [] m_numBins;
00794 m_numBins = new unsigned int[m_numDimensions];
00795
00796 delete [] m_binsWidth;
00797 m_binsWidth = new FeatType[m_numDimensions];
00798 m_lastMaxVal = (FeatType)0;
00799
00800 for(int d=0; d<m_numDimensions; d++) {
00801 m_numBins[d] = i_numBins[d];
00802 totalBins *= m_numBins[d];
00803 }
00804
00805 if (totalBins != m_totalBins) {
00806 SetSize(totalBins);
00807 }
00808 }
00809
00810
00811 void SetFeatures(const BinType *i_ref, unsigned int i_size)
00812 {
00813 if (m_totalBins != i_size ) {
00814 throw new FD::GeneralException ("VisualHistogramDesc::SetFeatures : number of histogram bins differs from current descriptor",__FILE__,__LINE__);
00815 }
00816
00817 for (int b=0; b<m_totalBins; b++) {
00818 m_bins[b] = i_ref[b];
00819 }
00820 }
00821
00822 void SetValidity(bool i_flag)
00823 {
00824 m_valid = i_flag;
00825 }
00826
00827 private:
00828 void SetSimilarityFct()
00829 {
00830 if (m_simType == e_VISUALHIST_BhattacharyyaCoeff) {
00831 m_similarityFct = &VisualHistogramDesc::BhattacharyyaCoeff;
00832 }
00833 else if (m_simType == e_VISUALHIST_BhattacharyyaDist) {
00834 m_similarityFct = &VisualHistogramDesc::BhattacharyyaDist;
00835 }
00836 else if (m_simType == e_VISUALHIST_HistIntersection) {
00837 if (m_normFlag) {
00838 m_similarityFct = &VisualHistogramDesc::HistogramIntersection;
00839 }
00840 else {
00841 m_similarityFct = &VisualHistogramDesc::HistogramIntersectionWNorm;
00842 }
00843 }
00844 else if (m_simType == e_VISUALHIST_EuclideanDist) {
00845 m_similarityFct = &VisualHistogramDesc::EuclideanDist;
00846 }
00847 else {
00848 m_similarityFct = NULL;
00849 }
00850 }
00851
00852 void SetAdaptFct()
00853 {
00854 if (m_normFlag) {
00855 m_adaptFct = &VisualHistogramDesc::AdaptNorm;
00856 }
00857 else {
00858 m_adaptFct = &VisualHistogramDesc::AdaptOnly;
00859 }
00860 }
00861
00862 double BhattacharyyaDist(const BinType *i_candidateBins) const
00863 {
00864 try {
00865 return sqrt(1.0-BhattacharyyaCoeff(i_candidateBins));
00866 }
00867 catch (FD::BaseException *e) {
00868 throw e->add(new FD::GeneralException("Exception caught in VisualHistogramDesc::BhattacharyyaDist:",__FILE__,__LINE__));
00869 }
00870 }
00871
00872 double BhattacharyyaCoeff(const BinType *i_candidateBins) const
00873 {
00874 int b;
00875 double coeff = 0.0;
00876 const BinType *p_curBins = (const BinType *)m_bins;
00877 const BinType *p_candidateBins = i_candidateBins;
00878
00879 for (int b=0; b<m_totalBins; b++) {
00880 coeff += sqrt((*p_curBins) * (*p_candidateBins));
00881 p_curBins++;
00882 p_candidateBins++;
00883 }
00884
00885
00886 return coeff;
00887 }
00888
00889 double HistogramIntersection(const BinType *i_candidateBins) const
00890 {
00891 const BinType *p_curBins = (const BinType *)m_bins;
00892 const BinType *p_candidateBins = i_candidateBins;
00893 double sum = 0.0;
00894
00895 for (int b=0; b<m_totalBins; b++) {
00896 if (*p_curBins < *p_candidateBins) {
00897 sum += *p_curBins;
00898 }
00899 else {
00900 sum += *p_candidateBins;
00901 }
00902
00903 p_curBins++;
00904 p_candidateBins++;
00905 }
00906
00907 return 1.0-sum;
00908 }
00909
00910 double HistogramIntersectionWNorm(const BinType *i_candidateBins) const
00911 {
00912 const BinType *p_curBins = (const BinType *)m_bins;
00913 const BinType *p_candidateBins = i_candidateBins;
00914 BinType curHistSum = (BinType)0;
00915 BinType candHistSum = (BinType)0;
00916 BinType curNormVal;
00917 BinType candNormVal;
00918 double sum = 0.0;
00919
00920 for (int b=0; b<m_totalBins; b++) {
00921 curHistSum += *p_curBins;
00922 candHistSum += *p_candidateBins;
00923
00924 p_curBins++;
00925 p_candidateBins++;
00926 }
00927
00928 p_curBins = (const BinType *)m_bins;
00929 p_candidateBins = i_candidateBins;
00930
00931 for (int b=0; b<m_totalBins; b++) {
00932 curNormVal = (*p_curBins)/curHistSum;
00933 candNormVal = (*p_candidateBins)/candHistSum;
00934
00935 if (curNormVal < candNormVal) {
00936 sum += curNormVal;
00937 }
00938 else {
00939 sum += candNormVal;
00940 }
00941
00942 p_curBins++;
00943 p_candidateBins++;
00944 }
00945
00946 return 1.0-sum;
00947 }
00948
00949 double EuclideanDist(const BinType *i_candidateBins) const
00950 {
00951 int b;
00952 BinType diff;
00953 double dist = 0.0;
00954 const BinType *p_curBins = (const BinType *)m_bins;
00955 const BinType *p_candidateBins = i_candidateBins;
00956
00957 for (int b=0; b<m_totalBins; b++) {
00958 diff = (*p_curBins) - (*p_candidateBins);
00959 dist += diff*diff;
00960 p_curBins++;
00961 p_candidateBins++;
00962 }
00963
00964 dist = sqrt(dist);
00965
00966 return 1.0-dist;
00967 }
00968
00969 void AdaptNorm(const BinType *i_candidateBins, double i_rate)
00970 {
00971 int b;
00972 const BinType *p_adaptBins = i_candidateBins;
00973 double compRate = 1.0 - i_rate;
00974 BinType sum = (BinType)0;
00975
00976 for (b=0; b<m_totalBins; b++) {
00977 m_bins[b] = (BinType)(compRate*(double)(m_bins[b]) + i_rate*(double)(p_adaptBins[b]));
00978 sum += m_bins[b];
00979 }
00980
00981 if (sum != (BinType)0) {
00982 NormalizeBins(sum);
00983 }
00984 }
00985
00986 void AdaptOnly(const BinType *i_candidateBins, double i_rate)
00987 {
00988 int b;
00989 const BinType *p_adaptBins = i_candidateBins;
00990 double compRate = 1.0 - i_rate;
00991
00992 for (b=0; b<m_totalBins; b++) {
00993 m_bins[b] = (BinType)(compRate*(double)(m_bins[b]) + i_rate*(double)(p_adaptBins[b]));
00994 }
00995 }
00996
00997 void NormalizeBins(BinType i_fact)
00998 {
00999 int b;
01000 double invFact = 1.0/(double)i_fact;
01001
01002 for (b=0; b<m_totalBins; ++b) {
01003 m_bins[b] = (BinType)((double)(m_bins[b])*invFact);
01004 }
01005 }
01006
01007 inline double EpanechKernel(double i_dist) const
01008 {
01009 return std::max( 0.0, k_VISUALHIST_2DIVPI * (1.0 - i_dist) );
01010 }
01011
01012 inline double DerivedEpanechKernel(double i_dist) const
01013 {
01014 if (i_dist <= 1.0) {
01015 return 1.0;
01016 }
01017
01018 return 0.0;
01019 }
01020
01021 private:
01022
01023 e_VISUALHIST_similarityType m_simType;
01024
01025
01026 bool m_valid;
01027
01028
01029 bool m_normFlag;
01030
01031
01032 unsigned int m_numDimensions;
01033
01034
01035 unsigned int m_totalBins;
01036
01037
01038 int *m_numBins;
01039
01040
01041 FeatType *m_binsWidth;
01042
01043
01044 FeatType m_lastMaxVal;
01045
01046
01047 BinType *m_bins;
01048
01049
01050 double (VisualHistogramDesc::*m_similarityFct)(const BinType *) const;
01051
01052
01053 void (VisualHistogramDesc::*m_adaptFct)(const BinType *, double);
01054 };
01055
01056 }
01057
01058 #endif