From c78d056ef69a71794e133cba7e09b44be52b9ca0 Mon Sep 17 00:00:00 2001
From: Vadim Pisarevsky <no@email>
Date: Fri, 27 Apr 2012 13:06:16 +0000
Subject: [PATCH] added BruteForceMatcher (the older variant of BFMatcher) to
 legacy (ticket #1796). added test for it. Renamed legacy tests to "Legacy_*"

---
 .../include/opencv2/features2d/features2d.hpp |  88 -------------
 .../test/test_bruteforcematcher.cpp           | 122 ------------------
 .../legacy/include/opencv2/legacy/legacy.hpp  | 104 +++++++++++++++
 .../legacy/test/test_bruteforcematcher.cpp    | 115 +++++++++++++++++
 modules/legacy/test/test_em.cpp               |   4 +-
 modules/legacy/test/test_nearestneighbors.cpp |   6 +-
 modules/legacy/test/test_optflow.cpp          |   2 +-
 modules/legacy/test/test_pyrsegmentation.cpp  |   2 +-
 modules/legacy/test/test_stereomatching.cpp   |   2 +-
 modules/legacy/test/test_subdivisions.cpp     |   2 +-
 10 files changed, 228 insertions(+), 219 deletions(-)
 delete mode 100644 modules/features2d/test/test_bruteforcematcher.cpp
 create mode 100644 modules/legacy/test/test_bruteforcematcher.cpp

diff --git a/modules/features2d/include/opencv2/features2d/features2d.hpp b/modules/features2d/include/opencv2/features2d/features2d.hpp
index 161aa2a8e9..fe81c1f520 100644
--- a/modules/features2d/include/opencv2/features2d/features2d.hpp
+++ b/modules/features2d/include/opencv2/features2d/features2d.hpp
@@ -737,94 +737,6 @@ protected:
     PixelTestFn test_fn_;
 };
 
