Move templates in dist.h in order to share them between KMeansIndex and HierarchicalC...
authorPierre-Emmanuel Viel <p.emmanuel.viel@gmail.com>
Tue, 17 Dec 2013 12:34:20 +0000 (13:34 +0100)
committerPierre-Emmanuel Viel <p.emmanuel.viel@gmail.com>
Wed, 18 Dec 2013 19:48:34 +0000 (20:48 +0100)
modules/flann/include/opencv2/flann/dist.h
modules/flann/include/opencv2/flann/hierarchical_clustering_index.h
modules/flann/include/opencv2/flann/kmeans_index.h

index 80ae2dc..2afceb8 100644 (file)
@@ -812,6 +812,66 @@ struct ZeroIterator
 
 };
 
+
+/*
+ * Depending on processed distances, some of them are already squared (e.g. L2)
+ * and some are not (e.g.Hamming). In KMeans++ for instance we want to be sure
+ * we are working on ^2 distances, thus following templates to ensure that.
+ */
+template <typename Distance, typename ElementType>
+struct squareDistance
+{
+    typedef typename Distance::ResultType ResultType;
+    ResultType operator()( ResultType dist ) { return dist*dist; }
+};
+
+
+template <typename ElementType>
+struct squareDistance<L2_Simple<ElementType>, ElementType>
+{
+    typedef typename L2_Simple<ElementType>::ResultType ResultType;
+    ResultType operator()( ResultType dist ) { return dist; }
+};
+
+template <typename ElementType>
+struct squareDistance<L2<ElementType>, ElementType>
+{
+    typedef typename L2<ElementType>::ResultType ResultType;
+    ResultType operator()( ResultType dist ) { return dist; }
+};
+
+
+template <typename ElementType>
+struct squareDistance<MinkowskiDistance<ElementType>, ElementType>
+{
+    typedef typename MinkowskiDistance<ElementType>::ResultType ResultType;
+    ResultType operator()( ResultType dist ) { return dist; }
+};
+
+template <typename ElementType>
+struct squareDistance<HellingerDistance<ElementType>, ElementType>
+{
+    typedef typename HellingerDistance<ElementType>::ResultType ResultType;
+    ResultType operator()( ResultType dist ) { return dist; }
+};
+
+template <typename ElementType>
+struct squareDistance<ChiSquareDistance<ElementType>, ElementType>
+{
+    typedef typename ChiSquareDistance<ElementType>::ResultType ResultType;
+    ResultType operator()( ResultType dist ) { return dist; }
+};
+
+
+template <typename Distance>
+typename Distance::ResultType ensureSquareDistance( typename Distance::ResultType dist )
+{
+    typedef typename Distance::ElementType ElementType;
+
+    squareDistance<Distance, ElementType> dummy;
+    return dummy( dist );
+}
+
 }
 
 #endif //OPENCV_FLANN_DIST_H_
index 02fc278..3ccfa55 100644 (file)
@@ -214,7 +214,7 @@ private:
         // far from previous centers (and this complies to "k-means++: the advantages of careful seeding" article)
         for (int i = 0; i < n; i++) {
             closestDistSq[i] = distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols);
-            closestDistSq[i] *= closestDistSq[i];
+            closestDistSq[i] = ensureSquareDistance<Distance>( closestDistSq[i] );
             currentPot += closestDistSq[i];
         }
 
@@ -242,7 +242,7 @@ private:
                 double newPot = 0;
                 for (int i = 0; i < n; i++) {
                     DistanceType dist = distance(dataset[dsindices[i]], dataset[dsindices[index]], dataset.cols);
-                    newPot += std::min( dist*dist, closestDistSq[i] );
+                    newPot += std::min( ensureSquareDistance<Distance>(dist), closestDistSq[i] );
                 }
 
                 // Store the best result
@@ -257,7 +257,7 @@ private:
             currentPot = bestNewPot;
             for (int i = 0; i < n; i++) {
                 DistanceType dist = distance(dataset[dsindices[i]], dataset[dsindices[bestNewIndex]], dataset.cols);
-                closestDistSq[i] = std::min( dist*dist, closestDistSq[i] );
+                closestDistSq[i] = std::min( ensureSquareDistance<Distance>(dist), closestDistSq[i] );
             }
         }
 
index 460dc64..3cbee24 100644 (file)
 namespace cvflann
 {
 
-template <typename Distance, typename ElementType>
-struct squareDistance
-{
-    typedef typename Distance::ResultType ResultType;
-    ResultType operator()( ResultType dist ) { return dist*dist; }
-};
-
-
-template <typename ElementType>
-struct squareDistance<L2_Simple<ElementType>, ElementType>
-{
-    typedef typename L2_Simple<ElementType>::ResultType ResultType;
-    ResultType operator()( ResultType dist ) { return dist; }
-};
-
-template <typename ElementType>
-struct squareDistance<L2<ElementType>, ElementType>
-{
-    typedef typename L2<ElementType>::ResultType ResultType;
-    ResultType operator()( ResultType dist ) { return dist; }
-};
-
-
-template <typename ElementType>
-struct squareDistance<MinkowskiDistance<ElementType>, ElementType>
-{
-    typedef typename MinkowskiDistance<ElementType>::ResultType ResultType;
-    ResultType operator()( ResultType dist ) { return dist; }
-};
-
-template <typename ElementType>
-struct squareDistance<HellingerDistance<ElementType>, ElementType>
-{
-    typedef typename HellingerDistance<ElementType>::ResultType ResultType;
-    ResultType operator()( ResultType dist ) { return dist; }
-};
-
-template <typename ElementType>
-struct squareDistance<ChiSquareDistance<ElementType>, ElementType>
-{
-    typedef typename ChiSquareDistance<ElementType>::ResultType ResultType;
-    ResultType operator()( ResultType dist ) { return dist; }
-};
-
-
-template <typename Distance>
-typename Distance::ResultType ensureSquareDistance( typename Distance::ResultType dist )
-{
-    typedef typename Distance::ElementType ElementType;
-
-    squareDistance<Distance, ElementType> dummy;
-    return dummy( dist );
-}
-
-
-
 struct KMeansIndexParams : public IndexParams
 {
     KMeansIndexParams(int branching = 32, int iterations = 11,