00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef _OPENCV_DIST_H_
00032 #define _OPENCV_DIST_H_
00033
00034 #include <cmath>
00035 using namespace std;
00036
00037 #include "opencv2/flann/general.h"
00038
00039 namespace cvflann
00040 {
00041
00047 #define flann_dist custom_dist
00048
00049
00050
00060 template <typename Iterator1, typename Iterator2>
00061 double euclidean_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00062 {
00063 double distsq = acc;
00064 double diff0, diff1, diff2, diff3;
00065 Iterator1 lastgroup = last1 - 3;
00066
00067
00068 while (first1 < lastgroup) {
00069 diff0 = first1[0] - first2[0];
00070 diff1 = first1[1] - first2[1];
00071 diff2 = first1[2] - first2[2];
00072 diff3 = first1[3] - first2[3];
00073 distsq += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
00074 first1 += 4;
00075 first2 += 4;
00076 }
00077
00078 while (first1 < last1) {
00079 diff0 = *first1++ - *first2++;
00080 distsq += diff0 * diff0;
00081 }
00082 return distsq;
00083 }
00084
00085 CV_EXPORTS double euclidean_dist(const unsigned char* first1, const unsigned char* last1, unsigned char* first2, double acc);
00086
00087
00094 template <typename Iterator1, typename Iterator2>
00095 double manhattan_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00096 {
00097 double distsq = acc;
00098 double diff0, diff1, diff2, diff3;
00099 Iterator1 lastgroup = last1 - 3;
00100
00101
00102 while (first1 < lastgroup) {
00103 diff0 = fabs(first1[0] - first2[0]);
00104 diff1 = fabs(first1[1] - first2[1]);
00105 diff2 = fabs(first1[2] - first2[2]);
00106 diff3 = fabs(first1[3] - first2[3]);
00107 distsq += diff0 + diff1 + diff2 + diff3;
00108 first1 += 4;
00109 first2 += 4;
00110 }
00111
00112 while (first1 < last1) {
00113 diff0 = fabs(*first1++ - *first2++);
00114 distsq += diff0;
00115 }
00116 return distsq;
00117 }
00118
00119
00120 CV_EXPORTS int flann_minkowski_order();
00130 template <typename Iterator1, typename Iterator2>
00131 double minkowski_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00132 {
00133 double distsq = acc;
00134 double diff0, diff1, diff2, diff3;
00135 Iterator1 lastgroup = last1 - 3;
00136
00137 int p = flann_minkowski_order();
00138
00139
00140 while (first1 < lastgroup) {
00141 diff0 = fabs(first1[0] - first2[0]);
00142 diff1 = fabs(first1[1] - first2[1]);
00143 diff2 = fabs(first1[2] - first2[2]);
00144 diff3 = fabs(first1[3] - first2[3]);
00145 distsq += pow(diff0,p) + pow(diff1,p) + pow(diff2,p) + pow(diff3,p);
00146 first1 += 4;
00147 first2 += 4;
00148 }
00149
00150 while (first1 < last1) {
00151 diff0 = fabs(*first1++ - *first2++);
00152 distsq += pow(diff0,p);
00153 }
00154 return distsq;
00155 }
00156
00157
00158
00159 template <typename Iterator1, typename Iterator2>
00160 double max_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00161 {
00162 double dist = acc;
00163 Iterator1 lastgroup = last1 - 3;
00164 double diff0, diff1, diff2, diff3;
00165
00166
00167 while (first1 < lastgroup) {
00168 diff0 = fabs(first1[0] - first2[0]);
00169 diff1 = fabs(first1[1] - first2[1]);
00170 diff2 = fabs(first1[2] - first2[2]);
00171 diff3 = fabs(first1[3] - first2[3]);
00172 if (diff0 > dist) dist = diff0;
00173 if (diff1 > dist) dist = diff1;
00174 if (diff2 > dist) dist = diff2;
00175 if (diff3 > dist) dist = diff3;
00176 first1 += 4;
00177 first2 += 4;
00178 }
00179
00180 while (first1 < last1) {
00181 diff0 = fabs(*first1++ - *first2++);
00182 dist = (diff0 > dist) ? diff0 : dist;
00183 }
00184 return dist;
00185 }
00186
00187
00188 template <typename Iterator1, typename Iterator2>
00189 double hist_intersection_kernel(Iterator1 first1, Iterator1 last1, Iterator2 first2)
00190 {
00191 double kernel = 0;
00192 Iterator1 lastgroup = last1 - 3;
00193 double min0, min1, min2, min3;
00194
00195
00196 while (first1 < lastgroup) {
00197 min0 = first1[0] < first2[0] ? first1[0] : first2[0];
00198 min1 = first1[1] < first2[1] ? first1[1] : first2[1];
00199 min2 = first1[2] < first2[2] ? first1[2] : first2[2];
00200 min3 = first1[3] < first2[3] ? first1[3] : first2[3];
00201 kernel += min0 + min1 + min2 + min3;
00202 first1 += 4;
00203 first2 += 4;
00204 }
00205
00206 while (first1 < last1) {
00207 min0 = first1[0] < first2[0] ? first1[0] : first2[0];
00208 kernel += min0;
00209 first1++;
00210 first2++;
00211 }
00212 return kernel;
00213 }
00214
00215 template <typename Iterator1, typename Iterator2>
00216 double hist_intersection_dist_sq(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00217 {
00218 double dist_sq = acc - 2 * hist_intersection_kernel(first1, last1, first2);
00219 while (first1 < last1) {
00220 dist_sq += *first1 + *first2;
00221 first1++;
00222 first2++;
00223 }
00224 return dist_sq;
00225 }
00226
00227
00228
00229 template <typename Iterator1, typename Iterator2>
00230 double hellinger_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00231 {
00232 double distsq = acc;
00233 double diff0, diff1, diff2, diff3;
00234 Iterator1 lastgroup = last1 - 3;
00235
00236
00237 while (first1 < lastgroup) {
00238 diff0 = sqrt(first1[0]) - sqrt(first2[0]);
00239 diff1 = sqrt(first1[1]) - sqrt(first2[1]);
00240 diff2 = sqrt(first1[2]) - sqrt(first2[2]);
00241 diff3 = sqrt(first1[3]) - sqrt(first2[3]);
00242 distsq += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
00243 first1 += 4;
00244 first2 += 4;
00245 }
00246
00247 while (first1 < last1) {
00248 diff0 = sqrt(*first1++) - sqrt(*first2++);
00249 distsq += diff0 * diff0;
00250 }
00251 return distsq;
00252 }
00253
00254
00255
00256 template <typename Iterator1, typename Iterator2>
00257 double chi_square_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00258 {
00259 double dist = acc;
00260
00261 while (first1 < last1) {
00262 double sum = *first1 + *first2;
00263 if (sum > 0) {
00264 double diff = *first1 - *first2;
00265 dist += diff * diff / sum;
00266 }
00267 first1++;
00268 first2++;
00269 }
00270 return dist;
00271 }
00272
00273
00274
00275 template <typename Iterator1, typename Iterator2>
00276 double kl_divergence(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00277 {
00278 double div = acc;
00279
00280 while (first1 < last1) {
00281 if (*first2 != 0) {
00282 double ratio = *first1 / *first2;
00283 if (ratio > 0) {
00284 div += *first1 * log(ratio);
00285 }
00286 }
00287 first1++;
00288 first2++;
00289 }
00290 return div;
00291 }
00292
00293
00294
00295
00296 CV_EXPORTS flann_distance_t flann_distance_type();
00304 template <typename Iterator1, typename Iterator2>
00305 double custom_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0)
00306 {
00307 switch (flann_distance_type()) {
00308 case EUCLIDEAN:
00309 return euclidean_dist(first1, last1, first2, acc);
00310 case MANHATTAN:
00311 return manhattan_dist(first1, last1, first2, acc);
00312 case MINKOWSKI:
00313 return minkowski_dist(first1, last1, first2, acc);
00314 case MAX_DIST:
00315 return max_dist(first1, last1, first2, acc);
00316 case HIK:
00317 return hist_intersection_dist_sq(first1, last1, first2, acc);
00318 case HELLINGER:
00319 return hellinger_dist(first1, last1, first2, acc);
00320 case CS:
00321 return chi_square_dist(first1, last1, first2, acc);
00322 case KL:
00323 return kl_divergence(first1, last1, first2, acc);
00324 default:
00325 return euclidean_dist(first1, last1, first2, acc);
00326 }
00327 }
00328
00329
00330
00331
00332
00333
00334
00335
00336 template <typename T>
00337 struct ZeroIterator {
00338
00339 T operator*() {
00340 return 0;
00341 }
00342
00343 T operator[](int) {
00344 return 0;
00345 }
00346
00347 ZeroIterator<T>& operator ++(int) {
00348 return *this;
00349 }
00350
00351 ZeroIterator<T>& operator+=(int) {
00352 return *this;
00353 }
00354
00355 };
00356
00357 CV_EXPORTS ZeroIterator<float>& zero();
00358
00359 }
00360
00361 #endif //_OPENCV_DIST_H_