-/****************************************************************************************\
-*                                          Distance                                      *
-\****************************************************************************************/
-template<typename T>
-struct CV_EXPORTS Accumulator
-{
-    typedef T Type;
-};
-
-template<> struct Accumulator<unsigned char>  { typedef float Type; };
-template<> struct Accumulator<unsigned short> { typedef float Type; };
-template<> struct Accumulator<char>   { typedef float Type; };
-template<> struct Accumulator<short>  { typedef float Type; };
-
-/*
- * Squared Euclidean distance functor
- */
-template<class T>
-struct CV_EXPORTS SL2
-{
-    typedef T ValueType;
-    typedef typename Accumulator<T>::Type ResultType;
-
-    ResultType operator()( const T* a, const T* b, int size ) const
-    {
-        return normL2Sqr<ValueType, ResultType>(a, b, size);
-    }
-};
-
-/*
- * Euclidean distance functor
- */
-template<class T>
-struct CV_EXPORTS L2
-{
-    typedef T ValueType;
-    typedef typename Accumulator<T>::Type ResultType;
-
-    ResultType operator()( const T* a, const T* b, int size ) const
-    {
-        return (ResultType)sqrt((double)normL2Sqr<ValueType, ResultType>(a, b, size));
-    }
-};
-
-/*
- * Manhattan distance (city block distance) functor
- */
-template<class T>
-struct CV_EXPORTS L1
-{
-    typedef T ValueType;
-    typedef typename Accumulator<T>::Type ResultType;
-
-    ResultType operator()( const T* a, const T* b, int size ) const
-    {
-        return normL1<ValueType, ResultType>(a, b, size);
-    }
-};
-
-/*
- * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
- * bit count of A exclusive XOR'ed with B
- */
-struct CV_EXPORTS Hamming
-{
-    typedef unsigned char ValueType;
-    typedef int ResultType;
-
-    /** this will count the bits in a ^ b
-     */
-    ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
-    {
-        return normHamming(a, b, size);
-    }
-};
-
-typedef Hamming HammingLUT;
-
-template<int cellsize> struct CV_EXPORTS HammingMultilevel
-{
-    typedef unsigned char ValueType;
-    typedef int ResultType;
-    
-    ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
-    {
-        return normHamming(a, b, size, cellsize);
-    }
-};
     
 /****************************************************************************************\
 *                                      DMatch                                            *
diff --git a/modules/features2d/test/test_bruteforcematcher.cpp b/modules/features2d/test/test_bruteforcematcher.cpp
deleted file mode 100644
index f2fdca1934..0000000000
--- a/modules/features2d/test/test_bruteforcematcher.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-#include "test_precomp.hpp"
-
-#if 0
-using namespace cv;
-
-class BruteForceMatcherTest : public cvtest::BaseTest
-{
-public:
-    BruteForceMatcherTest();
-protected:
-    void run( int );
-};
-
-struct CV_EXPORTS L2Fake : public L2<float>
-{
-};
-
-BruteForceMatcherTest::BruteForceMatcherTest() : cvtest::BaseTest( "BruteForceMatcher", "BruteForceMatcher::matchImpl")
-{
-    support_testing_modes = cvtest::TS::TIMING_MODE;
-}
-
-void BruteForceMatcherTest::run( int )
-{
-    const int dimensions = 64;
-    const int descriptorsNumber = 5000;
-
-    Mat train = Mat( descriptorsNumber, dimensions, CV_32FC1);
-    Mat query = Mat( descriptorsNumber, dimensions, CV_32FC1);
-
-    Mat permutation( 1, descriptorsNumber, CV_32SC1 );
-    for( int i=0;i<descriptorsNumber;i++ )
-        permutation.at<int>( 0, i ) = i;
-
-    //RNG rng = RNG( cvGetTickCount() );
-    RNG rng = RNG( *ts->get_rng() );
-    randShuffle( permutation, 1, &rng );
-
-    float boundary =  500.f;
-    for( int row=0;row<descriptorsNumber;row++ )
-    {
-        for( int col=0;col<dimensions;col++ )
-        {
-            int bit = rng( 2 );
-            train.at<float>( permutation.at<int>( 0, row ), col ) = bit*boundary + rng.uniform( 0.f, boundary );
-            query.at<float>( row, col ) = bit*boundary + rng.uniform( 0.f, boundary );
-        }
-    }
-
-    vector<DMatch> specMatches, genericMatches;
-    BruteForceMatcher<L2<float> > specMatcher;
-    BruteForceMatcher<L2Fake > genericMatcher;
-
-    int64 time0 = cvGetTickCount();
-    specMatcher.match( query, train, specMatches );
-    int64 time1 = cvGetTickCount();
-    genericMatcher.match( query, train, genericMatches );
-    int64 time2 = cvGetTickCount();
-
-    float specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
-    ts->printf( cvtest::TS::LOG, "Matching by matrix multiplication time s: %f, us per pair: %f\n",
-               specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
-
-    float genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
-    ts->printf( cvtest::TS::LOG, "Matching without matrix multiplication time s: %f, us per pair: %f\n",
-               genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
-
-    if( (int)specMatches.size() != descriptorsNumber || (int)genericMatches.size() != descriptorsNumber )
-        ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
-    for( int i=0;i<descriptorsNumber;i++ )
-    {
-        float epsilon = 0.01f;
-        bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon &&
-                       specMatches[i].queryIdx == genericMatches[i].queryIdx &&
-                       specMatches[i].trainIdx == genericMatches[i].trainIdx;
-        if( !isEquiv || specMatches[i].trainIdx != permutation.at<int>( 0, i ) )
-        {
-            ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
-            break;
-        }
-    }
-
-
-    //Test mask
-    Mat mask( query.rows, train.rows, CV_8UC1 );
-    rng.fill( mask, RNG::UNIFORM, 0, 2 );
-
-
-    time0 = cvGetTickCount();
-    specMatcher.match( query, train, specMatches, mask );
-    time1 = cvGetTickCount();
-    genericMatcher.match( query, train, genericMatches, mask );
-    time2 = cvGetTickCount();
-
-    specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
-    ts->printf( cvtest::TS::LOG, "Matching by matrix multiplication time with mask s: %f, us per pair: %f\n",
-               specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
-
-    genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
-    ts->printf( cvtest::TS::LOG, "Matching without matrix multiplication time with mask s: %f, us per pair: %f\n",
-               genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
-
-    if( specMatches.size() != genericMatches.size() )
-        ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
-
-    for( size_t i=0;i<specMatches.size();i++ )
-    {
-        //float epsilon = 1e-2;
-        float epsilon = 10000000;
-        bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon &&
-                       specMatches[i].queryIdx == genericMatches[i].queryIdx &&
-                       specMatches[i].trainIdx == genericMatches[i].trainIdx;
-        if( !isEquiv )
-        {
-            ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
-            break;
-        }
-    }
-}
-
-BruteForceMatcherTest taBruteForceMatcherTest;
-#endif
diff --git a/modules/legacy/include/opencv2/legacy/legacy.hpp b/modules/legacy/include/opencv2/legacy/legacy.hpp
index 1f0909b3b4..28b7ec478c 100644
--- a/modules/legacy/include/opencv2/legacy/legacy.hpp
+++ b/modules/legacy/include/opencv2/legacy/legacy.hpp
@@ -2840,6 +2840,110 @@ bool CalonderDescriptorExtractor<T>::empty() const
     return classifier_.trees_.empty();
 }
     
+    
+////////////////////// Distance & Brute Force Matcher //////////////////////////
+
+template<typename T>
+struct CV_EXPORTS Accumulator
+{
+    typedef T Type;
+};
+
+template<> struct Accumulator<unsigned char>  { typedef float Type; };
+template<> struct Accumulator<unsigned short> { typedef float Type; };
+template<> struct Accumulator<char>   { typedef float Type; };
+template<> struct Accumulator<short>  { typedef float Type; };
+
+/*
+ * Squared Euclidean distance functor
+ */
+template<class T>
+struct CV_EXPORTS SL2
+{
+    enum { normType = NORM_L2SQR };
+    typedef T ValueType;
+    typedef typename Accumulator<T>::Type ResultType;
+    
+    ResultType operator()( const T* a, const T* b, int size ) const
+    {
+        return normL2Sqr<ValueType, ResultType>(a, b, size);
+    }
+};
+
+/*
+ * Euclidean distance functor
+ */
+template<class T>
+struct CV_EXPORTS L2
+{
+    enum { normType = NORM_L2 };
+    typedef T ValueType;
+    typedef typename Accumulator<T>::Type ResultType;
+    
+    ResultType operator()( const T* a, const T* b, int size ) const
+    {
+        return (ResultType)sqrt((double)normL2Sqr<ValueType, ResultType>(a, b, size));
+    }
+};
+
+/*
+ * Manhattan distance (city block distance) functor
+ */
+template<class T>
+struct CV_EXPORTS L1
+{
+    enum { normType = NORM_L1 };
+    typedef T ValueType;
+    typedef typename Accumulator<T>::Type ResultType;
+    
+    ResultType operator()( const T* a, const T* b, int size ) const
+    {
+        return normL1<ValueType, ResultType>(a, b, size);
+    }
+};
+
+/*
+ * Hamming distance functor - counts the bit differences between two strings - useful for the Brief descriptor
+ * bit count of A exclusive XOR'ed with B
+ */
+struct CV_EXPORTS Hamming
+{
+    enum { normType = NORM_HAMMING };
+    typedef unsigned char ValueType;
+    typedef int ResultType;
+    
+    /** this will count the bits in a ^ b
+     */
+    ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
+    {
+        return normHamming(a, b, size);
+    }
+};
+
+typedef Hamming HammingLUT;
+
+template<int cellsize> struct CV_EXPORTS HammingMultilevel
+{
+    enum { normType = NORM_HAMMING + (cellsize>1) };
+    typedef unsigned char ValueType;
+    typedef int ResultType;
+    
+    ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
+    {
+        return normHamming(a, b, size, cellsize);
+    }
+};
+    
+    
+template<class Distance>
+class CV_EXPORTS BruteForceMatcher : public BFMatcher
+{
+public:
+    BruteForceMatcher( Distance d = Distance() ) : BFMatcher(Distance::normType, false) {}
+    virtual ~BruteForceMatcher() {}
+};
+    
+    
 /****************************************************************************************\
 *                                Planar Object Detection                                 *
 \****************************************************************************************/
