Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: RZ_A2M_Mbed_samples
dist.h
00001 /*********************************************************************** 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright 2008-2009 Marius Muja (mariusm@cs.ubc.ca). All rights reserved. 00005 * Copyright 2008-2009 David G. Lowe (lowe@cs.ubc.ca). All rights reserved. 00006 * 00007 * THE BSD LICENSE 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 00019 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00020 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00021 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00022 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00023 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00024 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00025 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00026 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00028 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 *************************************************************************/ 00030 00031 #ifndef OPENCV_FLANN_DIST_H_ 00032 #define OPENCV_FLANN_DIST_H_ 00033 00034 #include <cmath> 00035 #include <cstdlib> 00036 #include <string.h> 00037 #ifdef _MSC_VER 00038 typedef unsigned __int32 uint32_t; 00039 typedef unsigned __int64 uint64_t; 00040 #else 00041 #include <stdint.h> 00042 #endif 00043 00044 #include "defines.h" 00045 00046 #if (defined WIN32 || defined _WIN32) && defined(_M_ARM) 00047 # include <Intrin.h> 00048 #endif 00049 00050 #ifdef __ARM_NEON__ 00051 # include "arm_neon.h" 00052 #endif 00053 00054 namespace cvflann 00055 { 00056 00057 template<typename T> 00058 inline T abs(T x) { return (x<0) ? -x : x; } 00059 00060 template<> 00061 inline int abs<int>(int x) { return ::abs(x); } 00062 00063 template<> 00064 inline float abs<float>(float x) { return fabsf(x); } 00065 00066 template<> 00067 inline double abs<double>(double x) { return fabs(x); } 00068 00069 template<typename T> 00070 struct Accumulator { typedef T Type; }; 00071 template<> 00072 struct Accumulator<unsigned char> { typedef float Type; }; 00073 template<> 00074 struct Accumulator<unsigned short> { typedef float Type; }; 00075 template<> 00076 struct Accumulator<unsigned int> { typedef float Type; }; 00077 template<> 00078 struct Accumulator<char> { typedef float Type; }; 00079 template<> 00080 struct Accumulator<short> { typedef float Type; }; 00081 template<> 00082 struct Accumulator<int> { typedef float Type; }; 00083 00084 #undef True 00085 #undef False 00086 00087 class True 00088 { 00089 }; 00090 00091 class False 00092 { 00093 }; 00094 00095 00096 /** 00097 * Squared Euclidean distance functor. 00098 * 00099 * This is the simpler, unrolled version. This is preferable for 00100 * very low dimensionality data (eg 3D points) 00101 */ 00102 template<class T> 00103 struct L2_Simple 00104 { 00105 typedef True is_kdtree_distance; 00106 typedef True is_vector_space_distance; 00107 00108 typedef T ElementType; 00109 typedef typename Accumulator<T>::Type ResultType; 00110 00111 template <typename Iterator1, typename Iterator2> 00112 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const 00113 { 00114 ResultType result = ResultType(); 00115 ResultType diff; 00116 for(size_t i = 0; i < size; ++i ) { 00117 diff = *a++ - *b++; 00118 result += diff*diff; 00119 } 00120 return result; 00121 } 00122 00123 template <typename U, typename V> 00124 inline ResultType accum_dist(const U& a, const V& b, int) const 00125 { 00126 return (a-b)*(a-b); 00127 } 00128 }; 00129 00130 00131 00132 /** 00133 * Squared Euclidean distance functor, optimized version 00134 */ 00135 template<class T> 00136 struct L2 00137 { 00138 typedef True is_kdtree_distance; 00139 typedef True is_vector_space_distance; 00140 00141 typedef T ElementType; 00142 typedef typename Accumulator<T>::Type ResultType; 00143 00144 /** 00145 * Compute the squared Euclidean distance between two vectors. 00146 * 00147 * This is highly optimised, with loop unrolling, as it is one 00148 * of the most expensive inner loops. 00149 * 00150 * The computation of squared root at the end is omitted for 00151 * efficiency. 00152 */ 00153 template <typename Iterator1, typename Iterator2> 00154 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00155 { 00156 ResultType result = ResultType(); 00157 ResultType diff0, diff1, diff2, diff3; 00158 Iterator1 last = a + size; 00159 Iterator1 lastgroup = last - 3; 00160 00161 /* Process 4 items with each loop for efficiency. */ 00162 while (a < lastgroup) { 00163 diff0 = (ResultType)(a[0] - b[0]); 00164 diff1 = (ResultType)(a[1] - b[1]); 00165 diff2 = (ResultType)(a[2] - b[2]); 00166 diff3 = (ResultType)(a[3] - b[3]); 00167 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; 00168 a += 4; 00169 b += 4; 00170 00171 if ((worst_dist>0)&&(result>worst_dist)) { 00172 return result; 00173 } 00174 } 00175 /* Process last 0-3 pixels. Not needed for standard vector lengths. */ 00176 while (a < last) { 00177 diff0 = (ResultType)(*a++ - *b++); 00178 result += diff0 * diff0; 00179 } 00180 return result; 00181 } 00182 00183 /** 00184 * Partial euclidean distance, using just one dimension. This is used by the 00185 * kd-tree when computing partial distances while traversing the tree. 00186 * 00187 * Squared root is omitted for efficiency. 00188 */ 00189 template <typename U, typename V> 00190 inline ResultType accum_dist(const U& a, const V& b, int) const 00191 { 00192 return (a-b)*(a-b); 00193 } 00194 }; 00195 00196 00197 /* 00198 * Manhattan distance functor, optimized version 00199 */ 00200 template<class T> 00201 struct L1 00202 { 00203 typedef True is_kdtree_distance; 00204 typedef True is_vector_space_distance; 00205 00206 typedef T ElementType; 00207 typedef typename Accumulator<T>::Type ResultType; 00208 00209 /** 00210 * Compute the Manhattan (L_1) distance between two vectors. 00211 * 00212 * This is highly optimised, with loop unrolling, as it is one 00213 * of the most expensive inner loops. 00214 */ 00215 template <typename Iterator1, typename Iterator2> 00216 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00217 { 00218 ResultType result = ResultType(); 00219 ResultType diff0, diff1, diff2, diff3; 00220 Iterator1 last = a + size; 00221 Iterator1 lastgroup = last - 3; 00222 00223 /* Process 4 items with each loop for efficiency. */ 00224 while (a < lastgroup) { 00225 diff0 = (ResultType)abs(a[0] - b[0]); 00226 diff1 = (ResultType)abs(a[1] - b[1]); 00227 diff2 = (ResultType)abs(a[2] - b[2]); 00228 diff3 = (ResultType)abs(a[3] - b[3]); 00229 result += diff0 + diff1 + diff2 + diff3; 00230 a += 4; 00231 b += 4; 00232 00233 if ((worst_dist>0)&&(result>worst_dist)) { 00234 return result; 00235 } 00236 } 00237 /* Process last 0-3 pixels. Not needed for standard vector lengths. */ 00238 while (a < last) { 00239 diff0 = (ResultType)abs(*a++ - *b++); 00240 result += diff0; 00241 } 00242 return result; 00243 } 00244 00245 /** 00246 * Partial distance, used by the kd-tree. 00247 */ 00248 template <typename U, typename V> 00249 inline ResultType accum_dist(const U& a, const V& b, int) const 00250 { 00251 return abs(a-b); 00252 } 00253 }; 00254 00255 00256 00257 template<class T> 00258 struct MinkowskiDistance 00259 { 00260 typedef True is_kdtree_distance; 00261 typedef True is_vector_space_distance; 00262 00263 typedef T ElementType; 00264 typedef typename Accumulator<T>::Type ResultType; 00265 00266 int order; 00267 00268 MinkowskiDistance(int order_) : order(order_) {} 00269 00270 /** 00271 * Compute the Minkowsky (L_p) distance between two vectors. 00272 * 00273 * This is highly optimised, with loop unrolling, as it is one 00274 * of the most expensive inner loops. 00275 * 00276 * The computation of squared root at the end is omitted for 00277 * efficiency. 00278 */ 00279 template <typename Iterator1, typename Iterator2> 00280 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00281 { 00282 ResultType result = ResultType(); 00283 ResultType diff0, diff1, diff2, diff3; 00284 Iterator1 last = a + size; 00285 Iterator1 lastgroup = last - 3; 00286 00287 /* Process 4 items with each loop for efficiency. */ 00288 while (a < lastgroup) { 00289 diff0 = (ResultType)abs(a[0] - b[0]); 00290 diff1 = (ResultType)abs(a[1] - b[1]); 00291 diff2 = (ResultType)abs(a[2] - b[2]); 00292 diff3 = (ResultType)abs(a[3] - b[3]); 00293 result += pow(diff0,order) + pow(diff1,order) + pow(diff2,order) + pow(diff3,order); 00294 a += 4; 00295 b += 4; 00296 00297 if ((worst_dist>0)&&(result>worst_dist)) { 00298 return result; 00299 } 00300 } 00301 /* Process last 0-3 pixels. Not needed for standard vector lengths. */ 00302 while (a < last) { 00303 diff0 = (ResultType)abs(*a++ - *b++); 00304 result += pow(diff0,order); 00305 } 00306 return result; 00307 } 00308 00309 /** 00310 * Partial distance, used by the kd-tree. 00311 */ 00312 template <typename U, typename V> 00313 inline ResultType accum_dist(const U& a, const V& b, int) const 00314 { 00315 return pow(static_cast<ResultType>(abs(a-b)),order); 00316 } 00317 }; 00318 00319 00320 00321 template<class T> 00322 struct MaxDistance 00323 { 00324 typedef False is_kdtree_distance; 00325 typedef True is_vector_space_distance; 00326 00327 typedef T ElementType; 00328 typedef typename Accumulator<T>::Type ResultType; 00329 00330 /** 00331 * Compute the max distance (L_infinity) between two vectors. 00332 * 00333 * This distance is not a valid kdtree distance, it's not dimensionwise additive. 00334 */ 00335 template <typename Iterator1, typename Iterator2> 00336 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00337 { 00338 ResultType result = ResultType(); 00339 ResultType diff0, diff1, diff2, diff3; 00340 Iterator1 last = a + size; 00341 Iterator1 lastgroup = last - 3; 00342 00343 /* Process 4 items with each loop for efficiency. */ 00344 while (a < lastgroup) { 00345 diff0 = abs(a[0] - b[0]); 00346 diff1 = abs(a[1] - b[1]); 00347 diff2 = abs(a[2] - b[2]); 00348 diff3 = abs(a[3] - b[3]); 00349 if (diff0>result) {result = diff0; } 00350 if (diff1>result) {result = diff1; } 00351 if (diff2>result) {result = diff2; } 00352 if (diff3>result) {result = diff3; } 00353 a += 4; 00354 b += 4; 00355 00356 if ((worst_dist>0)&&(result>worst_dist)) { 00357 return result; 00358 } 00359 } 00360 /* Process last 0-3 pixels. Not needed for standard vector lengths. */ 00361 while (a < last) { 00362 diff0 = abs(*a++ - *b++); 00363 result = (diff0>result) ? diff0 : result; 00364 } 00365 return result; 00366 } 00367 00368 /* This distance functor is not dimension-wise additive, which 00369 * makes it an invalid kd-tree distance, not implementing the accum_dist method */ 00370 00371 }; 00372 00373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00374 00375 /** 00376 * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor 00377 * bit count of A exclusive XOR'ed with B 00378 */ 00379 struct HammingLUT 00380 { 00381 typedef False is_kdtree_distance; 00382 typedef False is_vector_space_distance; 00383 00384 typedef unsigned char ElementType; 00385 typedef int ResultType; 00386 00387 /** this will count the bits in a ^ b 00388 */ 00389 ResultType operator()(const unsigned char* a, const unsigned char* b, size_t size) const 00390 { 00391 static const uchar popCountTable[] = 00392 { 00393 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 00394 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 00395 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 00396 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 00397 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 00398 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 00399 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 00400 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 00401 }; 00402 ResultType result = 0; 00403 for (size_t i = 0; i < size; i++) { 00404 result += popCountTable[a[i] ^ b[i]]; 00405 } 00406 return result; 00407 } 00408 }; 00409 00410 /** 00411 * Hamming distance functor (pop count between two binary vectors, i.e. xor them and count the number of bits set) 00412 * That code was taken from brief.cpp in OpenCV 00413 */ 00414 template<class T> 00415 struct Hamming 00416 { 00417 typedef False is_kdtree_distance; 00418 typedef False is_vector_space_distance; 00419 00420 00421 typedef T ElementType; 00422 typedef int ResultType; 00423 00424 template<typename Iterator1, typename Iterator2> 00425 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const 00426 { 00427 ResultType result = 0; 00428 #ifdef __ARM_NEON__ 00429 { 00430 uint32x4_t bits = vmovq_n_u32(0); 00431 for (size_t i = 0; i < size; i += 16) { 00432 uint8x16_t A_vec = vld1q_u8 (a + i); 00433 uint8x16_t B_vec = vld1q_u8 (b + i); 00434 uint8x16_t AxorB = veorq_u8 (A_vec, B_vec); 00435 uint8x16_t bitsSet = vcntq_u8 (AxorB); 00436 uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet); 00437 uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8); 00438 bits = vaddq_u32(bits, bitSet4); 00439 } 00440 uint64x2_t bitSet2 = vpaddlq_u32 (bits); 00441 result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0); 00442 result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2); 00443 } 00444 #elif __GNUC__ 00445 { 00446 //for portability just use unsigned long -- and use the __builtin_popcountll (see docs for __builtin_popcountll) 00447 typedef unsigned long long pop_t; 00448 const size_t modulo = size % sizeof(pop_t); 00449 const pop_t* a2 = reinterpret_cast<const pop_t*> (a); 00450 const pop_t* b2 = reinterpret_cast<const pop_t*> (b); 00451 const pop_t* a2_end = a2 + (size / sizeof(pop_t)); 00452 00453 for (; a2 != a2_end; ++a2, ++b2) result += __builtin_popcountll((*a2) ^ (*b2)); 00454 00455 if (modulo) { 00456 //in the case where size is not dividable by sizeof(size_t) 00457 //need to mask off the bits at the end 00458 pop_t a_final = 0, b_final = 0; 00459 memcpy(&a_final, a2, modulo); 00460 memcpy(&b_final, b2, modulo); 00461 result += __builtin_popcountll(a_final ^ b_final); 00462 } 00463 } 00464 #else // NO NEON and NOT GNUC 00465 typedef unsigned long long pop_t; 00466 HammingLUT lut; 00467 result = lut(reinterpret_cast<const unsigned char*> (a), 00468 reinterpret_cast<const unsigned char*> (b), size * sizeof(pop_t)); 00469 #endif 00470 return result; 00471 } 00472 }; 00473 00474 template<typename T> 00475 struct Hamming2 00476 { 00477 typedef False is_kdtree_distance; 00478 typedef False is_vector_space_distance; 00479 00480 typedef T ElementType; 00481 typedef int ResultType; 00482 00483 /** This is popcount_3() from: 00484 * http://en.wikipedia.org/wiki/Hamming_weight */ 00485 unsigned int popcnt32(uint32_t n) const 00486 { 00487 n -= ((n >> 1) & 0x55555555); 00488 n = (n & 0x33333333) + ((n >> 2) & 0x33333333); 00489 return (((n + (n >> 4))& 0xF0F0F0F)* 0x1010101) >> 24; 00490 } 00491 00492 #ifdef FLANN_PLATFORM_64_BIT 00493 unsigned int popcnt64(uint64_t n) const 00494 { 00495 n -= ((n >> 1) & 0x5555555555555555); 00496 n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333); 00497 return (((n + (n >> 4))& 0x0f0f0f0f0f0f0f0f)* 0x0101010101010101) >> 56; 00498 } 00499 #endif 00500 00501 template <typename Iterator1, typename Iterator2> 00502 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const 00503 { 00504 #ifdef FLANN_PLATFORM_64_BIT 00505 const uint64_t* pa = reinterpret_cast<const uint64_t*>(a); 00506 const uint64_t* pb = reinterpret_cast<const uint64_t*>(b); 00507 ResultType result = 0; 00508 size /= (sizeof(uint64_t)/sizeof(unsigned char)); 00509 for(size_t i = 0; i < size; ++i ) { 00510 result += popcnt64(*pa ^ *pb); 00511 ++pa; 00512 ++pb; 00513 } 00514 #else 00515 const uint32_t* pa = reinterpret_cast<const uint32_t*>(a); 00516 const uint32_t* pb = reinterpret_cast<const uint32_t*>(b); 00517 ResultType result = 0; 00518 size /= (sizeof(uint32_t)/sizeof(unsigned char)); 00519 for(size_t i = 0; i < size; ++i ) { 00520 result += popcnt32(*pa ^ *pb); 00521 ++pa; 00522 ++pb; 00523 } 00524 #endif 00525 return result; 00526 } 00527 }; 00528 00529 00530 00531 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00532 00533 template<class T> 00534 struct HistIntersectionDistance 00535 { 00536 typedef True is_kdtree_distance; 00537 typedef True is_vector_space_distance; 00538 00539 typedef T ElementType; 00540 typedef typename Accumulator<T>::Type ResultType; 00541 00542 /** 00543 * Compute the histogram intersection distance 00544 */ 00545 template <typename Iterator1, typename Iterator2> 00546 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00547 { 00548 ResultType result = ResultType(); 00549 ResultType min0, min1, min2, min3; 00550 Iterator1 last = a + size; 00551 Iterator1 lastgroup = last - 3; 00552 00553 /* Process 4 items with each loop for efficiency. */ 00554 while (a < lastgroup) { 00555 min0 = (ResultType)(a[0] < b[0] ? a[0] : b[0]); 00556 min1 = (ResultType)(a[1] < b[1] ? a[1] : b[1]); 00557 min2 = (ResultType)(a[2] < b[2] ? a[2] : b[2]); 00558 min3 = (ResultType)(a[3] < b[3] ? a[3] : b[3]); 00559 result += min0 + min1 + min2 + min3; 00560 a += 4; 00561 b += 4; 00562 if ((worst_dist>0)&&(result>worst_dist)) { 00563 return result; 00564 } 00565 } 00566 /* Process last 0-3 pixels. Not needed for standard vector lengths. */ 00567 while (a < last) { 00568 min0 = (ResultType)(*a < *b ? *a : *b); 00569 result += min0; 00570 ++a; 00571 ++b; 00572 } 00573 return result; 00574 } 00575 00576 /** 00577 * Partial distance, used by the kd-tree. 00578 */ 00579 template <typename U, typename V> 00580 inline ResultType accum_dist(const U& a, const V& b, int) const 00581 { 00582 return a<b ? a : b; 00583 } 00584 }; 00585 00586 00587 00588 template<class T> 00589 struct HellingerDistance 00590 { 00591 typedef True is_kdtree_distance; 00592 typedef True is_vector_space_distance; 00593 00594 typedef T ElementType; 00595 typedef typename Accumulator<T>::Type ResultType; 00596 00597 /** 00598 * Compute the Hellinger distance 00599 */ 00600 template <typename Iterator1, typename Iterator2> 00601 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const 00602 { 00603 ResultType result = ResultType(); 00604 ResultType diff0, diff1, diff2, diff3; 00605 Iterator1 last = a + size; 00606 Iterator1 lastgroup = last - 3; 00607 00608 /* Process 4 items with each loop for efficiency. */ 00609 while (a < lastgroup) { 00610 diff0 = sqrt(static_cast<ResultType>(a[0])) - sqrt(static_cast<ResultType>(b[0])); 00611 diff1 = sqrt(static_cast<ResultType>(a[1])) - sqrt(static_cast<ResultType>(b[1])); 00612 diff2 = sqrt(static_cast<ResultType>(a[2])) - sqrt(static_cast<ResultType>(b[2])); 00613 diff3 = sqrt(static_cast<ResultType>(a[3])) - sqrt(static_cast<ResultType>(b[3])); 00614 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; 00615 a += 4; 00616 b += 4; 00617 } 00618 while (a < last) { 00619 diff0 = sqrt(static_cast<ResultType>(*a++)) - sqrt(static_cast<ResultType>(*b++)); 00620 result += diff0 * diff0; 00621 } 00622 return result; 00623 } 00624 00625 /** 00626 * Partial distance, used by the kd-tree. 00627 */ 00628 template <typename U, typename V> 00629 inline ResultType accum_dist(const U& a, const V& b, int) const 00630 { 00631 ResultType diff = sqrt(static_cast<ResultType>(a)) - sqrt(static_cast<ResultType>(b)); 00632 return diff * diff; 00633 } 00634 }; 00635 00636 00637 template<class T> 00638 struct ChiSquareDistance 00639 { 00640 typedef True is_kdtree_distance; 00641 typedef True is_vector_space_distance; 00642 00643 typedef T ElementType; 00644 typedef typename Accumulator<T>::Type ResultType; 00645 00646 /** 00647 * Compute the chi-square distance 00648 */ 00649 template <typename Iterator1, typename Iterator2> 00650 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00651 { 00652 ResultType result = ResultType(); 00653 ResultType sum, diff; 00654 Iterator1 last = a + size; 00655 00656 while (a < last) { 00657 sum = (ResultType)(*a + *b); 00658 if (sum>0) { 00659 diff = (ResultType)(*a - *b); 00660 result += diff*diff/sum; 00661 } 00662 ++a; 00663 ++b; 00664 00665 if ((worst_dist>0)&&(result>worst_dist)) { 00666 return result; 00667 } 00668 } 00669 return result; 00670 } 00671 00672 /** 00673 * Partial distance, used by the kd-tree. 00674 */ 00675 template <typename U, typename V> 00676 inline ResultType accum_dist(const U& a, const V& b, int) const 00677 { 00678 ResultType result = ResultType(); 00679 ResultType sum, diff; 00680 00681 sum = (ResultType)(a+b); 00682 if (sum>0) { 00683 diff = (ResultType)(a-b); 00684 result = diff*diff/sum; 00685 } 00686 return result; 00687 } 00688 }; 00689 00690 00691 template<class T> 00692 struct KL_Divergence 00693 { 00694 typedef True is_kdtree_distance; 00695 typedef True is_vector_space_distance; 00696 00697 typedef T ElementType; 00698 typedef typename Accumulator<T>::Type ResultType; 00699 00700 /** 00701 * Compute the Kullback–Leibler divergence 00702 */ 00703 template <typename Iterator1, typename Iterator2> 00704 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const 00705 { 00706 ResultType result = ResultType(); 00707 Iterator1 last = a + size; 00708 00709 while (a < last) { 00710 if (* b != 0) { 00711 ResultType ratio = (ResultType)(*a / *b); 00712 if (ratio>0) { 00713 result += *a * log(ratio); 00714 } 00715 } 00716 ++a; 00717 ++b; 00718 00719 if ((worst_dist>0)&&(result>worst_dist)) { 00720 return result; 00721 } 00722 } 00723 return result; 00724 } 00725 00726 /** 00727 * Partial distance, used by the kd-tree. 00728 */ 00729 template <typename U, typename V> 00730 inline ResultType accum_dist(const U& a, const V& b, int) const 00731 { 00732 ResultType result = ResultType(); 00733 if( *b != 0 ) { 00734 ResultType ratio = (ResultType)(a / b); 00735 if (ratio>0) { 00736 result = a * log(ratio); 00737 } 00738 } 00739 return result; 00740 } 00741 }; 00742 00743 00744 00745 /* 00746 * This is a "zero iterator". It basically behaves like a zero filled 00747 * array to all algorithms that use arrays as iterators (STL style). 00748 * It's useful when there's a need to compute the distance between feature 00749 * and origin it and allows for better compiler optimisation than using a 00750 * zero-filled array. 00751 */ 00752 template <typename T> 00753 struct ZeroIterator 00754 { 00755 00756 T operator*() 00757 { 00758 return 0; 00759 } 00760 00761 T operator[](int) 00762 { 00763 return 0; 00764 } 00765 00766 const ZeroIterator<T>& operator ++() 00767 { 00768 return *this; 00769 } 00770 00771 ZeroIterator<T> operator ++(int) 00772 { 00773 return *this; 00774 } 00775 00776 ZeroIterator<T>& operator+=(int) 00777 { 00778 return *this; 00779 } 00780 00781 }; 00782 00783 00784 /* 00785 * Depending on processed distances, some of them are already squared (e.g. L2) 00786 * and some are not (e.g.Hamming). In KMeans++ for instance we want to be sure 00787 * we are working on ^2 distances, thus following templates to ensure that. 00788 */ 00789 template <typename Distance, typename ElementType> 00790 struct squareDistance 00791 { 00792 typedef typename Distance::ResultType ResultType; 00793 ResultType operator()( ResultType dist ) { return dist*dist; } 00794 }; 00795 00796 00797 template <typename ElementType> 00798 struct squareDistance<L2_Simple<ElementType>, ElementType> 00799 { 00800 typedef typename L2_Simple<ElementType>::ResultType ResultType; 00801 ResultType operator()( ResultType dist ) { return dist; } 00802 }; 00803 00804 template <typename ElementType> 00805 struct squareDistance<L2<ElementType>, ElementType> 00806 { 00807 typedef typename L2<ElementType>::ResultType ResultType; 00808 ResultType operator()( ResultType dist ) { return dist; } 00809 }; 00810 00811 00812 template <typename ElementType> 00813 struct squareDistance<MinkowskiDistance<ElementType>, ElementType> 00814 { 00815 typedef typename MinkowskiDistance<ElementType>::ResultType ResultType; 00816 ResultType operator()( ResultType dist ) { return dist; } 00817 }; 00818 00819 template <typename ElementType> 00820 struct squareDistance<HellingerDistance<ElementType>, ElementType> 00821 { 00822 typedef typename HellingerDistance<ElementType>::ResultType ResultType; 00823 ResultType operator()( ResultType dist ) { return dist; } 00824 }; 00825 00826 template <typename ElementType> 00827 struct squareDistance<ChiSquareDistance<ElementType>, ElementType> 00828 { 00829 typedef typename ChiSquareDistance<ElementType>::ResultType ResultType; 00830 ResultType operator()( ResultType dist ) { return dist; } 00831 }; 00832 00833 00834 template <typename Distance> 00835 typename Distance::ResultType ensureSquareDistance( typename Distance::ResultType dist ) 00836 { 00837 typedef typename Distance::ElementType ElementType; 00838 00839 squareDistance<Distance, ElementType> dummy; 00840 return dummy( dist ); 00841 } 00842 00843 00844 /* 00845 * ...and a template to ensure the user that he will process the normal distance, 00846 * and not squared distance, without loosing processing time calling sqrt(ensureSquareDistance) 00847 * that will result in doing actually sqrt(dist*dist) for L1 distance for instance. 00848 */ 00849 template <typename Distance, typename ElementType> 00850 struct simpleDistance 00851 { 00852 typedef typename Distance::ResultType ResultType; 00853 ResultType operator()( ResultType dist ) { return dist; } 00854 }; 00855 00856 00857 template <typename ElementType> 00858 struct simpleDistance<L2_Simple<ElementType>, ElementType> 00859 { 00860 typedef typename L2_Simple<ElementType>::ResultType ResultType; 00861 ResultType operator()( ResultType dist ) { return sqrt(dist); } 00862 }; 00863 00864 template <typename ElementType> 00865 struct simpleDistance<L2<ElementType>, ElementType> 00866 { 00867 typedef typename L2<ElementType>::ResultType ResultType; 00868 ResultType operator()( ResultType dist ) { return sqrt(dist); } 00869 }; 00870 00871 00872 template <typename ElementType> 00873 struct simpleDistance<MinkowskiDistance<ElementType>, ElementType> 00874 { 00875 typedef typename MinkowskiDistance<ElementType>::ResultType ResultType; 00876 ResultType operator()( ResultType dist ) { return sqrt(dist); } 00877 }; 00878 00879 template <typename ElementType> 00880 struct simpleDistance<HellingerDistance<ElementType>, ElementType> 00881 { 00882 typedef typename HellingerDistance<ElementType>::ResultType ResultType; 00883 ResultType operator()( ResultType dist ) { return sqrt(dist); } 00884 }; 00885 00886 template <typename ElementType> 00887 struct simpleDistance<ChiSquareDistance<ElementType>, ElementType> 00888 { 00889 typedef typename ChiSquareDistance<ElementType>::ResultType ResultType; 00890 ResultType operator()( ResultType dist ) { return sqrt(dist); } 00891 }; 00892 00893 00894 template <typename Distance> 00895 typename Distance::ResultType ensureSimpleDistance( typename Distance::ResultType dist ) 00896 { 00897 typedef typename Distance::ElementType ElementType; 00898 00899 simpleDistance<Distance, ElementType> dummy; 00900 return dummy( dist ); 00901 } 00902 00903 } 00904 00905 #endif //OPENCV_FLANN_DIST_H_
Generated on Tue Jul 12 2022 18:20:17 by
