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

metrics.hxx
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
48namespace vigra{
49
50/// \brief Define functors for various common metrics.
51namespace 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(
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(
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(
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()
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()
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(
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(
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 */
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
Class for a single RGB value.
Definition rgbvalue.hxx:128
iterator begin()
Definition tinyvector.hxx:861
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
MetricType
Tags to select a metric for vector distance computation.
Definition metrics.hxx:230
@ ManhattanMetric
Manhattan distance (L1 norm)
Definition metrics.hxx:236
@ BhattacharyaMetric
Bhattacharya distance (sum of elementwise geometric means)
Definition metrics.hxx:239
@ ChiSquaredMetric
chi-squared distance for histograms (sum of squared differences normalized by means)
Definition metrics.hxx:231
@ HellingerMetric
Hellinger distance (Euclidean distance between the square-root vectors)
Definition metrics.hxx:232
@ SquaredNormMetric
squared Euclidean distance
Definition metrics.hxx:233
@ L1Norm
Manhattan distance (L1 norm)
Definition metrics.hxx:237
@ SymetricKlMetric
symmetric Kullback-Leibler divergence
Definition metrics.hxx:238
@ NormMetric
Euclidean distance (L2 norm)
Definition metrics.hxx:234
@ L2Norm
Euclidean distance (L2 norm)
Definition metrics.hxx:235
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition tinyvector.hxx:2073

© 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.2