Main Page | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Namespace Members | Data Fields | Globals

VisualHistogramDesc.h

Go to the documentation of this file.
00001 /* Copyright (C) 2005 Pierre Moisan (Pierre.Moisan@USherbrooke.ca) 
00002 
00003    This library is free software; you can redistribute it and/or
00004    modify it under the terms of the GNU Lesser General Public
00005    License as published by the Free Software Foundation; either
00006    version 2.1 of the License, or (at your option) any later version.
00007    
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Lesser General Public License for more details.
00012    
00013    You should have received a copy of the GNU Lesser General Public
00014    License along with this library; if not, write to the Free Software
00015    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // TODO: add other similarity methods
00037         e_VISUALHIST_unknownSimilarity
00038 } e_VISUALHIST_similarityType;
00039 
00040 //
00041 // BinType will be used to save each bin value
00042 //  and should only be basic c/c++ types
00043 //  e.g. double, int, char, ...
00044 //
00045 // FeatType is the type used for the feature map
00046 //  that will used to compute the histogram
00047 //  e.g. unsigned char if the feature map is
00048 //  an image
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                 // Avoid self assignment
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                 // Reallocate memory only if required
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         // Default routine to print a VisualHistogramDesc object to an output stream
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         // Default routine to read a VisualHistogramDesc object from an input stream
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                                 // Allocate memory
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                                 // Allocate memory
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                                 // Allocate memory
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                                 // Invalid descriptor, output maximal distance
00336                                 return 0.0;
00337                         }
00338                         
00339                         // Use appropriate function
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                                 // Nothing to do
00360                                 return;
00361                         }
00362                         
00363                         if (i_rate == 1.0) {
00364                                 SetFeatures(i_candidate, i_size);
00365                                 return;
00366                         }
00367                         
00368                         // Use appropriate function
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                 // Adjust region offsets to fit in feature map only
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                 // For each pixels in the region of interest, compute the histogram bin index
00441                 // then add "1" to this bin.
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                 // Adjust region offsets to fit in feature map only
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                 // For each pixels in the region of interest, compute the histogram bin index
00552                 // then compute this pixel weight base on its distance from the center of the
00553                 // region using a kernel profile. This weight will be added in the appropriate
00554                 // histogram bin.
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                                         // Compute normalized distance of the pixel from the center
00581                                         // assuming a unit circle region.
00582                                         xnorm = (double)(x-xCen)/(double)(hx);
00583                                         ynorm = (double)(y-yCen)/(double)(hy);
00584         
00585                                         // Using by default the Epanechnikov kernel
00586                                         // TODO: make kernel profiles enum to choose from
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                 // Adjust region offsets to fit in feature map only
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                                         // Compute normalized distance of the pixel from the center
00690                                         // assuming a unit circle region.
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                         // Mean shift x location
00719                         (*o_msLoc)[0] = i_cueWeight*(numeratorX/denominator);
00720                         // Mean shift y location
00721                         (*o_msLoc)[1] = i_cueWeight*(numeratorY/denominator);
00722                 }
00723                 else {
00724                         // Invalid mean shift estimation. 
00725                         // Output current ROI center location.
00726                         // Mean shift x location
00727                         (*o_msLoc)[0] = xCen;
00728                         // Mean shift y location
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         // WARNING: this function modifies only the histogram bins
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         // A more complete Set function for the histogram bins
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         // WARNING: assumes that i_ref has the same size as the current object
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                 //return coeff/sqrt((double)m_totalBins);
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         // Similarity/Distance type to use
01023         e_VISUALHIST_similarityType m_simType;
01024         
01025         // Validity flag in cases where ROI was invalid for features extraction
01026         bool m_valid;
01027         
01028         // Flag to normalize histogram bins
01029         bool m_normFlag;
01030         
01031         // Numer of dimensions of the histogram
01032         unsigned int m_numDimensions;
01033         
01034         // Total number of bins in the histogram
01035         unsigned int m_totalBins;
01036         
01037         // Number of bins for each dimension
01038         int *m_numBins;
01039         
01040         // Width (in terms of the feature type) of each bin
01041         FeatType *m_binsWidth;
01042         
01043         // Last maximum value used to compute the width of each bin
01044         FeatType m_lastMaxVal;
01045         
01046         // Histogram bin data
01047         BinType *m_bins;
01048         
01049         // Function pointer to the appropriate private similarity routine
01050         double (VisualHistogramDesc::*m_similarityFct)(const BinType *) const;
01051         
01052         // Function pointer to the appropriate private adaptation routine
01053         void (VisualHistogramDesc::*m_adaptFct)(const BinType *, double);
01054 };
01055 
01056 }
01057 
01058 #endif

Generated on Wed Oct 5 14:36:12 2005 for RobotFlow by  doxygen 1.4.4