diff --git a/modules/legacy/test/test_bruteforcematcher.cpp b/modules/legacy/test/test_bruteforcematcher.cpp
new file mode 100644
index 0000000000..b9b2502008
--- /dev/null
+++ b/modules/legacy/test/test_bruteforcematcher.cpp
@@ -0,0 +1,115 @@
+#include "test_precomp.hpp"
+
+using namespace cv;
+
+struct CV_EXPORTS L2Fake : public L2<float>
+{
+    enum { normType = NORM_L2 };
+};
+
+class CV_BruteForceMatcherTest : public cvtest::BaseTest
+{
+public:
+    CV_BruteForceMatcherTest() {}
+protected:
+    void run( int )
+    {
+        const int dimensions = 64;
+        const int descriptorsNumber = 5000;
+
+        Mat train = Mat( descriptorsNumber, dimensions, CV_32FC1);
+        Mat query = Mat( descriptorsNumber, dimensions, CV_32FC1);
+
+        Mat permutation( 1, descriptorsNumber, CV_32SC1 );
+        for( int i=0;i<descriptorsNumber;i++ )
+            permutation.at<int>( 0, i ) = i;
+
+        //RNG rng = RNG( cvGetTickCount() );
+        RNG rng;
+        randShuffle( permutation, 1, &rng );
+
+        float boundary =  500.f;
+        for( int row=0;row<descriptorsNumber;row++ )
+        {
+            for( int col=0;col<dimensions;col++ )
+            {
+                int bit = rng( 2 );
+                train.at<float>( permutation.at<int>( 0, row ), col ) = bit*boundary + rng.uniform( 0.f, boundary );
+                query.at<float>( row, col ) = bit*boundary + rng.uniform( 0.f, boundary );
+            }
+        }
+
+        vector<DMatch> specMatches, genericMatches;
+        BruteForceMatcher<L2<float> > specMatcher;
+        BruteForceMatcher<L2Fake > genericMatcher;
+
+        int64 time0 = cvGetTickCount();
+        specMatcher.match( query, train, specMatches );
+        int64 time1 = cvGetTickCount();
+        genericMatcher.match( query, train, genericMatches );
+        int64 time2 = cvGetTickCount();
+
+        float specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
+        ts->printf( cvtest::TS::LOG, "Matching by matrix multiplication time s: %f, us per pair: %f\n",
+                   specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
+
+        float genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
+        ts->printf( cvtest::TS::LOG, "Matching without matrix multiplication time s: %f, us per pair: %f\n",
+                   genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
+
+        if( (int)specMatches.size() != descriptorsNumber || (int)genericMatches.size() != descriptorsNumber )
+            ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
+        for( int i=0;i<descriptorsNumber;i++ )
+        {
+            float epsilon = 0.01f;
+            bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon &&
+                           specMatches[i].queryIdx == genericMatches[i].queryIdx &&
+                           specMatches[i].trainIdx == genericMatches[i].trainIdx;
+            if( !isEquiv || specMatches[i].trainIdx != permutation.at<int>( 0, i ) )
+            {
+                ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
+                break;
+            }
+        }
+
+
+        //Test mask
+        Mat mask( query.rows, train.rows, CV_8UC1 );
+        rng.fill( mask, RNG::UNIFORM, 0, 2 );
+
+
+        time0 = cvGetTickCount();
+        specMatcher.match( query, train, specMatches, mask );
+        time1 = cvGetTickCount();
+        genericMatcher.match( query, train, genericMatches, mask );
+        time2 = cvGetTickCount();
+
+        specMatcherTime = float(time1 - time0)/(float)cvGetTickFrequency();
+        ts->printf( cvtest::TS::LOG, "Matching by matrix multiplication time with mask s: %f, us per pair: %f\n",
+                   specMatcherTime*1e-6, specMatcherTime/( descriptorsNumber*descriptorsNumber ) );
+
+        genericMatcherTime = float(time2 - time1)/(float)cvGetTickFrequency();
+        ts->printf( cvtest::TS::LOG, "Matching without matrix multiplication time with mask s: %f, us per pair: %f\n",
+                   genericMatcherTime*1e-6, genericMatcherTime/( descriptorsNumber*descriptorsNumber ) );
+
+        if( specMatches.size() != genericMatches.size() )
+            ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
+
+        for( size_t i=0;i<specMatches.size();i++ )
+        {
+            //float epsilon = 1e-2;
+            float epsilon = 10000000;
+            bool isEquiv = fabs( specMatches[i].distance - genericMatches[i].distance ) < epsilon &&
+                           specMatches[i].queryIdx == genericMatches[i].queryIdx &&
+                           specMatches[i].trainIdx == genericMatches[i].trainIdx;
+            if( !isEquiv )
+            {
+                ts->set_failed_test_info( cvtest::TS::FAIL_MISMATCH );
+                break;
+            }
+        }
+    }
+};
+
+TEST(Legacy_BruteForceMatcher, accuracy) { CV_BruteForceMatcherTest test; test.safe_run(); }
+
diff --git a/modules/legacy/test/test_em.cpp b/modules/legacy/test/test_em.cpp
index 26be3feffe..823561ac2b 100644
--- a/modules/legacy/test/test_em.cpp
+++ b/modules/legacy/test/test_em.cpp
@@ -444,5 +444,5 @@ protected:
     }
 };
 
