From 5f3ee657cee484619e8c7fb8577e4328b35b562b Mon Sep 17 00:00:00 2001 From: Dmitriy Anisimov Date: Sun, 31 Aug 2014 21:39:47 +0400 Subject: [PATCH] removed kdtree declaration from interface --- .../features2d/test/test_nearestneighbors.cpp | 86 ---------------- modules/ml/include/opencv2/ml.hpp | 83 ---------------- modules/ml/src/kdtree.cpp | 1 + modules/ml/src/kdtree.hpp | 97 +++++++++++++++++++ modules/ml/src/knearest.cpp | 1 + modules/ml/test/test_emknearestkmeans.cpp | 5 + 6 files changed, 104 insertions(+), 169 deletions(-) create mode 100644 modules/ml/src/kdtree.hpp diff --git a/modules/features2d/test/test_nearestneighbors.cpp b/modules/features2d/test/test_nearestneighbors.cpp index 8dd333ce84..df56025202 100644 --- a/modules/features2d/test/test_nearestneighbors.cpp +++ b/modules/features2d/test/test_nearestneighbors.cpp @@ -157,91 +157,6 @@ void NearestNeighborTest::run( int /*start_from*/ ) { ts->set_failed_test_info( code ); } -//-------------------------------------------------------------------------------- -class CV_KDTreeTest_CPP : public NearestNeighborTest -{ -public: - CV_KDTreeTest_CPP() {} -protected: - virtual void createModel( const Mat& data ); - virtual int checkGetPoins( const Mat& data ); - virtual int findNeighbors( Mat& points, Mat& neighbors ); - virtual int checkFindBoxed(); - virtual void releaseModel(); - ml::KDTree* tr; -}; - - -void CV_KDTreeTest_CPP::createModel( const Mat& data ) -{ - tr = new ml::KDTree( data, false ); -} - -int CV_KDTreeTest_CPP::checkGetPoins( const Mat& data ) -{ - Mat res1( data.size(), data.type() ), - res3( data.size(), data.type() ); - Mat idxs( 1, data.rows, CV_32SC1 ); - for( int pi = 0; pi < data.rows; pi++ ) - { - idxs.at(0, pi) = pi; - // 1st way - const float* point = tr->getPoint(pi); - for( int di = 0; di < data.cols; di++ ) - res1.at(pi, di) = point[di]; - } - - // 3d way - tr->getPoints( idxs, res3 ); - - if( cvtest::norm( res1, data, NORM_L1) != 0 || - cvtest::norm( res3, data, NORM_L1) != 0) - return cvtest::TS::FAIL_BAD_ACCURACY; - return cvtest::TS::OK; -} - -int CV_KDTreeTest_CPP::checkFindBoxed() -{ - vector min( dims, static_cast(minValue)), max(dims, static_cast(maxValue)); - vector indices; - tr->findOrthoRange( min, max, indices ); - // TODO check indices - if( (int)indices.size() != featuresCount) - return cvtest::TS::FAIL_BAD_ACCURACY; - return cvtest::TS::OK; -} - -int CV_KDTreeTest_CPP::findNeighbors( Mat& points, Mat& neighbors ) -{ - const int emax = 20; - Mat neighbors2( neighbors.size(), CV_32SC1 ); - int j; - for( int pi = 0; pi < points.rows; pi++ ) - { - // 1st way - Mat nrow = neighbors.row(pi); - tr->findNearest( points.row(pi), neighbors.cols, emax, nrow ); - - // 2nd way - vector neighborsIdx2( neighbors2.cols, 0 ); - tr->findNearest( points.row(pi), neighbors2.cols, emax, neighborsIdx2 ); - vector::const_iterator it2 = neighborsIdx2.begin(); - for( j = 0; it2 != neighborsIdx2.end(); ++it2, j++ ) - neighbors2.at(pi,j) = *it2; - } - - // compare results - if( cvtest::norm( neighbors, neighbors2, NORM_L1 ) != 0 ) - return cvtest::TS::FAIL_BAD_ACCURACY; - - return cvtest::TS::OK; -} - -void CV_KDTreeTest_CPP::releaseModel() -{ - delete tr; -} - //-------------------------------------------------------------------------------- class CV_FlannTest : public NearestNeighborTest { @@ -403,7 +318,6 @@ void CV_FlannSavedIndexTest::createModel(const cv::Mat &data) remove( filename.c_str() ); } -TEST(Features2d_KDTree_CPP, regression) { CV_KDTreeTest_CPP test; test.safe_run(); } TEST(Features2d_FLANN_Linear, regression) { CV_FlannLinearIndexTest test; test.safe_run(); } TEST(Features2d_FLANN_KMeans, regression) { CV_FlannKMeansIndexTest test; test.safe_run(); } TEST(Features2d_FLANN_KDTree, regression) { CV_FlannKDTreeIndexTest test; test.safe_run(); } diff --git a/modules/ml/include/opencv2/ml.hpp b/modules/ml/include/opencv2/ml.hpp index ebd11c7608..0a8f01dd03 100644 --- a/modules/ml/include/opencv2/ml.hpp +++ b/modules/ml/include/opencv2/ml.hpp @@ -571,89 +571,6 @@ public: static Ptr create(const Params& params=Params()); }; -/*! - Fast Nearest Neighbor Search Class. - - The class implements D. Lowe BBF (Best-Bin-First) algorithm for the last - approximate (or accurate) nearest neighbor search in multi-dimensional spaces. - - First, a set of vectors is passed to KDTree::KDTree() constructor - or KDTree::build() method, where it is reordered. - - Then arbitrary vectors can be passed to KDTree::findNearest() methods, which - find the K nearest neighbors among the vectors from the initial set. - The user can balance between the speed and accuracy of the search by varying Emax - parameter, which is the number of leaves that the algorithm checks. - The larger parameter values yield more accurate results at the expense of lower processing speed. - - \code - KDTree T(points, false); - const int K = 3, Emax = INT_MAX; - int idx[K]; - float dist[K]; - T.findNearest(query_vec, K, Emax, idx, 0, dist); - CV_Assert(dist[0] <= dist[1] && dist[1] <= dist[2]); - \endcode -*/ -class CV_EXPORTS_W KDTree -{ -public: - /*! - The node of the search tree. - */ - struct Node - { - Node() : idx(-1), left(-1), right(-1), boundary(0.f) {} - Node(int _idx, int _left, int _right, float _boundary) - : idx(_idx), left(_left), right(_right), boundary(_boundary) {} - - //! split dimension; >=0 for nodes (dim), < 0 for leaves (index of the point) - int idx; - //! node indices of the left and the right branches - int left, right; - //! go to the left if query_vec[node.idx]<=node.boundary, otherwise go to the right - float boundary; - }; - - //! the default constructor - CV_WRAP KDTree(); - //! the full constructor that builds the search tree - CV_WRAP KDTree(InputArray points, bool copyAndReorderPoints = false); - //! the full constructor that builds the search tree - CV_WRAP KDTree(InputArray points, InputArray _labels, - bool copyAndReorderPoints = false); - //! builds the search tree - CV_WRAP void build(InputArray points, bool copyAndReorderPoints = false); - //! builds the search tree - CV_WRAP void build(InputArray points, InputArray labels, - bool copyAndReorderPoints = false); - //! finds the K nearest neighbors of "vec" while looking at Emax (at most) leaves - CV_WRAP int findNearest(InputArray vec, int K, int Emax, - OutputArray neighborsIdx, - OutputArray neighbors = noArray(), - OutputArray dist = noArray(), - OutputArray labels = noArray()) const; - //! finds all the points from the initial set that belong to the specified box - CV_WRAP void findOrthoRange(InputArray minBounds, - InputArray maxBounds, - OutputArray neighborsIdx, - OutputArray neighbors = noArray(), - OutputArray labels = noArray()) const; - //! returns vectors with the specified indices - CV_WRAP void getPoints(InputArray idx, OutputArray pts, - OutputArray labels = noArray()) const; - //! return a vector with the specified index - const float* getPoint(int ptidx, int* label = 0) const; - //! returns the search space dimensionality - CV_WRAP int dims() const; - - std::vector nodes; //!< all the tree nodes - CV_PROP Mat points; //!< all the points. It can be a reordered copy of the input vector set or the original vector set. - CV_PROP std::vector labels; //!< the parallel array of labels. - CV_PROP int maxDepth; //!< maximum depth of the search tree. Do not modify it - CV_PROP_RW int normType; //!< type of the distance (cv::NORM_L1 or cv::NORM_L2) used for search. Initially set to cv::NORM_L2, but you can modify it -}; - /****************************************************************************************\ * Auxilary functions declarations * \****************************************************************************************/ diff --git a/modules/ml/src/kdtree.cpp b/modules/ml/src/kdtree.cpp index f37d910faa..9ab61e4d6b 100644 --- a/modules/ml/src/kdtree.cpp +++ b/modules/ml/src/kdtree.cpp @@ -43,6 +43,7 @@ //M*/ #include "precomp.hpp" +#include "kdtree.hpp" namespace cv { diff --git a/modules/ml/src/kdtree.hpp b/modules/ml/src/kdtree.hpp new file mode 100644 index 0000000000..2975c7c75f --- /dev/null +++ b/modules/ml/src/kdtree.hpp @@ -0,0 +1,97 @@ +#ifndef KDTREE_H +#define KDTREE_H + +#include "precomp.hpp" + +namespace cv +{ +namespace ml +{ + +/*! + Fast Nearest Neighbor Search Class. + + The class implements D. Lowe BBF (Best-Bin-First) algorithm for the last + approximate (or accurate) nearest neighbor search in multi-dimensional spaces. + + First, a set of vectors is passed to KDTree::KDTree() constructor + or KDTree::build() method, where it is reordered. + + Then arbitrary vectors can be passed to KDTree::findNearest() methods, which + find the K nearest neighbors among the vectors from the initial set. + The user can balance between the speed and accuracy of the search by varying Emax + parameter, which is the number of leaves that the algorithm checks. + The larger parameter values yield more accurate results at the expense of lower processing speed. + + \code + KDTree T(points, false); + const int K = 3, Emax = INT_MAX; + int idx[K]; + float dist[K]; + T.findNearest(query_vec, K, Emax, idx, 0, dist); + CV_Assert(dist[0] <= dist[1] && dist[1] <= dist[2]); + \endcode +*/ +class CV_EXPORTS_W KDTree +{ +public: + /*! + The node of the search tree. + */ + struct Node + { + Node() : idx(-1), left(-1), right(-1), boundary(0.f) {} + Node(int _idx, int _left, int _right, float _boundary) + : idx(_idx), left(_left), right(_right), boundary(_boundary) {} + + //! split dimension; >=0 for nodes (dim), < 0 for leaves (index of the point) + int idx; + //! node indices of the left and the right branches + int left, right; + //! go to the left if query_vec[node.idx]<=node.boundary, otherwise go to the right + float boundary; + }; + + //! the default constructor + CV_WRAP KDTree(); + //! the full constructor that builds the search tree + CV_WRAP KDTree(InputArray points, bool copyAndReorderPoints = false); + //! the full constructor that builds the search tree + CV_WRAP KDTree(InputArray points, InputArray _labels, + bool copyAndReorderPoints = false); + //! builds the search tree + CV_WRAP void build(InputArray points, bool copyAndReorderPoints = false); + //! builds the search tree + CV_WRAP void build(InputArray points, InputArray labels, + bool copyAndReorderPoints = false); + //! finds the K nearest neighbors of "vec" while looking at Emax (at most) leaves + CV_WRAP int findNearest(InputArray vec, int K, int Emax, + OutputArray neighborsIdx, + OutputArray neighbors = noArray(), + OutputArray dist = noArray(), + OutputArray labels = noArray()) const; + //! finds all the points from the initial set that belong to the specified box + CV_WRAP void findOrthoRange(InputArray minBounds, + InputArray maxBounds, + OutputArray neighborsIdx, + OutputArray neighbors = noArray(), + OutputArray labels = noArray()) const; + //! returns vectors with the specified indices + CV_WRAP void getPoints(InputArray idx, OutputArray pts, + OutputArray labels = noArray()) const; + //! return a vector with the specified index + const float* getPoint(int ptidx, int* label = 0) const; + //! returns the search space dimensionality + CV_WRAP int dims() const; + + std::vector nodes; //!< all the tree nodes + CV_PROP Mat points; //!< all the points. It can be a reordered copy of the input vector set or the original vector set. + CV_PROP std::vector labels; //!< the parallel array of labels. + CV_PROP int maxDepth; //!< maximum depth of the search tree. Do not modify it + CV_PROP_RW int normType; //!< type of the distance (cv::NORM_L1 or cv::NORM_L2) used for search. Initially set to cv::NORM_L2, but you can modify it +}; + +} +} + +#endif diff --git a/modules/ml/src/knearest.cpp b/modules/ml/src/knearest.cpp index 6d2bebff25..14c799be5b 100644 --- a/modules/ml/src/knearest.cpp +++ b/modules/ml/src/knearest.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "kdtree.hpp" /****************************************************************************************\ * K-Nearest Neighbors Classifier * diff --git a/modules/ml/test/test_emknearestkmeans.cpp b/modules/ml/test/test_emknearestkmeans.cpp index b40463430b..8e08170c36 100644 --- a/modules/ml/test/test_emknearestkmeans.cpp +++ b/modules/ml/test/test_emknearestkmeans.cpp @@ -338,6 +338,11 @@ void CV_KNearestTest::run( int /*start_from*/ ) ts->printf( cvtest::TS::LOG, "Bad output labels.\n" ); code = cvtest::TS::FAIL_INVALID_OUTPUT; } + else if( err > 0.01f ) + { + ts->printf( cvtest::TS::LOG, "Bad accuracy (%f) on test data.\n", err ); + code = cvtest::TS::FAIL_BAD_ACCURACY; + } ts->set_failed_test_info( code ); }