www.pudn.com > firev0.01.rar > emdistance.hpp


/*
This file is part of the FIRE -- Flexible Image Retrieval System

FIRE is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

FIRE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FIRE; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/**
 * @file   emdistance.hpp
 * @author Thomas Deselaers
 * @date   Mon Jun 23 19:02:56 2003
 * 
 * @brief Earth movers distance as subclass of basedist.
 * 
 * This is an encapsulation of the earth movers distance implemented
 * by yassi rubner.
 */

#ifndef __emdistance_hpp
#define __emdistance_hpp

#include 
#include "basedist.hpp"
#include "mdhistogram.hpp"
#include "histogram.hpp"
#include "colorpixel.hpp"

typedef vector* feature_t;
#ifdef __HAVE_EMD__
#include "emd.h"
#endif

inline float emdbasedist(feature_t *F1, feature_t *F2) {
  double dX=0.0;
  double tmp;
  for(unsigned int i=0;i<(*F1)->size();++i) {
    tmp=(*F1)->operator[](i)-(*F2)->operator[](i);
    dX+=tmp*tmp;
  }
  return (float)sqrt(dX);
}



class EMDistance : public BaseDist {

public:
  EMDistance() {};

  virtual double dist(const BaseFeature *a, const BaseFeature *b) const {
#ifdef __HAVE_EMD__
    signature_t *s1=(signature_t*) malloc(1*sizeof(signature_t));
    signature_t *s2=(signature_t*) malloc(1*sizeof(signature_t));
    
    s1->n=a->size();
    s2->n=b->size();
    s1->Features=(feature_t*)malloc(s1->n*sizeof(feature_t));
    s2->Features=(feature_t*)malloc(s2->n*sizeof(feature_t));
    s1->Weights=(float *) malloc(s1->n*sizeof(float));
    s2->Weights=(float *) malloc(s2->n*sizeof(float));
    
    if(dynamic_cast >* >(a)) {
      const ::img::MDHistogram< ::img::ColorPixel > *mdha=dynamic_cast >* >(a);
      const ::img::MDHistogram< ::img::ColorPixel > *mdhb=dynamic_cast >* >(b);
      
      if(!mdha) ERR << "[EMDistance::dist()] !mdha" << endl;
      if(!mdhb) ERR << "[EMDistance::dist()] !mdhb" << endl;
      
      for(unsigned int i=0;inOfBins();++i) {
        int dim=mdha->dim();
        feature_t v=new vector(dim);
	s1->Features[i]=v;
	for(unsigned int k=0;kdim();++k) {
	  s1->Features[i]->operator[](k)=mdha->value(i)[k];
	}
	s1->Weights[i]=mdha->operator[](i);
      }

      for(unsigned int i=0;inOfBins();++i) {
        int dim=mdhb->dim();
        feature_t v=new vector(dim);
	s2->Features[i]=v;
	for(unsigned int k=0;kdim();++k) {
	  s2->Features[i]->operator[](k)=mdhb->value(i)[k];
	}
	s2->Weights[i]=mdhb->operator[](i);
      }

	    
    } else if(dynamic_cast< const ::img::Histogram* >(a)) {
      const ::img::Histogram *ha=dynamic_cast* >(a);
      const ::img::Histogram *hb=dynamic_cast* >(b);
      if(!ha) ERR << "[EMDistance::dist()] !ha" << endl;
      if(!hb) ERR << "[EMDistance::dist()] !hb" << endl;

      for(unsigned int i=0;inOfBins();++i) {
        int dim=1;
        feature_t v=new vector(dim);
        s1->Features[i]=v;
        s1->Features[i]->operator[](0)=ha->value(i);
        s1->Weights[i]=ha->operator[](i);
      }
      for(unsigned int i=0;inOfBins();++i) {
        int dim=1;
        feature_t v=new vector(dim);
        s2->Features[i]=v;
        s2->Features[i]->operator[](0)=hb->value(i);
        s2->Weights[i]=hb->operator[](i);
      }
    } else {
      ERR << "[EMDistance::dist()] Not MDHistogram, not Histogram, don't know what to do." << endl;
    }


    double result=emd(s1,s2,emdbasedist,0,0);

    //freeing memory
    for(int i=0;in;++i) {
      delete (s1->Features[i]);
    }
    free(s1->Features);
    free(s1->Weights);

    for(int i=0;in;++i) {
      delete (s2->Features[i]);
    }
    free(s2->Features);
    free(s2->Weights);
    
    //returning
    return result;
#else
    ERR << "Need EMD implementation to use this" << endl;
    exit(20);
#endif


  }
  
  virtual double dist(const BaseFeature*, const vector&) const {
    return 0;
  }

  virtual std::string name() {
    return "emd";
  }


private:
};


#endif