-TEST(ML_CvEM, accuracy) { CV_CvEMTest test; test.safe_run(); }
-TEST(ML_CvEM, save_load) { CV_CvEMTest_SaveLoad test; test.safe_run(); }
+TEST(Legacy_CvEM, accuracy) { CV_CvEMTest test; test.safe_run(); }
+TEST(Legacy_CvEM, save_load) { CV_CvEMTest_SaveLoad test; test.safe_run(); }
diff --git a/modules/legacy/test/test_nearestneighbors.cpp b/modules/legacy/test/test_nearestneighbors.cpp
index b3e4735980..df5fc5fc30 100644
--- a/modules/legacy/test/test_nearestneighbors.cpp
+++ b/modules/legacy/test/test_nearestneighbors.cpp
@@ -259,6 +259,6 @@ int CV_KDTreeTest_C::checkFindBoxed()
 }
 
 
-TEST(Features2d_LSH, regression) { CV_LSHTest test; test.safe_run(); }
-TEST(Features2d_SpillTree, regression) { CV_SpillTreeTest_C test; test.safe_run(); }
-TEST(Features2d_KDTree_C, regression) { CV_KDTreeTest_C test; test.safe_run(); }
+TEST(Legacy_LSH, regression) { CV_LSHTest test; test.safe_run(); }
+TEST(Legacy_SpillTree, regression) { CV_SpillTreeTest_C test; test.safe_run(); }
+TEST(Legacy_KDTree_C, regression) { CV_KDTreeTest_C test; test.safe_run(); }
diff --git a/modules/legacy/test/test_optflow.cpp b/modules/legacy/test/test_optflow.cpp
index e14e8554a7..71aea3541c 100644
--- a/modules/legacy/test/test_optflow.cpp
+++ b/modules/legacy/test/test_optflow.cpp
@@ -351,6 +351,6 @@ void CV_OptFlowTest::run( int /* start_from */)
 }
 
 
