Distance.tcc 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. namespace NICE {
  2. template<class T>
  3. T VectorDistance<T>::calculate(const VectorT<T>& v1 , const VectorT<T>& v2) const {
  4. return doCalculate(v1,v2);
  5. }
  6. template<class T>
  7. T VectorDistance<T>::operator()(const VectorT<T>& v1 , const VectorT<T>& v2) const {
  8. return doCalculate(v1,v2);
  9. }
  10. template<class T>
  11. T EuclidianDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  12. if(v1.size()!=v2.size())
  13. _THROW_EVector("Input vectors must have the same size. v1: ");
  14. T dist = T(0);
  15. // FIXME BUG in version using IPP
  16. // #ifdef NICE_USELIB_IPP
  17. //
  18. // VectorT<Ipp32f> v1f(v1.size()), v2f(v2.size());
  19. //
  20. // ippsConvert(v1.getDataPointer(), v1f.getDataPointer(), v1.size());
  21. // ippsConvert(v2.getDataPointer(), v2f.getDataPointer(), v2.size());
  22. //
  23. // ippsSub_32f(v1f.getDataPointer(), v2f.getDataPointer(), v1f.getDataPointer(), v1f.size());
  24. // ippsSqr_32f(v1f.getDataPointer(), v1f.getDataPointer(), v1f.size());
  25. //
  26. // dist = v1f.Sum();
  27. //
  28. // #else // NICE_USELIB_IPP
  29. const T* pSrc2 = v2.begin();
  30. for(const T* pSrc1 = v1.begin();
  31. pSrc1 < v1.end();
  32. ++pSrc1, ++pSrc2) {
  33. dist += (*pSrc1-*pSrc2)*(*pSrc1-*pSrc2);
  34. }
  35. // #endif // NICE_USELIB_IPP
  36. return T(std::sqrt( (double) dist)); //double cast neccessary, otherwise the template cast is disambigous
  37. }
  38. template<class T>
  39. T MahalanobisDistance<T>::doCalculate( const VectorT<T>& v1, const VectorT<T>& v2 ) const
  40. {
  41. if ( v1.size()!=v2.size() )
  42. _THROW_EVector( "Input vectors must have the same size." );
  43. if ( v1.size()!=m_matrix.rows() )
  44. _THROW_EVector( "Input vectors must have the same size as matrix." );
  45. VectorT<T> difference(v1);
  46. difference -= v2;
  47. VectorT<T> tmp(difference.size());
  48. tmp.multiply(m_matrix, difference);
  49. T dist = std::sqrt(difference.scalarProduct(tmp));
  50. return dist;
  51. }
  52. template<class T>
  53. T ManhattanDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  54. if(v1.size()!=v2.size())
  55. _THROW_EVector("Input vectors must have the same size.");
  56. T d = 0;
  57. ippsNormDiff_L1(v1.getDataPointer(),v2.getDataPointer(),v1.size(),&d);
  58. return d;
  59. };
  60. template<class T>
  61. T MaximumDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  62. if(v1.size()!=v2.size())
  63. _THROW_EVector("Input vectors must have the same size.");
  64. T d = 0;
  65. ippsNormDiff_Inf(v1.getDataPointer(),v2.getDataPointer(),v1.size(),&d);
  66. return d;
  67. };
  68. template<class T>
  69. T MedianDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  70. if(v1.size()!=v2.size())
  71. _THROW_EVector("Input vectors must have the same size.");
  72. VectorT<T> r(v1);
  73. r-=v2;
  74. r.absInplace();
  75. r.sortAscend();
  76. return r[r.size()/2];
  77. };
  78. /**
  79. * @struct SinDistance
  80. * @brief calculate the sinus of the in-between angle
  81. */
  82. template<class T>
  83. T SinDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  84. if(v1.size()!=v2.size())
  85. _THROW_EVector("Input vectors must have the same size.");
  86. T d = 0;
  87. T d1 = 0;
  88. T d2 = 0;
  89. #ifdef NICE_USELIB_IPP
  90. ippsNorm_L2(v1.getDataPointer(), v1.size(), &d1);
  91. ippsNorm_L2(v2.getDataPointer(), v2.size(), &d2);
  92. if(isZero(d1)) d1=T(1.0);
  93. if(isZero(d2)) d2=T(1.0);
  94. ippsDotProd(v1.getDataPointer(),v2.getDataPointer(),v1.size(),&d);
  95. d = d/(d1*d2);
  96. d = static_cast<T>(sqrt(1-d*d));
  97. #else // NICE_USELIB_IPP
  98. typename VectorT<T>::const_iterator it = v1.getDataPointer();
  99. typename VectorT<T>::const_iterator it2 = v2.getDataPointer();
  100. typename VectorT<T>::const_iterator end = v1.getDataPointer() + v1.size();
  101. for(; it < end; it++, it2++) {
  102. d1 += *it* *it;
  103. d2 += *it2* *it2;
  104. }
  105. if(isZero(d1))
  106. d1=T(1.0);
  107. else
  108. d1=sqrt(d1);
  109. if(isZero(d2))
  110. d2=T(1.0);
  111. else
  112. d2=sqrt(d2);
  113. it = v1.getDataPointer();
  114. it2 = v2.getDataPointer();
  115. for(; it < end; it++, it2++)
  116. d += *it * *it2;
  117. d=d/(d1*d2);
  118. d=sqrt(T(1.0)-d*d);
  119. #endif // NICE_USELIB_IPP
  120. return d;
  121. };
  122. /**
  123. * @struct CosDistance
  124. * @brief calculate the cosinus of the in-between angle
  125. */
  126. template<class T>
  127. T CosDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  128. if(v1.size()!=v2.size())
  129. _THROW_EVector("Input vectors must have the same size.");
  130. Ipp32f val=0.0;
  131. if((v1.normL2()*v2.normL2())>1e-8)
  132. {
  133. val = (v1.scalarProduct(v2))/(v1.normL2()*v2.normL2());
  134. }
  135. if(val>=0.0)
  136. {
  137. return static_cast<T>(static_cast<T>(1.0)-val);
  138. }
  139. else
  140. {
  141. return static_cast<T>(static_cast<T>(1.0)+val);
  142. }
  143. };
  144. template<class T>
  145. T Chi2Distance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  146. if(v1.size()!=v2.size())
  147. _THROW_EVector("Input vectors must have the same size.");
  148. T d = 0;
  149. T d1 = 0;
  150. T d2 = 0;
  151. Ipp32f div,fac;
  152. #ifdef NICE_USELIB_IPP
  153. ippsNorm_L2(v1.getDataPointer(),v1.size(),&d1);
  154. ippsNorm_L2(v2.getDataPointer(),v2.size(),&d2);
  155. if(isZero(d1)) d1=1;
  156. if(isZero(d2)) d2=1;
  157. typename VectorT<T>::const_iterator it2 = v2.getDataPointer();
  158. typename VectorT<T>::const_iterator end = v1.getDataPointer() + v2.size();
  159. typename VectorT<T>::const_iterator it = v1.getDataPointer();
  160. for(; it < end; it++, it2++) {
  161. div = (*it/d1 + *it2/d2);
  162. //div = div==0?1e-6:div;
  163. if (std::fabs(div) < std::numeric_limits<T>::epsilon()) {
  164. div = std::numeric_limits<T>::epsilon();
  165. }
  166. fac = *it/d1-div;
  167. d += static_cast<T>(fac*fac/div);
  168. }
  169. #else // NICE_USELIB_IPP
  170. typename VectorT<T>::const_iterator it2 = v2.getDataPointer();
  171. typename VectorT<T>::const_iterator end = v2.getDataPointer() + v2.size();
  172. for(; it2 < end; it2++) {
  173. d2 += *it2;
  174. }
  175. if(d2==0) d2=1;
  176. typename VectorT<T>::const_iterator it = v1.getDataPointer();
  177. end = v1.getDataPointer() + v1.size();
  178. for(; it < end; it++) {
  179. d1 += *it;
  180. }
  181. if(isZero(d1)) d1=1;
  182. it = v1.getDataPointer();
  183. it2 = v2.getDataPointer();
  184. for(; it < end; it++, it2++) {
  185. div=(*it/d1 + *it2/d2)/2.;
  186. if (std::fabs(div) < std::numeric_limits<T>::epsilon()) {
  187. div = std::numeric_limits<T>::epsilon();
  188. }
  189. fac=*it/d1-div;
  190. d+=fac*fac/div;
  191. }
  192. #endif // NICE_USELIB_IPP
  193. return d;
  194. };
  195. template<class T>
  196. T SphericalDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  197. if(v1.size()!=v2.size())
  198. _THROW_EVector("Input vectors must have the same size.");
  199. return static_cast<T>(acos(sin(v1[1])*sin(v2[1])+cos(v1[1])*cos(v2[1])*cos(v1[0]-v2[0])));
  200. };
  201. template<class T>
  202. T KLDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  203. if(v1.size()!=v2.size())
  204. _THROW_EVector("Input vectors must have the same size.");
  205. Ipp32f res = 0.0;
  206. typename VectorT<T>::const_iterator it2 = v2.begin();
  207. for(typename VectorT<T>::const_iterator it1 = v1.begin(); it1!=v1.end(); ++it1,++it2)
  208. if(*it1>0 && *it2>0)
  209. res += *it1 * log(*it1 / static_cast<float>(*it2));
  210. return static_cast<T>(res);
  211. };
  212. template<class T>
  213. SwappedKLDistance<T>::SwappedKLDistance() {
  214. pKLDistance = new KLDistance<T>();
  215. }
  216. template<class T>
  217. SwappedKLDistance<T>::~SwappedKLDistance() {
  218. delete pKLDistance;
  219. }
  220. template<class T>
  221. T SwappedKLDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  222. if(v1.size()!=v2.size())
  223. _THROW_EVector("Input vectors must have the same size.");
  224. return pKLDistance->calculate(v2, v1);
  225. }
  226. template<class T>
  227. ExtendedKLDistance<T>::ExtendedKLDistance() {
  228. pKLDistance = new KLDistance<T>();
  229. }
  230. template<class T>
  231. ExtendedKLDistance<T>::~ExtendedKLDistance() {
  232. delete pKLDistance;
  233. }
  234. template<class T>
  235. T ExtendedKLDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  236. if(v1.size()!=v2.size())
  237. _THROW_EVector("Input vectors must have the same size.");
  238. return static_cast<T>((pKLDistance->calculate(v1, v2)+pKLDistance->calculate(v2, v1))/2.0);
  239. }
  240. template<class T>
  241. T BhattacharyyaDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2) const {
  242. if(v1.size()!=v2.size())
  243. _THROW_EVector("Input vectors must have the same size.");
  244. Ipp32f B;
  245. #ifdef NICE_USELIB_IPP
  246. VectorT<Ipp32f> v1f(v1.size()), v2f(v2.size());
  247. ippsConvert(v1.getDataPointer(), v1f.getDataPointer(), v1.size());
  248. ippsConvert(v2.getDataPointer(), v2f.getDataPointer(), v2.size());
  249. v1f *= v2f;
  250. ippsSqrt(v1f.getDataPointer(), v1f.getDataPointer(), v1f.size());
  251. ippsSum(v1f.getDataPointer(), v1f.size(), &B);
  252. #else // NICE_USELIB_IPP
  253. B = 0.0;
  254. for(int i=0; i<v1.size(); ++i)
  255. B += std::sqrt(v1[i]*v2[i]);
  256. #endif // NICE_USELIB_IPP
  257. return static_cast<T>(std::sqrt(1-B));
  258. }
  259. template<class T>
  260. T ScalarProductDistance<T>::doCalculate(const VectorT<T>& v1, const VectorT<T>& v2)const {
  261. if(v1.size()!=v2.size())
  262. _THROW_EVector("Input vectors must have the same size.");
  263. VectorT<T> t1(v1);
  264. t1 *= v2;
  265. return -t1.Sum();
  266. }
  267. } // namespace NICE