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

VisualIntegralDesc.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 _VISUALINTEGRALCOLORDESC_H_
00019 #define _VISUALINTEGRALCOLORDESC_H_
00020 
00021 #include <math.h>
00022 #include "VisualFeatureDesc.h"
00023 
00024 namespace RobotFlow {
00025 
00026 typedef enum
00027 {
00028         e_VISUALINTDESC_EuclideanDist = 0,
00029         // TODO: maybe add other similarity methods
00030         e_VISUALINTDESC_UnknownSimilarity
00031 } e_VISUALINTDESC_similarityType;
00032 
00033 //
00034 // Descriptor for integral image features
00035 // A typical integral image feature consists of a mean value
00036 // for a given region of interest in each channel of the image
00037 // 
00038 template <class FeatType>
00039 class VisualIntegralDesc : public VisualFeatureDesc<FeatType>
00040 {
00041 public:
00042         VisualIntegralDesc()
00043         : VisualFeatureDesc<FeatType>(e_VISUALDESCRIPTOR_integral),
00044         m_simType(e_VISUALINTDESC_UnknownSimilarity), m_numClrChannels(0), 
00045         m_numIntValues(0), m_featSize(0), m_valid(false), m_useRectDiff(false),
00046         m_useBoundary(false), m_intFeatures(NULL)
00047         { 
00048                 SetSimilarityFct();
00049         }
00050         
00051         VisualIntegralDesc(e_VISUALINTDESC_similarityType i_simType,
00052                 unsigned int i_numClrChannels, unsigned int i_numIntValues,
00053                 FeatType i_maxValue, bool i_useRectDiff, bool i_useBoundary) 
00054         : VisualFeatureDesc<FeatType>(e_VISUALDESCRIPTOR_integral),
00055         m_simType(i_simType), m_numClrChannels(i_numClrChannels),
00056         m_numIntValues(i_numIntValues), m_maxValue(i_maxValue),
00057         m_valid(true), m_useRectDiff(i_useRectDiff), 
00058         m_useBoundary(i_useBoundary), m_intFeatures(NULL)
00059         { 
00060                 m_featSize = m_numClrChannels*m_numIntValues;
00061                 
00062                 if (m_useRectDiff) {
00063                         m_maxDiffValue = m_maxValue;
00064                         m_maxValue = (FeatType)((double)(m_maxDiffValue)*0.5);
00065                         m_numMeanValues = (unsigned int)(sqrt((float)(m_numIntValues)));
00066                         m_numIntValues -= m_numMeanValues;
00067                 }
00068                 
00069                 if (m_useBoundary) {
00070                         m_featSize += 4;
00071                 }
00072                 
00073                 m_intFeatures = new FeatType[m_featSize];
00074                 
00075                 SetSimilarityFct();
00076         }
00077         
00078         VisualIntegralDesc(const VisualIntegralDesc<FeatType> &i_ref)
00079         {
00080                 try {
00081                         this->SetType(i_ref.GetType());
00082                         m_simType = i_ref.m_simType;
00083                         m_numClrChannels = i_ref.m_numClrChannels;
00084                         m_numIntValues = i_ref.m_numIntValues;
00085                         m_featSize = i_ref.m_featSize;
00086                         m_maxValue = i_ref.m_maxValue;
00087                         m_valid = i_ref.m_valid;
00088                         m_useRectDiff = i_ref.m_useRectDiff;
00089                         m_useBoundary = i_ref.m_useBoundary;
00090                         m_maxDiffValue = i_ref.m_maxDiffValue;
00091                         m_numMeanValues = i_ref.m_numMeanValues;
00092                         
00093                         m_intFeatures = new FeatType[m_featSize];
00094                         
00095                         for (int i=0; i<m_featSize; i++) {
00096                                 m_intFeatures[i] = i_ref.m_intFeatures[i];
00097                         }
00098                         
00099                         SetSimilarityFct();
00100                 }
00101                 catch (FD::BaseException *e) {
00102                         throw e->add(new FD::GeneralException("Exception caught in VisualIntegralDesc::VisualIntegralDesc:",__FILE__,__LINE__));
00103                 }
00104         }
00105 
00106         ~VisualIntegralDesc()
00107         {
00108                 delete [] m_intFeatures;
00109         }
00110 
00111         VisualIntegralDesc<FeatType> & operator =(const VisualIntegralDesc<FeatType> &i_ref)
00112         {
00113                 // Avoid self assignment
00114                 if (&i_ref == this) {
00115                         return *this;
00116                 }
00117                 
00118                 this->SetType(i_ref.GetType());
00119                 m_simType = i_ref.m_simType;
00120                 m_numClrChannels = i_ref.m_numClrChannels;
00121                 m_numIntValues = i_ref.m_numIntValues;
00122                 m_featSize = i_ref.m_featSize;
00123                 m_maxValue = i_ref.m_maxValue;
00124                 m_valid = i_ref.m_valid;
00125                 m_useRectDiff = i_ref.m_useRectDiff;
00126                 m_useBoundary = i_ref.m_useBoundary;
00127                 m_maxDiffValue = i_ref.m_maxDiffValue;
00128                 m_numMeanValues = i_ref.m_numMeanValues;
00129                 
00130                 delete [] m_intFeatures;
00131                 m_intFeatures = new FeatType[m_featSize];
00132                 
00133                 for (int i=0; i<m_featSize; i++) {
00134                         m_intFeatures[i] = i_ref.m_intFeatures[i];
00135                 }
00136                 
00137                 SetSimilarityFct();
00138                 
00139                 return *this;
00140         }
00141         
00142         VisualIntegralDesc<FeatType>* clone()  const
00143         {
00144                 return new VisualIntegralDesc<FeatType>(*this);
00145         }
00146 
00147         // Default routine to print a VisualIntegralDesc object to an output stream
00148         void printOn(std::ostream &out) const
00149         {
00150                 throw new FD::GeneralException("Exception in VisualIntegralDesc::printOn: cannot use base class routine.",__FILE__,__LINE__);
00151         }
00152 
00153         // Default routine to read a VisualIntegralDesc object from an input stream
00154         void readFrom(std::istream &in)
00155         {
00156                 throw new FD::GeneralException("Exception in VisualIntegralDesc::readFrom: cannot use base class routine.",__FILE__,__LINE__);
00157         }
00158 
00159         double Similarity(const FeatType *i_candidate, unsigned int i_size) const
00160         {
00161                 try {
00162                         if (!i_candidate) {
00163                                 throw new FD::GeneralException("VisualIntegralDesc::Similarity: invalid (NULL) candidate features.",__FILE__,__LINE__);
00164                         }
00165                         
00166                         if (i_size != m_featSize) {
00167                                 throw new FD::GeneralException("VisualIntegralDesc::Similarity: candidate features size differs from current features descriptor size.",__FILE__,__LINE__);
00168                         }
00169                         
00170                         if (!m_similarityFct) {
00171                                 throw new FD::GeneralException("VisualIntegralDesc::Similarity: invalid or unknown similarity type.",__FILE__,__LINE__);
00172                         }
00173                         
00174                         if (!m_valid) {
00175                                 // Invalid descriptor, output maximal distance
00176                                 return 0.0;
00177                         }
00178                         
00179                         // Use appropriate function
00180                         return (this->*m_similarityFct)(i_candidate);
00181                 }
00182                 catch (FD::BaseException *e) {
00183                         throw e->add(new FD::GeneralException("Exception caught in VisualIntegralDesc::Similarity:",__FILE__,__LINE__));
00184                 }
00185         }
00186         
00187         void Adapt(const FeatType *i_candidate, unsigned int i_size, double i_rate)
00188         {
00189                 try {
00190                         if (!i_candidate) {
00191                                 throw new FD::GeneralException("VisualIntegralDesc::Adapt: invalid (NULL) candidate features.",__FILE__,__LINE__);
00192                         }
00193                         
00194                         if (i_size != m_featSize) {
00195                                 throw new FD::GeneralException("VisualIntegralDesc::Adapt: candidate features size differs from current features descriptor size.",__FILE__,__LINE__);
00196                         }
00197                         
00198                         if (i_rate < 0.0 || i_rate > 1.0) {
00199                                 throw new FD::GeneralException ("VisualHistogramDesc::Adapt : adaptation rate must be in the interval [0.0,1.0]",__FILE__,__LINE__);
00200                         }
00201                         
00202                         if (i_rate == 0.0) {
00203                                 // Nothing to do
00204                                 return;
00205                         }
00206                         
00207                         if (i_rate == 1.0) {
00208                                 SetFeatures(i_candidate, i_size);
00209                                 return;
00210                         }
00211                         
00212                         int i;
00213                         const FeatType *p_adaptFeat = i_candidate;
00214                         double compRate = 1.0 - i_rate;
00215                         
00216                         for (i=0; i<m_featSize; i++) {
00217                                 m_intFeatures[i] = (FeatType)(compRate*(double)(m_intFeatures[i]) + i_rate*(double)(p_adaptFeat[i]));
00218                         }
00219                 }
00220                 catch (FD::BaseException *e) {
00221                         throw e->add(new FD::GeneralException("Exception caught in VisualIntegralDesc::Adapt:",__FILE__,__LINE__));
00222                 }
00223         }
00224         
00225         unsigned int GetSize() const
00226         {
00227                 return m_featSize;
00228         }
00229 
00230         FeatType *GetFeatures()
00231         {
00232                 return m_intFeatures;
00233         }
00234         
00235         const FeatType *GetCstFeatures() const
00236         {
00237                 return (const FeatType *)m_intFeatures;
00238         }
00239         
00240         bool GetValidity() const
00241         {
00242                 return m_valid;
00243         }
00244         
00245         void SetSize(unsigned int i_size)
00246         {
00247                 throw new FD::GeneralException("Exception in VisualIntegralDesc::SetSize: cannot use base class routine.",__FILE__,__LINE__);
00248         }
00249         
00250         void SetFeatures(const FeatType *i_ref, unsigned int i_size)
00251         {
00252                 try {
00253                         if (!i_ref) {
00254                                 throw new FD::GeneralException("VisualIntegralDesc::SetFeatures: invalid (NULL) input features.",__FILE__,__LINE__);
00255                         }
00256                         
00257                         if (i_size != m_featSize) {
00258                                 throw new FD::GeneralException("VisualIntegralDesc::SetFeatures: candidate features size differs from current features descriptor size.",__FILE__,__LINE__);
00259                         }
00260                         
00261                         int i;
00262                         const FeatType *p_inFeat = i_ref;
00263                         
00264                         for (i=0; i<m_featSize; i++) {
00265                                 m_intFeatures[i] = *p_inFeat++;
00266                         }
00267                 }
00268                 catch (FD::BaseException *e) {
00269                         throw e->add(new FD::GeneralException("Exception caught in VisualIntegralDesc::SetFeatures:",__FILE__,__LINE__));
00270                 }
00271         }
00272         
00273         void SetValidity(bool i_flag) {
00274                 m_valid = i_flag;
00275         }
00276         
00277 private:
00278         void SetSimilarityFct()
00279         {
00280                 if (m_simType == e_VISUALINTDESC_EuclideanDist) {
00281                         if (m_useRectDiff) {
00282                                 if (m_useBoundary) {
00283                                         m_similarityFct = &VisualIntegralDesc::EuclideanDistWDiffWBound;
00284                                 }
00285                                 else {
00286                                         m_similarityFct = &VisualIntegralDesc::EuclideanDistWDiff;
00287                                 }
00288                         }
00289                         else {
00290                                 if (m_useBoundary) {
00291                                         m_similarityFct = &VisualIntegralDesc::EuclideanDistWBound;
00292                                 }
00293                                 else {
00294                                         m_similarityFct = &VisualIntegralDesc::EuclideanDist;
00295                                 }
00296                         }
00297                 }
00298                 else {
00299                         m_similarityFct = NULL;
00300                 }
00301         }
00302         
00303         double EuclideanDist(const FeatType *i_candidate) const
00304         {
00305                 FeatType diff;
00306                 double dist = 0.0;
00307                 const FeatType *p_curFeat = (const FeatType *)m_intFeatures;
00308                 const FeatType *p_candFeat = i_candidate;
00309         
00310                 for (int i=0; i<m_numIntValues; i++) {
00311                         double clrDist = 0.0;
00312                         for (int c=0; c<m_numClrChannels; c++) {
00313                                 diff = ((*p_curFeat) - (*p_candFeat))/m_maxValue;
00314                                 clrDist += (double)(diff*diff);
00315                                 p_curFeat++;
00316                                 p_candFeat++;
00317                         }
00318                         dist += sqrt(clrDist);
00319                 }
00320                 
00321                 dist /= m_numIntValues;
00322                 
00323                 if (dist > 1.0) {
00324                         return 0.0;
00325                 }
00326         
00327                 return 1.0-dist;
00328         }
00329         
00330         double EuclideanDistWDiff(const FeatType *i_candidate) const
00331         {
00332                 int i, c;
00333                 FeatType diff;
00334                 double dist, dist1 = 0.0, dist2 = 0.0;
00335                 const FeatType *p_curFeat = (const FeatType *)m_intFeatures;
00336                 const FeatType *p_candFeat = i_candidate;
00337         
00338                 for (i=0; i<m_numMeanValues; i++) {
00339                         double clrDist = 0.0;
00340                         for (c=0; c<m_numClrChannels; c++) {
00341                                 diff = ((*p_curFeat) - (*p_candFeat))/m_maxValue;
00342                                 clrDist += (double)(diff*diff);
00343                                 p_curFeat++;
00344                                 p_candFeat++;
00345                         }
00346                         dist1 += sqrt(clrDist);
00347                 }
00348 
00349                 dist1 /= m_numMeanValues;
00350 
00351                 if (dist1 > 1.0) {
00352                         return 0.0;
00353                 }
00354                 
00355                 for (i=0; i<m_numIntValues; i++) {
00356                         double clrDist = 0.0;
00357                         for (c=0; c<m_numClrChannels; c++) {
00358                                 diff = ((*p_curFeat) - (*p_candFeat))/m_maxDiffValue;
00359                                 clrDist += (double)(diff*diff);
00360                                 
00361                                 p_curFeat++;
00362                                 p_candFeat++;
00363                         }
00364                         dist2 += sqrt(clrDist);
00365                 }
00366                 
00367                 dist2 /= m_numIntValues;
00368                 
00369                 if (dist2 > 1.0) {
00370                         return 0.0;
00371                 }
00372                 
00373                 dist = (dist1+dist2)*0.5;
00374                 
00375                 if (dist > 1.0) {
00376                         return 0.0;
00377                 }
00378         
00379                 return 1.0-dist;
00380         }
00381         
00382         double EuclideanDistWBound(const FeatType *i_candidate) const
00383         {
00384                 int i;
00385                 FeatType diff;
00386                 double dist = 0.0;
00387                 const FeatType *p_curFeat = (const FeatType *)m_intFeatures;
00388                 const FeatType *p_candFeat = i_candidate;
00389         
00390                 for (i=0; i<m_numIntValues; i++) {
00391                         double clrDist = 0.0;
00392                         for (int c=0; c<m_numClrChannels; c++) {
00393                                 diff = ((*p_curFeat) - (*p_candFeat))/m_maxValue;
00394                                 clrDist += (double)(diff*diff);
00395                                 p_curFeat++;
00396                                 p_candFeat++;
00397                         }
00398                         dist += sqrt(clrDist);
00399                 }
00400                 
00401                 dist /= m_numIntValues;
00402                 
00403                 if (dist > 1.0) {
00404                         return 0.0;
00405                 }
00406                 
00407                 // Check for an obvious boundary in candidate
00408                 int numBoundary = 0;
00409                 int numUnknown = 0;
00410                 for (i=0; i<4; i++) {
00411                         if (*p_candFeat == 1) {
00412                                 numUnknown++;
00413                         }
00414                         else if (*p_candFeat == 2) {
00415                                 numBoundary++;
00416                         }
00417                 }
00418                 
00419                 if (numUnknown < 4) {
00420                         int numValid = 4-numUnknown;
00421                         dist += (double)(numValid-numBoundary)/(double)(numValid);
00422                         
00423                         if (dist > 1.0) {
00424                                 return 0.0;
00425                         }
00426                 }
00427                 
00428                 return 1.0-dist;
00429         }
00430         
00431         double EuclideanDistWDiffWBound(const FeatType *i_candidate) const
00432         {
00433                 int i, c;
00434                 FeatType diff;
00435                 double dist, dist1 = 0.0, dist2 = 0.0;
00436                 const FeatType *p_curFeat = (const FeatType *)m_intFeatures;
00437                 const FeatType *p_candFeat = i_candidate;
00438         
00439                 for (i=0; i<m_numMeanValues; i++) {
00440                         double clrDist = 0.0;
00441                         for (c=0; c<m_numClrChannels; c++) {
00442                                 diff = ((*p_curFeat) - (*p_candFeat))/m_maxValue;
00443                                 clrDist += (double)(diff*diff);
00444                                 p_curFeat++;
00445                                 p_candFeat++;
00446                         }
00447                         dist1 += sqrt(clrDist);
00448                 }
00449 
00450                 dist1 /= m_numMeanValues;
00451                 
00452                 if (dist1 > 1.0) {
00453                         return 0.0;
00454                 }
00455                 
00456                 for (i=0; i<m_numIntValues; i++) {
00457                         double clrDist = 0.0;
00458                         for (c=0; c<m_numClrChannels; c++) {
00459                                 diff = ((*p_curFeat) - (*p_candFeat))/m_maxDiffValue;
00460                                 clrDist += (double)(diff*diff);
00461                                 p_curFeat++;
00462                                 p_candFeat++;
00463                         }
00464                         dist2 += sqrt(clrDist);
00465                 }
00466                 
00467                 dist2 /= m_numIntValues;
00468                 
00469                 if (dist2 > 1.0) {
00470                         return 0.0;
00471                 }
00472                 
00473                 dist = (dist1+dist2)*0.5;
00474                 
00475                 if (dist > 1.0) {
00476                         return 0.0;
00477                 }
00478         
00479                 // Check for an obvious boundary in candidate
00480                 int numBoundary = 0;
00481                 int numUnknown = 0;
00482                 for (i=0; i<4; i++) {
00483                         if (*p_candFeat == 1) {
00484                                 numUnknown++;
00485                         }
00486                         else if (*p_candFeat == 2) {
00487                                 numBoundary++;
00488                         }
00489                 }
00490                 
00491                 if (numUnknown < 4) {
00492                         int numValid = 4-numUnknown;
00493                         dist += (double)(numValid-numBoundary)/(double)(numValid);
00494                         
00495                         if (dist > 1.0) {
00496                                 return 0.0;
00497                         }
00498                 }
00499                 
00500                 return 1.0-dist;
00501         }
00502 
00503 private:
00504         // Similarity/Distance type to use
00505         e_VISUALINTDESC_similarityType m_simType;
00506         
00507         // Number of color channels of the color space used
00508         unsigned int m_numClrChannels;
00509         
00510         // Number of integral rectangle values/features
00511         unsigned int m_numIntValues;
00512         
00513         // The size of the feature descriptor
00514         unsigned int m_featSize;
00515         
00516         // Maximum channel value 
00517         FeatType m_maxValue;
00518         
00519         unsigned int m_numMeanValues;
00520         FeatType m_maxDiffValue;
00521         
00522         bool m_useRectDiff;
00523         
00524         bool m_useBoundary;
00525         
00526         // Validity flag in cases where ROI was invalid for features extraction
00527         bool m_valid;
00528         
00529         // Integral features
00530         FeatType *m_intFeatures;
00531         
00532         // Function pointer to the appropriate private similarity routine
00533         double (VisualIntegralDesc::*m_similarityFct)(const FeatType *) const;
00534 };
00535 
00536 }
00537 
00538 #endif

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