[ 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 namespace vigra{
44 namespace metrics{
45 
46 
47 
48 
49 
50  template<class T>
51  class ChiSquared{
52  public:
53  ChiSquared(){}
54  T operator()(const T & a,const T & b)const{
55  return opImpl(&a,&a+1,&b);
56  }
57  template<class A>
58  T operator()(const A & a,const A & b)const{
59  return opImpl(a.begin(),a.end(),b.begin());
60  }
61  private:
62  template<class ITER_A,class ITER_B>
63  T opImpl(
64  ITER_A iterA ,ITER_A endA ,ITER_B iterB
65  )const{
66  T res = 0.0;
67  while(iterA!=endA){
68  const T aa=static_cast<T>(*iterA);
69  const T bb=static_cast<T>(*iterB);
70  const T sum = aa + bb;
71  const T diff = aa - bb;
72  if(sum> static_cast<T>(0.0000001))
73  res+=(diff*diff)/sum;
74  ++iterA;
75  ++iterB;
76  }
77  return res*T(0.5);
78  }
79  };
80 
81 
82  template<class T>
83  class HellingerDistance{
84  public:
85  HellingerDistance(){}
86  T operator()(const T & a,const T & b)const{
87  return opImpl(&a,&a+1,&b);
88  }
89  template<class A>
90  T operator()(const A & a,const A & b)const{
91  return opImpl(a.begin(),a.end(),b.begin());
92  }
93  private:
94  template<class ITER_A,class ITER_B>
95  T opImpl(
96  ITER_A iterA ,ITER_A endA ,ITER_B iterB
97  )const{
98  T res = 0.0;
99  while(iterA!=endA){
100  const T aa=std::sqrt(static_cast<T>(*iterA));
101  const T bb=std::sqrt(static_cast<T>(*iterB));
102  const T diff = aa - bb;
103  res+=diff*diff;
104  ++iterA;
105  ++iterB;
106  }
107  return std::sqrt(res)/std::sqrt(2.0);
108  }
109  };
110 
111  template<class T,unsigned int NORM,bool TAKE_ROOT=true>
112  class PNorm{
113  public:
114  PNorm(){}
115  T operator()(const T & a,const T & b)const{
116  return opImpl(&a,&a+1,&b);
117  }
118  template<class A>
119  T operator()(const A & a,const A & b)const{
120  return opImpl(a.begin(),a.end(),b.begin());
121  }
122  private:
123  template<class ITER_A,class ITER_B>
124  T opImpl(
125  ITER_A iterA ,ITER_A endA ,ITER_B iterB
126  )const{
127  T res = static_cast<T>(0.0);
128  while(iterA!=endA){
129  const T aa=static_cast<T>(*iterA);
130  const T bb=static_cast<T>(*iterB);
131  const T diff = aa-bb;
132  res+= std::abs(std::pow((double)diff,(int)NORM));
133  ++iterA;
134  ++iterB;
135  }
136  return TAKE_ROOT ? std::pow(res,static_cast<T>(1)/static_cast<T>(NORM)) : res;
137  }
138  };
139 
140  template<class T>
141  class SquaredNorm
142  : public PNorm<T,2,false>{
143  public:
144  SquaredNorm()
145  : PNorm<T,2,false>(){
146  }
147  };
148 
149  template<class T>
150  class Norm
151  : public PNorm<T,2,true>{
152  public:
153  Norm()
154  : PNorm<T,2,true>(){
155  }
156  };
157 
158  template<class T>
159  class Manhattan
160  : public PNorm<T,1,false>{
161  public:
162  Manhattan()
163  : PNorm<T,1,false>(){
164  }
165  };
166 
167  template<class T>
168  class SymetricKlDivergenz{
169  public:
170  SymetricKlDivergenz(){}
171  T operator()(const T & a,const T & b)const{
172  return opImpl(&a,&a+1,&b);
173  }
174  template<class A>
175  T operator()(const A & a,const A & b)const{
176  return opImpl(a.begin(),a.end(),b.begin());
177  }
178  private:
179  template<class ITER_A,class ITER_B>
180  T opImpl(
181  ITER_A iterA ,ITER_A endA ,ITER_B iterB
182  )const{
183  T res = static_cast<T>(0.0);
184  while(iterA!=endA){
185  const T aa=static_cast<T>(*iterA);
186  const T bb=static_cast<T>(*iterB);
187  if(aa>static_cast<T>(0.0000001) && bb>static_cast<T>(0.0000001) ){
188  const T val = std::log(aa/bb)*aa + std::log(bb/aa)*bb;
189  if(!isinf(val) && !isnan(val))
190  res+=std::log(aa/bb)*aa + std::log(bb/aa)*bb;
191  }
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>
207  T operator()(const A & a,const A & 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  enum MetricType{
228  ChiSquaredMetric=0,
229  HellingerMetric=1,
230  SquaredNormMetric=2,
231  NormMetric=3,
232  ManhattanMetric=4,
233  SymetricKlMetric=5,
234  BhattacharyaMetric=6
235  };
236 
237 
238  template<class T>
239  class Metric{
240  public:
241 
242  Metric(const MetricType metricType = ManhattanMetric)
243  : metricType_(metricType){
244 
245  }
246 
247  template<class A>
248  T operator()(const A & a,const A & b)const{
249  switch(static_cast<unsigned int>(metricType_)){
250  case 0:
251  return chiSquared_(a,b);
252  case 1:
253  return hellingerDistance_(a,b);
254  case 2:
255  return squaredNorm_(a,b);
256  case 3:
257  return norm_(a,b);
258  case 4:
259  return manhattan_(a,b);
260  case 5:
261  return symetricKlDivergenz_(a,b);
262  case 6 :
263  return bhattacharyaDistance_(a,b);
264  default :
265  return 0;
266  }
267  }
268  private:
269  MetricType metricType_;
270  ChiSquared<T> chiSquared_;
271  HellingerDistance<T> hellingerDistance_;
272  SquaredNorm<T> squaredNorm_;
273  Norm<T> norm_;
274  Manhattan<T> manhattan_;
275  SymetricKlDivergenz<T> symetricKlDivergenz_;
276  BhattacharyaDistance<T> bhattacharyaDistance_;
277  };
278 
279 } // end namespace metric
280 } // end namepsace vigra
281 
282 
283 #endif //VIGRA_METRIC_HXX

© 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.10.0 (Thu Jan 8 2015)