vigra - vigra/metrics.hxx Source File

[ 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 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)