[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

metrics.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2014 by Thorsten Beier and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 #ifndef VIGRA_METRIC_HXX
36 #define VIGRA_METRIC_HXX
37 
38 #include <vigra/numerictraits.hxx>
39 #include <vigra/multi_array.hxx>
40 
41 #include <cmath>
42 
43 /** \addtogroup MathFunctions
44 */
45 //@{
46 
47 
48 namespace vigra{
49 
50 /// \brief Define functors for various common metrics.
51 namespace metrics{
52 
53  template<class T>
54  class ChiSquared{
55  public:
56  ChiSquared(){}
57  T operator()(const T & a,const T & b)const{
58  return opImpl(&a,&a+1,&b);
59  }
60  template<class A, class B>
61  T operator()(const A & a,const B & b)const{
62  return opImpl(a.begin(),a.end(),b.begin());
63  }
64  private:
65  template<class ITER_A,class ITER_B>
66  T opImpl(
67  ITER_A iterA ,ITER_A endA ,ITER_B iterB
68  )const{
69  T res = 0.0;
70  while(iterA!=endA){
71  const T aa=static_cast<T>(*iterA);
72  const T bb=static_cast<T>(*iterB);
73  const T sum = aa + bb;
74  const T diff = aa - bb;
75  if(sum> static_cast<T>(0.0000001))
76  res+=(diff*diff)/sum;
77  ++iterA;
78  ++iterB;
79  }
80  return res*T(0.5);
81  }
82  };
83 
84  template<class T>
85  class HellingerDistance{
86  public:
87  HellingerDistance(){}
88  T operator()(const T & a,const T & b)const{
89  return opImpl(&a,&a+1,&b);
90  }
91  template<class A, class B>
92  T operator()(const A & a,const B & b)const{
93  return opImpl(a.begin(),a.end(),b.begin());
94  }
95  private:
96  template<class ITER_A,class ITER_B>
97  T opImpl(
98  ITER_A iterA ,ITER_A endA ,ITER_B iterB
99  )const{
100  T res = 0.0;
101  while(iterA!=endA){
102  const T aa=std::sqrt(static_cast<T>(*iterA));
103  const T bb=std::sqrt(static_cast<T>(*iterB));
104  const T diff = aa - bb;
105  res+=diff*diff;
106  ++iterA;
107  ++iterB;
108  }
109  return std::sqrt(res)/std::sqrt(2.0);
110  }
111  };
112 
113  template<class T,unsigned int NORM,bool TAKE_ROOT=true>
114  class PNorm{
115  public:
116  PNorm(){}
117  T operator()(const T & a,const T & b)const{
118  return opImpl(&a,&a+1,&b);
119  }
120  template<class A, class B>
121  T operator()(const A & a,const B & b)const{
122  return opImpl(a.begin(),a.end(),b.begin());
123  }
124  private:
125  template<class ITER_A,class ITER_B>
126  T opImpl(
127  ITER_A iterA ,ITER_A endA ,ITER_B iterB
128  )const{
129  T res = static_cast<T>(0.0);
130  while(iterA!=endA){
131  const T aa=static_cast<T>(*iterA);
132  const T bb=static_cast<T>(*iterB);
133  const T diff = aa-bb;
134  res+= std::abs(std::pow((double)diff,(int)NORM));
135  ++iterA;
136  ++iterB;
137  }
138  return TAKE_ROOT ? std::pow(res,static_cast<T>(1)/static_cast<T>(NORM)) : res;
139  }
140  };
141 
142  template<class T>
143  class SquaredNorm
144  : public PNorm<T,2,false>{
145  public:
146  SquaredNorm()
147  : PNorm<T,2,false>(){
148  }
149  };
150 
151  template<class T>
152  class Norm
153  : public PNorm<T,2,true>{
154  public:
155  Norm()
156  : PNorm<T,2,true>(){
157  }
158  };
159 
160  template<class T>
161  class Manhattan
162  : public PNorm<T,1,false>{
163  public:
164  Manhattan()
165  : PNorm<T,1,false>(){
166  }
167  };
168 
169  template<class T>
170  class SymetricKlDivergenz{
171  public:
172  SymetricKlDivergenz(){}
173  T operator()(const T & a,const T & b)const{
174  return opImpl(&a,&a+1,&b);
175  }
176  template<class A, class B>
177  T operator()(const A & a,const B & b)const{
178  return opImpl(a.begin(),a.end(),b.begin());
179  }
180  private:
181  template<class ITER_A,class ITER_B>
182  T opImpl(
183  ITER_A iterA ,ITER_A endA ,ITER_B iterB
184  )const{
185  T res = static_cast<T>(0.0);
186  while(iterA!=endA){
187  const T aa=static_cast<T>(*iterA);
188  const T bb=static_cast<T>(*iterB);
189  const T val = std::log(aa/bb)*(aa - bb);
190  if(!isinf(val) && !isnan(val))
191  res+=val;
192  ++iterA;
193  ++iterB;
194  }
195  return res/static_cast<T>(2.0);
196  }
197  };
198 
199  template<class T>
200  class BhattacharyaDistance{
201  public:
202  BhattacharyaDistance(){}
203  T operator()(const T & a,const T & b)const{
204  return opImpl(&a,&a+1,&b);
205  }
206  template<class A, class B>
207  T operator()(const A & a,const B & b)const{
208  return opImpl(a.begin(),a.end(),b.begin());
209  }
210  private:
211  template<class ITER_A,class ITER_B>
212  T opImpl(
213  ITER_A iterA ,ITER_A endA ,ITER_B iterB
214  )const{
215  T res = static_cast<T>(0.0);
216  while(iterA!=endA){
217  const T aa=static_cast<T>(*iterA);
218  const T bb=static_cast<T>(*iterB);
219  res+=std::sqrt(aa*bb);
220  ++iterA;
221  ++iterB;
222  }
223  return std::sqrt( static_cast<T>(1.0)-res);
224  }
225  };
226 
227  /** \brief Tags to select a metric for vector distance computation.
228  */
230  {
231  ChiSquaredMetric=0, //!< chi-squared distance for histograms (sum of squared differences normalized by means)
232  HellingerMetric=1, //!< Hellinger distance (Euclidean distance between the square-root vectors)
233  SquaredNormMetric=2, //!< squared Euclidean distance
234  NormMetric=3, //!< Euclidean distance (L2 norm)
235  L2Norm=NormMetric, //!< Euclidean distance (L2 norm)
236  ManhattanMetric=4, //!< Manhattan distance (L1 norm)
237  L1Norm=ManhattanMetric, //!< Manhattan distance (L1 norm)
238  SymetricKlMetric=5, //!< symmetric Kullback-Leibler divergence
239  BhattacharyaMetric=6 //!< Bhattacharya distance (sum of elementwise geometric means)
240  };
241 
242 
243  /** \brief Functor to compute a metric between two vectors.
244 
245  The value type of the metric is given by template parameter <tt>T</tt>. Supported
246  metrics are defined in \ref vigra::metrics::MetricType. The functor's argument
247  must support <tt>begin()</tt> and <tt>end()</tt> to create an STL range.
248  */
249  template<class T>
250  class Metric{
251  public:
252 
253  /** \brief Construct functor for the given metric.
254 
255  The value type of the metric is given by template parameter <tt>T</tt>. Supported
256  metrics are defined in \ref vigra::metrics::MetricType.
257  */
258  Metric(const MetricType metricType = ManhattanMetric)
259  : metricType_(metricType){
260 
261  }
262 
263  template<class A, class B>
264  T operator()(const A & a,const B & b)const{
265  switch(static_cast<unsigned int>(metricType_)){
266  case 0:
267  return chiSquared_(a,b);
268  case 1:
269  return hellingerDistance_(a,b);
270  case 2:
271  return squaredNorm_(a,b);
272  case 3:
273  return norm_(a,b);
274  case 4:
275  return manhattan_(a,b);
276  case 5:
277  return symetricKlDivergenz_(a,b);
278  case 6 :
279  return bhattacharyaDistance_(a,b);
280  default :
281  return 0;
282  }
283  }
284  private:
285  MetricType metricType_;
286  ChiSquared<T> chiSquared_;
287  HellingerDistance<T> hellingerDistance_;
288  SquaredNorm<T> squaredNorm_;
289  Norm<T> norm_;
290  Manhattan<T> manhattan_;
291  SymetricKlDivergenz<T> symetricKlDivergenz_;
292  BhattacharyaDistance<T> bhattacharyaDistance_;
293  };
294 
295 } // end namespace metric
296 } // end namepsace vigra
297 
298 //@}
299 
300 #endif //VIGRA_METRIC_HXX
Euclidean distance (L2 norm)
Definition: metrics.hxx:234
Functor to compute a metric between two vectors.
Definition: metrics.hxx:250
Metric(const MetricType metricType=ManhattanMetric)
Construct functor for the given metric.
Definition: metrics.hxx:258
Manhattan distance (L1 norm)
Definition: metrics.hxx:236
Bhattacharya distance (sum of elementwise geometric means)
Definition: metrics.hxx:239
Manhattan distance (L1 norm)
Definition: metrics.hxx:237
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition: tinyvector.hxx:2073
MetricType
Tags to select a metric for vector distance computation.
Definition: metrics.hxx:229
chi-squared distance for histograms (sum of squared differences normalized by means) ...
Definition: metrics.hxx:231
squared Euclidean distance
Definition: metrics.hxx:233
linalg::TemporaryMatrix< T > log(MultiArrayView< 2, T, C > const &v)
FFTWComplex< R >::NormType abs(const FFTWComplex< R > &a)
absolute value (= magnitude)
Definition: fftw3.hxx:1002
Hellinger distance (Euclidean distance between the square-root vectors)
Definition: metrics.hxx:232
symmetric Kullback-Leibler divergence
Definition: metrics.hxx:238
SquareRootTraits< FixedPoint< IntBits, FracBits > >::SquareRootResult sqrt(FixedPoint< IntBits, FracBits > v)
square root.
Definition: fixedpoint.hxx:616
Euclidean distance (L2 norm)
Definition: metrics.hxx:235

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)