From 0d19685f9544ddf2668fa899ce74580fd9d1039f Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Viel Date: Tue, 17 Dec 2013 13:34:20 +0100 Subject: [PATCH] Move templates in dist.h in order to share them between KMeansIndex and HierarchicalClusteringIndex classes. --- modules/flann/include/opencv2/flann/dist.h | 60 +++++++++++++++++++ .../flann/hierarchical_clustering_index.h | 6 +- .../include/opencv2/flann/kmeans_index.h | 56 ----------------- 3 files changed, 63 insertions(+), 59 deletions(-) diff --git a/modules/flann/include/opencv2/flann/dist.h b/modules/flann/include/opencv2/flann/dist.h index 80ae2dc916..2afceb8893 100644 --- a/modules/flann/include/opencv2/flann/dist.h +++ b/modules/flann/include/opencv2/flann/dist.h @@ -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 +struct squareDistance +{ + typedef typename Distance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist*dist; } +}; + + +template +struct squareDistance, ElementType> +{ + typedef typename L2_Simple::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + +template +struct squareDistance, ElementType> +{ + typedef typename L2::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + + +template +struct squareDistance, ElementType> +{ + typedef typename MinkowskiDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + +template +struct squareDistance, ElementType> +{ + typedef typename HellingerDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + +template +struct squareDistance, ElementType> +{ + typedef typename ChiSquareDistance::ResultType ResultType; + ResultType operator()( ResultType dist ) { return dist; } +}; + + +template +typename Distance::ResultType ensureSquareDistance( typename Distance::ResultType dist ) +{ + typedef typename Distance::ElementType ElementType; + + squareDistance dummy; + return dummy( dist ); +} + } #endif //OPENCV_FLANN_DIST_H_ diff --git a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h index 02fc278448..3ccfa5534b 100644 --- a/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h +++ b/modules/flann/include/opencv2/flann/hierarchical_clustering_index.h @@ -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( 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(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(dist), closestDistSq[i] ); } } diff --git a/modules/flann/include/opencv2/flann/kmeans_index.h b/modules/flann/include/opencv2/flann/kmeans_index.h index 460dc64be9..3cbee24404 100644 --- a/modules/flann/include/opencv2/flann/kmeans_index.h +++ b/modules/flann/include/opencv2/flann/kmeans_index.h @@ -53,62 +53,6 @@ namespace cvflann { -template -struct squareDistance -{ - typedef typename Distance::ResultType ResultType; - ResultType operator()( ResultType dist ) { return dist*dist; } -}; - - -template -struct squareDistance, ElementType> -{ - typedef typename L2_Simple::ResultType ResultType; - ResultType operator()( ResultType dist ) { return dist; } -}; - -template -struct squareDistance, ElementType> -{ - typedef typename L2::ResultType ResultType; - ResultType operator()( ResultType dist ) { return dist; } -}; - - -template -struct squareDistance, ElementType> -{ - typedef typename MinkowskiDistance::ResultType ResultType; - ResultType operator()( ResultType dist ) { return dist; } -}; - -template -struct squareDistance, ElementType> -{ - typedef typename HellingerDistance::ResultType ResultType; - ResultType operator()( ResultType dist ) { return dist; } -}; - -template -struct squareDistance, ElementType> -{ - typedef typename ChiSquareDistance::ResultType ResultType; - ResultType operator()( ResultType dist ) { return dist; } -}; - - -template -typename Distance::ResultType ensureSquareDistance( typename Distance::ResultType dist ) -{ - typedef typename Distance::ElementType ElementType; - - squareDistance dummy; - return dummy( dist ); -} - - - struct KMeansIndexParams : public IndexParams { KMeansIndexParams(int branching = 32, int iterations = 11,