-TEST(Video_OpticalFlow, accuracy) { CV_OptFlowTest test; test.safe_run(); }
+TEST(Legacy_OpticalFlow, accuracy) { CV_OptFlowTest test; test.safe_run(); }
 
 
diff --git a/modules/legacy/test/test_pyrsegmentation.cpp b/modules/legacy/test/test_pyrsegmentation.cpp
index 89fe46a6cb..674265a7cf 100644
--- a/modules/legacy/test/test_pyrsegmentation.cpp
+++ b/modules/legacy/test/test_pyrsegmentation.cpp
@@ -199,6 +199,6 @@ _exit_:
         ts->set_failed_test_info( code );
 }
 
-TEST(Imgproc_PyrSegmentation, regression) { CV_PyrSegmentationTest test; test.safe_run(); }
+TEST(Legacy_PyrSegmentation, regression) { CV_PyrSegmentationTest test; test.safe_run(); }
 
 /* End of file. */
diff --git a/modules/legacy/test/test_stereomatching.cpp b/modules/legacy/test/test_stereomatching.cpp
index 21834b0af5..c3d37d551b 100644
--- a/modules/legacy/test/test_stereomatching.cpp
+++ b/modules/legacy/test/test_stereomatching.cpp
@@ -719,4 +719,4 @@ protected:
 };
 
 
-TEST(Calib3d_StereoGC, regression) { CV_StereoGCTest test; test.safe_run(); }
+TEST(Legacy_StereoGC, regression) { CV_StereoGCTest test; test.safe_run(); }
diff --git a/modules/legacy/test/test_subdivisions.cpp b/modules/legacy/test/test_subdivisions.cpp
index 65e2112a75..924cc67101 100644
--- a/modules/legacy/test/test_subdivisions.cpp
+++ b/modules/legacy/test/test_subdivisions.cpp
@@ -335,7 +335,7 @@ _exit_:
     return code;
 }
 
-TEST(Imgproc_Subdiv, correctness) { CV_SubdivTest test; test.safe_run(); }
+TEST(Legacy_Subdiv, correctness) { CV_SubdivTest test; test.safe_run(); }
 
 /* End of file. */