all the tests now pass except for MSER
This commit is contained in:
		| @@ -874,6 +874,9 @@ public: | ||||
|     virtual ~Algorithm(); | ||||
|     String name() const; | ||||
|  | ||||
|     virtual void set(int, double); | ||||
|     virtual double get(int) const; | ||||
|  | ||||
|     template<typename _Tp> typename ParamType<_Tp>::member_type get(const String& name) const; | ||||
|     template<typename _Tp> typename ParamType<_Tp>::member_type get(const char* name) const; | ||||
|  | ||||
|   | ||||
| @@ -179,6 +179,9 @@ String Algorithm::name() const | ||||
|     return info()->name(); | ||||
| } | ||||
|  | ||||
| void Algorithm::set(int, double) {} | ||||
| double Algorithm::get(int) const { return 0.; } | ||||
|  | ||||
| void Algorithm::set(const String& parameter, int value) | ||||
| { | ||||
|     info()->set(this, parameter.c_str(), ParamType<int>::type, &value); | ||||
|   | ||||
| @@ -213,9 +213,10 @@ CV_EXPORTS void FAST( InputArray image, CV_OUT std::vector<KeyPoint>& keypoints, | ||||
| class CV_EXPORTS_W FastFeatureDetector : public Feature2D | ||||
| { | ||||
| public: | ||||
|     enum Type | ||||
|     enum | ||||
|     { | ||||
|         TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2 | ||||
|         TYPE_5_8 = 0, TYPE_7_12 = 1, TYPE_9_16 = 2, | ||||
|         THRESHOLD = 10000, NONMAX_SUPPRESSION=10001, FAST_N=10002, | ||||
|     }; | ||||
|  | ||||
|     CV_WRAP static Ptr<FastFeatureDetector> create( int threshold=10, | ||||
|   | ||||
| @@ -32,11 +32,8 @@ OCL_PERF_TEST_P(FASTFixture, FastDetect, testing::Combine( | ||||
|     mframe.copyTo(frame); | ||||
|     declare.in(frame); | ||||
|  | ||||
|     Ptr<FeatureDetector> fd = Algorithm::create<FeatureDetector>("Feature2D.FAST"); | ||||
|     Ptr<FeatureDetector> fd = FastFeatureDetector::create(20, true, type); | ||||
|     ASSERT_FALSE( fd.empty() ); | ||||
|     fd->set("threshold", 20); | ||||
|     fd->set("nonmaxSuppression", true); | ||||
|     fd->set("type", type); | ||||
|     vector<KeyPoint> points; | ||||
|  | ||||
|     OCL_TEST_CYCLE() fd->detect(frame, points); | ||||
|   | ||||
| @@ -30,11 +30,8 @@ PERF_TEST_P(fast, detect, testing::Combine( | ||||
|  | ||||
|     declare.in(frame); | ||||
|  | ||||
|     Ptr<FeatureDetector> fd = Algorithm::create<FeatureDetector>("Feature2D.FAST"); | ||||
|     Ptr<FeatureDetector> fd = FastFeatureDetector::create(20, true, type); | ||||
|     ASSERT_FALSE( fd.empty() ); | ||||
|     fd->set("threshold", 20); | ||||
|     fd->set("nonmaxSuppression", true); | ||||
|     fd->set("type", type); | ||||
|     vector<KeyPoint> points; | ||||
|  | ||||
|     TEST_CYCLE() fd->detect(frame, points); | ||||
|   | ||||
| @@ -2099,7 +2099,7 @@ BriskLayer::BriskLayer(const BriskLayer& layer, int mode) | ||||
| void | ||||
| BriskLayer::getAgastPoints(int threshold, std::vector<KeyPoint>& keypoints) | ||||
| { | ||||
|   fast_9_16_ = FastFeatureDetector::create(threshold); | ||||
|   fast_9_16_->set(FastFeatureDetector::THRESHOLD, threshold); | ||||
|   fast_9_16_->detect(img_, keypoints); | ||||
|  | ||||
|   // also write scores | ||||
|   | ||||
| @@ -383,6 +383,30 @@ public: | ||||
|         KeyPointsFilter::runByPixelsMask( keypoints, mask ); | ||||
|     } | ||||
|  | ||||
|     void set(int prop, double value) | ||||
|     { | ||||
|         if(prop == THRESHOLD) | ||||
|             threshold = cvRound(value); | ||||
|         else if(prop == NONMAX_SUPPRESSION) | ||||
|             nonmaxSuppression = value != 0; | ||||
|         else if(prop == FAST_N) | ||||
|             type = cvRound(value); | ||||
|         else | ||||
|             CV_Error(Error::StsBadArg, ""); | ||||
|     } | ||||
|  | ||||
|     double get(int prop) const | ||||
|     { | ||||
|         if(prop == THRESHOLD) | ||||
|             return threshold; | ||||
|         if(prop == NONMAX_SUPPRESSION) | ||||
|             return nonmaxSuppression; | ||||
|         if(prop == FAST_N) | ||||
|             return type; | ||||
|         CV_Error(Error::StsBadArg, ""); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     int threshold; | ||||
|     bool nonmaxSuppression; | ||||
|     int type; | ||||
|   | ||||
| @@ -800,9 +800,12 @@ extractMSER_8uC3( const Mat& src, Mat& labels, | ||||
|     double emean = 0; | ||||
|     Mat dx( src.rows, src.cols-1, CV_32FC1 ); | ||||
|     Mat dy( src.rows, src.cols, CV_32FC1 ); | ||||
|  | ||||
|     Ne = preprocessMSER_8UC3( map, edge, emean, src, dx, dy, Ne, params.edgeBlurSize ); | ||||
|     emean = emean / (double)Ne; | ||||
|  | ||||
|     std::sort(edge, edge + Ne, LessThanEdge()); | ||||
|  | ||||
|     MSCREdge* edge_ub = edge+Ne; | ||||
|     MSCREdge* edgeptr = edge; | ||||
|     TempMSCR* mscrptr = mscr; | ||||
|   | ||||
| @@ -106,8 +106,6 @@ public: | ||||
|  | ||||
|     ~CV_DescriptorExtractorTest() | ||||
|     { | ||||
|         if(!detector.empty()) | ||||
|             detector.release(); | ||||
|     } | ||||
| protected: | ||||
|     virtual void createDescriptorExtractor() {} | ||||
| @@ -333,7 +331,7 @@ TEST( Features2d_DescriptorExtractor_KAZE, regression ) | ||||
| { | ||||
|     CV_DescriptorExtractorTest< L2<float> > test( "descriptor-kaze",  0.03f, | ||||
|                                                  KAZE::create(), | ||||
|                                                  L2<float>() ); | ||||
|                                                  L2<float>(), KAZE::create() ); | ||||
|     test.safe_run(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -41,6 +41,7 @@ | ||||
|  | ||||
| #include "test_precomp.hpp" | ||||
| #include "opencv2/highgui.hpp" | ||||
| #include "opencv2/core/core_c.h" | ||||
|  | ||||
| using namespace std; | ||||
| using namespace cv; | ||||
| @@ -48,6 +49,683 @@ using namespace cv; | ||||
| const string FEATURES2D_DIR = "features2d"; | ||||
| const string IMAGE_FILENAME = "tsukuba.png"; | ||||
|  | ||||
| const int TABLE_SIZE = 400; | ||||
|  | ||||
| static const float chitab3[]= | ||||
| { | ||||
|     0.f,  0.0150057f,  0.0239478f,  0.0315227f, | ||||
|     0.0383427f,  0.0446605f,  0.0506115f,  0.0562786f, | ||||
|     0.0617174f,  0.0669672f,  0.0720573f,  0.0770099f, | ||||
|     0.081843f,  0.0865705f,  0.0912043f,  0.0957541f, | ||||
|     0.100228f,  0.104633f,  0.108976f,  0.113261f, | ||||
|     0.117493f,  0.121676f,  0.125814f,  0.12991f, | ||||
|     0.133967f,  0.137987f,  0.141974f,  0.145929f, | ||||
|     0.149853f,  0.15375f,  0.15762f,  0.161466f, | ||||
|     0.165287f,  0.169087f,  0.172866f,  0.176625f, | ||||
|     0.180365f,  0.184088f,  0.187794f,  0.191483f, | ||||
|     0.195158f,  0.198819f,  0.202466f,  0.2061f, | ||||
|     0.209722f,  0.213332f,  0.216932f,  0.220521f, | ||||
|     0.2241f,  0.22767f,  0.231231f,  0.234783f, | ||||
|     0.238328f,  0.241865f,  0.245395f,  0.248918f, | ||||
|     0.252435f,  0.255947f,  0.259452f,  0.262952f, | ||||
|     0.266448f,  0.269939f,  0.273425f,  0.276908f, | ||||
|     0.280386f,  0.283862f,  0.287334f,  0.290803f, | ||||
|     0.29427f,  0.297734f,  0.301197f,  0.304657f, | ||||
|     0.308115f,  0.311573f,  0.315028f,  0.318483f, | ||||
|     0.321937f,  0.32539f,  0.328843f,  0.332296f, | ||||
|     0.335749f,  0.339201f,  0.342654f,  0.346108f, | ||||
|     0.349562f,  0.353017f,  0.356473f,  0.35993f, | ||||
|     0.363389f,  0.366849f,  0.37031f,  0.373774f, | ||||
|     0.377239f,  0.380706f,  0.384176f,  0.387648f, | ||||
|     0.391123f,  0.3946f,  0.39808f,  0.401563f, | ||||
|     0.405049f,  0.408539f,  0.412032f,  0.415528f, | ||||
|     0.419028f,  0.422531f,  0.426039f,  0.429551f, | ||||
|     0.433066f,  0.436586f,  0.440111f,  0.44364f, | ||||
|     0.447173f,  0.450712f,  0.454255f,  0.457803f, | ||||
|     0.461356f,  0.464915f,  0.468479f,  0.472049f, | ||||
|     0.475624f,  0.479205f,  0.482792f,  0.486384f, | ||||
|     0.489983f,  0.493588f,  0.4972f,  0.500818f, | ||||
|     0.504442f,  0.508073f,  0.511711f,  0.515356f, | ||||
|     0.519008f,  0.522667f,  0.526334f,  0.530008f, | ||||
|     0.533689f,  0.537378f,  0.541075f,  0.54478f, | ||||
|     0.548492f,  0.552213f,  0.555942f,  0.55968f, | ||||
|     0.563425f,  0.56718f,  0.570943f,  0.574715f, | ||||
|     0.578497f,  0.582287f,  0.586086f,  0.589895f, | ||||
|     0.593713f,  0.597541f,  0.601379f,  0.605227f, | ||||
|     0.609084f,  0.612952f,  0.61683f,  0.620718f, | ||||
|     0.624617f,  0.628526f,  0.632447f,  0.636378f, | ||||
|     0.64032f,  0.644274f,  0.648239f,  0.652215f, | ||||
|     0.656203f,  0.660203f,  0.664215f,  0.668238f, | ||||
|     0.672274f,  0.676323f,  0.680384f,  0.684457f, | ||||
|     0.688543f,  0.692643f,  0.696755f,  0.700881f, | ||||
|     0.70502f,  0.709172f,  0.713339f,  0.717519f, | ||||
|     0.721714f,  0.725922f,  0.730145f,  0.734383f, | ||||
|     0.738636f,  0.742903f,  0.747185f,  0.751483f, | ||||
|     0.755796f,  0.760125f,  0.76447f,  0.768831f, | ||||
|     0.773208f,  0.777601f,  0.782011f,  0.786438f, | ||||
|     0.790882f,  0.795343f,  0.799821f,  0.804318f, | ||||
|     0.808831f,  0.813363f,  0.817913f,  0.822482f, | ||||
|     0.827069f,  0.831676f,  0.836301f,  0.840946f, | ||||
|     0.84561f,  0.850295f,  0.854999f,  0.859724f, | ||||
|     0.864469f,  0.869235f,  0.874022f,  0.878831f, | ||||
|     0.883661f,  0.888513f,  0.893387f,  0.898284f, | ||||
|     0.903204f,  0.908146f,  0.913112f,  0.918101f, | ||||
|     0.923114f,  0.928152f,  0.933214f,  0.938301f, | ||||
|     0.943413f,  0.94855f,  0.953713f,  0.958903f, | ||||
|     0.964119f,  0.969361f,  0.974631f,  0.979929f, | ||||
|     0.985254f,  0.990608f,  0.99599f,  1.0014f, | ||||
|     1.00684f,  1.01231f,  1.01781f,  1.02335f, | ||||
|     1.02891f,  1.0345f,  1.04013f,  1.04579f, | ||||
|     1.05148f,  1.05721f,  1.06296f,  1.06876f, | ||||
|     1.07459f,  1.08045f,  1.08635f,  1.09228f, | ||||
|     1.09826f,  1.10427f,  1.11032f,  1.1164f, | ||||
|     1.12253f,  1.1287f,  1.1349f,  1.14115f, | ||||
|     1.14744f,  1.15377f,  1.16015f,  1.16656f, | ||||
|     1.17303f,  1.17954f,  1.18609f,  1.19269f, | ||||
|     1.19934f,  1.20603f,  1.21278f,  1.21958f, | ||||
|     1.22642f,  1.23332f,  1.24027f,  1.24727f, | ||||
|     1.25433f,  1.26144f,  1.26861f,  1.27584f, | ||||
|     1.28312f,  1.29047f,  1.29787f,  1.30534f, | ||||
|     1.31287f,  1.32046f,  1.32812f,  1.33585f, | ||||
|     1.34364f,  1.3515f,  1.35943f,  1.36744f, | ||||
|     1.37551f,  1.38367f,  1.39189f,  1.4002f, | ||||
|     1.40859f,  1.41705f,  1.42561f,  1.43424f, | ||||
|     1.44296f,  1.45177f,  1.46068f,  1.46967f, | ||||
|     1.47876f,  1.48795f,  1.49723f,  1.50662f, | ||||
|     1.51611f,  1.52571f,  1.53541f,  1.54523f, | ||||
|     1.55517f,  1.56522f,  1.57539f,  1.58568f, | ||||
|     1.59611f,  1.60666f,  1.61735f,  1.62817f, | ||||
|     1.63914f,  1.65025f,  1.66152f,  1.67293f, | ||||
|     1.68451f,  1.69625f,  1.70815f,  1.72023f, | ||||
|     1.73249f,  1.74494f,  1.75757f,  1.77041f, | ||||
|     1.78344f,  1.79669f,  1.81016f,  1.82385f, | ||||
|     1.83777f,  1.85194f,  1.86635f,  1.88103f, | ||||
|     1.89598f,  1.91121f,  1.92674f,  1.94257f, | ||||
|     1.95871f,  1.97519f,  1.99201f,  2.0092f, | ||||
|     2.02676f,  2.04471f,  2.06309f,  2.08189f, | ||||
|     2.10115f,  2.12089f,  2.14114f,  2.16192f, | ||||
|     2.18326f,  2.2052f,  2.22777f,  2.25101f, | ||||
|     2.27496f,  2.29966f,  2.32518f,  2.35156f, | ||||
|     2.37886f,  2.40717f,  2.43655f,  2.46709f, | ||||
|     2.49889f,  2.53206f,  2.56673f,  2.60305f, | ||||
|     2.64117f,  2.6813f,  2.72367f,  2.76854f, | ||||
|     2.81623f,  2.86714f,  2.92173f,  2.98059f, | ||||
|     3.04446f,  3.1143f,  3.19135f,  3.27731f, | ||||
|     3.37455f,  3.48653f,  3.61862f,  3.77982f, | ||||
|     3.98692f,  4.2776f,  4.77167f,  133.333f | ||||
| }; | ||||
|  | ||||
| struct MSCRNode; | ||||
|  | ||||
| struct TempMSCR | ||||
| { | ||||
|     MSCRNode* head; | ||||
|     MSCRNode* tail; | ||||
|     double m; // the margin used to prune area later | ||||
|     int size; | ||||
| }; | ||||
|  | ||||
| struct MSCRNode | ||||
| { | ||||
|     MSCRNode* shortcut; | ||||
|     // to make the finding of root less painful | ||||
|     MSCRNode* prev; | ||||
|     MSCRNode* next; | ||||
|     // a point double-linked list | ||||
|     TempMSCR* tmsr; | ||||
|     // the temporary msr (set to NULL at every re-initialise) | ||||
|     TempMSCR* gmsr; | ||||
|     // the global msr (once set, never to NULL) | ||||
|     int index; | ||||
|     // the index of the node, at this point, it should be x at the first 16-bits, and y at the last 16-bits. | ||||
|     int rank; | ||||
|     int reinit; | ||||
|     int size, sizei; | ||||
|     double dt, di; | ||||
|     double s; | ||||
| }; | ||||
|  | ||||
| struct MSCREdge | ||||
| { | ||||
|     double chi; | ||||
|     MSCRNode* left; | ||||
|     MSCRNode* right; | ||||
| }; | ||||
|  | ||||
| static double ChiSquaredDistance( uchar* x, uchar* y ) | ||||
| { | ||||
|     return (double)((x[0]-y[0])*(x[0]-y[0]))/(double)(x[0]+y[0]+1e-10)+ | ||||
|     (double)((x[1]-y[1])*(x[1]-y[1]))/(double)(x[1]+y[1]+1e-10)+ | ||||
|     (double)((x[2]-y[2])*(x[2]-y[2]))/(double)(x[2]+y[2]+1e-10); | ||||
| } | ||||
|  | ||||
| static void initMSCRNode( MSCRNode* node ) | ||||
| { | ||||
|     node->gmsr = node->tmsr = NULL; | ||||
|     node->reinit = 0xffff; | ||||
|     node->rank = 0; | ||||
|     node->sizei = node->size = 1; | ||||
|     node->prev = node->next = node->shortcut = node; | ||||
| } | ||||
|  | ||||
| // the preprocess to get the edge list with proper gaussian blur | ||||
| static int preprocessMSER_8UC3( MSCRNode* node, | ||||
|                                MSCREdge* edge, | ||||
|                                double* total, | ||||
|                                CvMat* src, | ||||
|                                CvMat* mask, | ||||
|                                CvMat* dx, | ||||
|                                CvMat* dy, | ||||
|                                int Ne, | ||||
|                                int edgeBlurSize ) | ||||
| { | ||||
|     int srccpt = src->step-src->cols*3; | ||||
|     uchar* srcptr = src->data.ptr; | ||||
|     uchar* lastptr = src->data.ptr+3; | ||||
|     double* dxptr = dx->data.db; | ||||
|     for ( int i = 0; i < src->rows; i++ ) | ||||
|     { | ||||
|         for ( int j = 0; j < src->cols-1; j++ ) | ||||
|         { | ||||
|             *dxptr = ChiSquaredDistance( srcptr, lastptr ); | ||||
|             dxptr++; | ||||
|             srcptr += 3; | ||||
|             lastptr += 3; | ||||
|         } | ||||
|         srcptr += srccpt+3; | ||||
|         lastptr += srccpt+3; | ||||
|     } | ||||
|     srcptr = src->data.ptr; | ||||
|     lastptr = src->data.ptr+src->step; | ||||
|     double* dyptr = dy->data.db; | ||||
|     for ( int i = 0; i < src->rows-1; i++ ) | ||||
|     { | ||||
|         for ( int j = 0; j < src->cols; j++ ) | ||||
|         { | ||||
|             *dyptr = ChiSquaredDistance( srcptr, lastptr ); | ||||
|             dyptr++; | ||||
|             srcptr += 3; | ||||
|             lastptr += 3; | ||||
|         } | ||||
|         srcptr += srccpt; | ||||
|         lastptr += srccpt; | ||||
|     } | ||||
|     // get dx and dy and blur it | ||||
|     if ( edgeBlurSize >= 1 ) | ||||
|     { | ||||
|         Mat _dx(dx->rows, dx->cols, dx->type, dx->data.ptr, dx->step); | ||||
|         Mat _dy(dy->rows, dy->cols, dy->type, dy->data.ptr, dy->step); | ||||
|         GaussianBlur( _dx, _dx, Size(edgeBlurSize, edgeBlurSize), 0 ); | ||||
|         GaussianBlur( _dy, _dy, Size(edgeBlurSize, edgeBlurSize), 0 ); | ||||
|     } | ||||
|     dxptr = dx->data.db; | ||||
|     dyptr = dy->data.db; | ||||
|     // assian dx, dy to proper edge list and initialize mscr node | ||||
|     // the nasty code here intended to avoid extra loops | ||||
|     if ( mask ) | ||||
|     { | ||||
|         Ne = 0; | ||||
|         int maskcpt = mask->step-mask->cols+1; | ||||
|         uchar* maskptr = mask->data.ptr; | ||||
|         MSCRNode* nodeptr = node; | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = 0; | ||||
|         *total += edge->chi = *dxptr; | ||||
|         if ( maskptr[0] && maskptr[1] ) | ||||
|         { | ||||
|             edge->left = nodeptr; | ||||
|             edge->right = nodeptr+1; | ||||
|             edge++; | ||||
|             Ne++; | ||||
|         } | ||||
|         dxptr++; | ||||
|         nodeptr++; | ||||
|         maskptr++; | ||||
|         for ( int i = 1; i < src->cols-1; i++ ) | ||||
|         { | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = i; | ||||
|             if ( maskptr[0] && maskptr[1] ) | ||||
|             { | ||||
|                 *total += edge->chi = *dxptr; | ||||
|                 edge->left = nodeptr; | ||||
|                 edge->right = nodeptr+1; | ||||
|                 edge++; | ||||
|                 Ne++; | ||||
|             } | ||||
|             dxptr++; | ||||
|             nodeptr++; | ||||
|             maskptr++; | ||||
|         } | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = src->cols-1; | ||||
|         nodeptr++; | ||||
|         maskptr += maskcpt; | ||||
|         for ( int i = 1; i < src->rows-1; i++ ) | ||||
|         { | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = i<<16; | ||||
|             if ( maskptr[0] ) | ||||
|             { | ||||
|                 if ( maskptr[-mask->step] ) | ||||
|                 { | ||||
|                     *total += edge->chi = *dyptr; | ||||
|                     edge->left = nodeptr-src->cols; | ||||
|                     edge->right = nodeptr; | ||||
|                     edge++; | ||||
|                     Ne++; | ||||
|                 } | ||||
|                 if ( maskptr[1] ) | ||||
|                 { | ||||
|                     *total += edge->chi = *dxptr; | ||||
|                     edge->left = nodeptr; | ||||
|                     edge->right = nodeptr+1; | ||||
|                     edge++; | ||||
|                     Ne++; | ||||
|                 } | ||||
|             } | ||||
|             dyptr++; | ||||
|             dxptr++; | ||||
|             nodeptr++; | ||||
|             maskptr++; | ||||
|             for ( int j = 1; j < src->cols-1; j++ ) | ||||
|             { | ||||
|                 initMSCRNode( nodeptr ); | ||||
|                 nodeptr->index = (i<<16)|j; | ||||
|                 if ( maskptr[0] ) | ||||
|                 { | ||||
|                     if ( maskptr[-mask->step] ) | ||||
|                     { | ||||
|                         *total += edge->chi = *dyptr; | ||||
|                         edge->left = nodeptr-src->cols; | ||||
|                         edge->right = nodeptr; | ||||
|                         edge++; | ||||
|                         Ne++; | ||||
|                     } | ||||
|                     if ( maskptr[1] ) | ||||
|                     { | ||||
|                         *total += edge->chi = *dxptr; | ||||
|                         edge->left = nodeptr; | ||||
|                         edge->right = nodeptr+1; | ||||
|                         edge++; | ||||
|                         Ne++; | ||||
|                     } | ||||
|                 } | ||||
|                 dyptr++; | ||||
|                 dxptr++; | ||||
|                 nodeptr++; | ||||
|                 maskptr++; | ||||
|             } | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = (i<<16)|(src->cols-1); | ||||
|             if ( maskptr[0] && maskptr[-mask->step] ) | ||||
|             { | ||||
|                 *total += edge->chi = *dyptr; | ||||
|                 edge->left = nodeptr-src->cols; | ||||
|                 edge->right = nodeptr; | ||||
|                 edge++; | ||||
|                 Ne++; | ||||
|             } | ||||
|             dyptr++; | ||||
|             nodeptr++; | ||||
|             maskptr += maskcpt; | ||||
|         } | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = (src->rows-1)<<16; | ||||
|         if ( maskptr[0] ) | ||||
|         { | ||||
|             if ( maskptr[1] ) | ||||
|             { | ||||
|                 *total += edge->chi = *dxptr; | ||||
|                 edge->left = nodeptr; | ||||
|                 edge->right = nodeptr+1; | ||||
|                 edge++; | ||||
|                 Ne++; | ||||
|             } | ||||
|             if ( maskptr[-mask->step] ) | ||||
|             { | ||||
|                 *total += edge->chi = *dyptr; | ||||
|                 edge->left = nodeptr-src->cols; | ||||
|                 edge->right = nodeptr; | ||||
|                 edge++; | ||||
|                 Ne++; | ||||
|             } | ||||
|         } | ||||
|         dxptr++; | ||||
|         dyptr++; | ||||
|         nodeptr++; | ||||
|         maskptr++; | ||||
|         for ( int i = 1; i < src->cols-1; i++ ) | ||||
|         { | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = ((src->rows-1)<<16)|i; | ||||
|             if ( maskptr[0] ) | ||||
|             { | ||||
|                 if ( maskptr[1] ) | ||||
|                 { | ||||
|                     *total += edge->chi = *dxptr; | ||||
|                     edge->left = nodeptr; | ||||
|                     edge->right = nodeptr+1; | ||||
|                     edge++; | ||||
|                     Ne++; | ||||
|                 } | ||||
|                 if ( maskptr[-mask->step] ) | ||||
|                 { | ||||
|                     *total += edge->chi = *dyptr; | ||||
|                     edge->left = nodeptr-src->cols; | ||||
|                     edge->right = nodeptr; | ||||
|                     edge++; | ||||
|                     Ne++; | ||||
|                 } | ||||
|             } | ||||
|             dxptr++; | ||||
|             dyptr++; | ||||
|             nodeptr++; | ||||
|             maskptr++; | ||||
|         } | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = ((src->rows-1)<<16)|(src->cols-1); | ||||
|         if ( maskptr[0] && maskptr[-mask->step] ) | ||||
|         { | ||||
|             *total += edge->chi = *dyptr; | ||||
|             edge->left = nodeptr-src->cols; | ||||
|             edge->right = nodeptr; | ||||
|             Ne++; | ||||
|         } | ||||
|     } else { | ||||
|         MSCRNode* nodeptr = node; | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = 0; | ||||
|         *total += edge->chi = *dxptr; | ||||
|         dxptr++; | ||||
|         edge->left = nodeptr; | ||||
|         edge->right = nodeptr+1; | ||||
|         edge++; | ||||
|         nodeptr++; | ||||
|         for ( int i = 1; i < src->cols-1; i++ ) | ||||
|         { | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = i; | ||||
|             *total += edge->chi = *dxptr; | ||||
|             dxptr++; | ||||
|             edge->left = nodeptr; | ||||
|             edge->right = nodeptr+1; | ||||
|             edge++; | ||||
|             nodeptr++; | ||||
|         } | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = src->cols-1; | ||||
|         nodeptr++; | ||||
|         for ( int i = 1; i < src->rows-1; i++ ) | ||||
|         { | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = i<<16; | ||||
|             *total += edge->chi = *dyptr; | ||||
|             dyptr++; | ||||
|             edge->left = nodeptr-src->cols; | ||||
|             edge->right = nodeptr; | ||||
|             edge++; | ||||
|             *total += edge->chi = *dxptr; | ||||
|             dxptr++; | ||||
|             edge->left = nodeptr; | ||||
|             edge->right = nodeptr+1; | ||||
|             edge++; | ||||
|             nodeptr++; | ||||
|             for ( int j = 1; j < src->cols-1; j++ ) | ||||
|             { | ||||
|                 initMSCRNode( nodeptr ); | ||||
|                 nodeptr->index = (i<<16)|j; | ||||
|                 *total += edge->chi = *dyptr; | ||||
|                 dyptr++; | ||||
|                 edge->left = nodeptr-src->cols; | ||||
|                 edge->right = nodeptr; | ||||
|                 edge++; | ||||
|                 *total += edge->chi = *dxptr; | ||||
|                 dxptr++; | ||||
|                 edge->left = nodeptr; | ||||
|                 edge->right = nodeptr+1; | ||||
|                 edge++; | ||||
|                 nodeptr++; | ||||
|             } | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = (i<<16)|(src->cols-1); | ||||
|             *total += edge->chi = *dyptr; | ||||
|             dyptr++; | ||||
|             edge->left = nodeptr-src->cols; | ||||
|             edge->right = nodeptr; | ||||
|             edge++; | ||||
|             nodeptr++; | ||||
|         } | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = (src->rows-1)<<16; | ||||
|         *total += edge->chi = *dxptr; | ||||
|         dxptr++; | ||||
|         edge->left = nodeptr; | ||||
|         edge->right = nodeptr+1; | ||||
|         edge++; | ||||
|         *total += edge->chi = *dyptr; | ||||
|         dyptr++; | ||||
|         edge->left = nodeptr-src->cols; | ||||
|         edge->right = nodeptr; | ||||
|         edge++; | ||||
|         nodeptr++; | ||||
|         for ( int i = 1; i < src->cols-1; i++ ) | ||||
|         { | ||||
|             initMSCRNode( nodeptr ); | ||||
|             nodeptr->index = ((src->rows-1)<<16)|i; | ||||
|             *total += edge->chi = *dxptr; | ||||
|             dxptr++; | ||||
|             edge->left = nodeptr; | ||||
|             edge->right = nodeptr+1; | ||||
|             edge++; | ||||
|             *total += edge->chi = *dyptr; | ||||
|             dyptr++; | ||||
|             edge->left = nodeptr-src->cols; | ||||
|             edge->right = nodeptr; | ||||
|             edge++; | ||||
|             nodeptr++; | ||||
|         } | ||||
|         initMSCRNode( nodeptr ); | ||||
|         nodeptr->index = ((src->rows-1)<<16)|(src->cols-1); | ||||
|         *total += edge->chi = *dyptr; | ||||
|         edge->left = nodeptr-src->cols; | ||||
|         edge->right = nodeptr; | ||||
|     } | ||||
|     return Ne; | ||||
| } | ||||
|  | ||||
| class LessThanEdge | ||||
| { | ||||
| public: | ||||
|     bool operator()(const MSCREdge& a, const MSCREdge& b) const { return a.chi < b.chi; } | ||||
| }; | ||||
|  | ||||
| // to find the root of one region | ||||
| static MSCRNode* findMSCR( MSCRNode* x ) | ||||
| { | ||||
|     MSCRNode* prev = x; | ||||
|     MSCRNode* next; | ||||
|     for ( ; ; ) | ||||
|     { | ||||
|         next = x->shortcut; | ||||
|         x->shortcut = prev; | ||||
|         if ( next == x ) break; | ||||
|         prev= x; | ||||
|         x = next; | ||||
|     } | ||||
|     MSCRNode* root = x; | ||||
|     for ( ; ; ) | ||||
|     { | ||||
|         prev = x->shortcut; | ||||
|         x->shortcut = root; | ||||
|         if ( prev == x ) break; | ||||
|         x = prev; | ||||
|     } | ||||
|     return root; | ||||
| } | ||||
|  | ||||
| struct MSERParams | ||||
| { | ||||
|     MSERParams( int _delta=5, int _min_area=60, int _max_area=14400, | ||||
|                       double _max_variation=0.25, double _min_diversity=.2, | ||||
|                       int _max_evolution=200, double _area_threshold=1.01, | ||||
|                       double _min_margin=0.003, int _edge_blur_size=5 ) | ||||
|     { | ||||
|         delta = _delta; | ||||
|         minArea = _min_area; | ||||
|         maxArea = _max_area; | ||||
|         maxVariation = _max_variation; | ||||
|         minDiversity = _min_diversity; | ||||
|         maxEvolution = _max_evolution; | ||||
|         areaThreshold = _area_threshold; | ||||
|         minMargin = _min_margin; | ||||
|         edgeBlurSize = _edge_blur_size; | ||||
|     } | ||||
|  | ||||
|     int delta; | ||||
|     int minArea; | ||||
|     int maxArea; | ||||
|     double maxVariation; | ||||
|     double minDiversity; | ||||
|     int maxEvolution; | ||||
|     double areaThreshold; | ||||
|     double minMargin; | ||||
|     int edgeBlurSize; | ||||
| }; | ||||
|  | ||||
| // the stable mscr should be: | ||||
| // bigger than minArea and smaller than maxArea | ||||
| // differ from its ancestor more than minDiversity | ||||
| static bool MSCRStableCheck( MSCRNode* x, MSERParams params ) | ||||
| { | ||||
|     if ( x->size <= params.minArea || x->size >= params.maxArea ) | ||||
|         return 0; | ||||
|     if ( x->gmsr == NULL ) | ||||
|         return 1; | ||||
|     double div = (double)(x->size-x->gmsr->size)/(double)x->size; | ||||
|     return div > params.minDiversity; | ||||
| } | ||||
|  | ||||
| static void | ||||
| extractMSER_8UC3( CvMat* src, | ||||
|                  CvMat* mask, | ||||
|                  vector<vector<Point> >& msers, | ||||
|                  MSERParams params ) | ||||
| { | ||||
|     msers.clear(); | ||||
|     MSCRNode* map = (MSCRNode*)cvAlloc( src->cols*src->rows*sizeof(map[0]) ); | ||||
|     int Ne = src->cols*src->rows*2-src->cols-src->rows; | ||||
|     MSCREdge* edge = (MSCREdge*)cvAlloc( Ne*sizeof(edge[0]) ); | ||||
|     TempMSCR* mscr = (TempMSCR*)cvAlloc( src->cols*src->rows*sizeof(mscr[0]) ); | ||||
|     double emean = 0; | ||||
|     CvMat* dx = cvCreateMat( src->rows, src->cols-1, CV_64FC1 ); | ||||
|     CvMat* dy = cvCreateMat( src->rows-1, src->cols, CV_64FC1 ); | ||||
|     Ne = preprocessMSER_8UC3( map, edge, &emean, src, mask, dx, dy, Ne, params.edgeBlurSize ); | ||||
|     emean = emean / (double)Ne; | ||||
|     std::sort(edge, edge + Ne, LessThanEdge()); | ||||
|     MSCREdge* edge_ub = edge+Ne; | ||||
|     MSCREdge* edgeptr = edge; | ||||
|     TempMSCR* mscrptr = mscr; | ||||
|     // the evolution process | ||||
|     for ( int i = 0; i < params.maxEvolution; i++ ) | ||||
|     { | ||||
|         double k = (double)i/(double)params.maxEvolution*(TABLE_SIZE-1); | ||||
|         int ti = cvFloor(k); | ||||
|         double reminder = k-ti; | ||||
|         double thres = emean*(chitab3[ti]*(1-reminder)+chitab3[ti+1]*reminder); | ||||
|         // to process all the edges in the list that chi < thres | ||||
|         while ( edgeptr < edge_ub && edgeptr->chi < thres ) | ||||
|         { | ||||
|             MSCRNode* lr = findMSCR( edgeptr->left ); | ||||
|             MSCRNode* rr = findMSCR( edgeptr->right ); | ||||
|             // get the region root (who is responsible) | ||||
|             if ( lr != rr ) | ||||
|             { | ||||
|                 // rank idea take from: N-tree Disjoint-Set Forests for Maximally Stable Extremal Regions | ||||
|                 if ( rr->rank > lr->rank ) | ||||
|                 { | ||||
|                     MSCRNode* tmp; | ||||
|                     CV_SWAP( lr, rr, tmp ); | ||||
|                 } else if ( lr->rank == rr->rank ) { | ||||
|                     // at the same rank, we will compare the size | ||||
|                     if ( lr->size > rr->size ) | ||||
|                     { | ||||
|                         MSCRNode* tmp; | ||||
|                         CV_SWAP( lr, rr, tmp ); | ||||
|                     } | ||||
|                     lr->rank++; | ||||
|                 } | ||||
|                 rr->shortcut = lr; | ||||
|                 lr->size += rr->size; | ||||
|                 // join rr to the end of list lr (lr is a endless double-linked list) | ||||
|                 lr->prev->next = rr; | ||||
|                 lr->prev = rr->prev; | ||||
|                 rr->prev->next = lr; | ||||
|                 rr->prev = lr; | ||||
|                 // area threshold force to reinitialize | ||||
|                 if ( lr->size > (lr->size-rr->size)*params.areaThreshold ) | ||||
|                 { | ||||
|                     lr->sizei = lr->size; | ||||
|                     lr->reinit = i; | ||||
|                     if ( lr->tmsr != NULL ) | ||||
|                     { | ||||
|                         lr->tmsr->m = lr->dt-lr->di; | ||||
|                         lr->tmsr = NULL; | ||||
|                     } | ||||
|                     lr->di = edgeptr->chi; | ||||
|                     lr->s = 1e10; | ||||
|                 } | ||||
|                 lr->dt = edgeptr->chi; | ||||
|                 if ( i > lr->reinit ) | ||||
|                 { | ||||
|                     double s = (double)(lr->size-lr->sizei)/(lr->dt-lr->di); | ||||
|                     if ( s < lr->s ) | ||||
|                     { | ||||
|                         // skip the first one and check stablity | ||||
|                         if ( i > lr->reinit+1 && MSCRStableCheck( lr, params ) ) | ||||
|                         { | ||||
|                             if ( lr->tmsr == NULL ) | ||||
|                             { | ||||
|                                 lr->gmsr = lr->tmsr = mscrptr; | ||||
|                                 mscrptr++; | ||||
|                             } | ||||
|                             lr->tmsr->size = lr->size; | ||||
|                             lr->tmsr->head = lr; | ||||
|                             lr->tmsr->tail = lr->prev; | ||||
|                             lr->tmsr->m = 0; | ||||
|                         } | ||||
|                         lr->s = s; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             edgeptr++; | ||||
|         } | ||||
|         if ( edgeptr >= edge_ub ) | ||||
|             break; | ||||
|     } | ||||
|     for ( TempMSCR* ptr = mscr; ptr < mscrptr; ptr++ ) | ||||
|         // to prune area with margin less than minMargin | ||||
|         if ( ptr->m > params.minMargin ) | ||||
|         { | ||||
|             vector<Point> mser; | ||||
|             MSCRNode* lpt = ptr->head; | ||||
|             for ( int i = 0; i < ptr->size; i++ ) | ||||
|             { | ||||
|                 Point pt; | ||||
|                 pt.x = (lpt->index)&0xffff; | ||||
|                 pt.y = (lpt->index)>>16; | ||||
|                 lpt = lpt->next; | ||||
|                 mser.push_back(pt); | ||||
|             } | ||||
|             msers.push_back(mser); | ||||
|         } | ||||
|     cvReleaseMat( &dx ); | ||||
|     cvReleaseMat( &dy ); | ||||
|     cvFree( &mscr ); | ||||
|     cvFree( &edge ); | ||||
|     cvFree( &map ); | ||||
| } | ||||
|  | ||||
| /****************************************************************************************\ | ||||
| *                                     Test for KeyPoint                                  * | ||||
| \****************************************************************************************/ | ||||
| @@ -74,6 +752,11 @@ protected: | ||||
|         } | ||||
|  | ||||
|         vector<KeyPoint> keypoints; | ||||
|         vector<vector<Point> > msers; | ||||
|         CvMat src = image; | ||||
|  | ||||
|         extractMSER_8UC3( &src, 0, msers, MSERParams()); | ||||
|  | ||||
|         detector->detect(image, keypoints); | ||||
|  | ||||
|         if(keypoints.empty()) | ||||
|   | ||||
| @@ -533,13 +533,13 @@ void CV_DescriptorMatcherTest::run( int ) | ||||
| TEST( Features2d_DescriptorMatcher_BruteForce, regression ) | ||||
| { | ||||
|     CV_DescriptorMatcherTest test( "descriptor-matcher-brute-force", | ||||
|                                   DescriptorMatcher::create("BFMatcher"), 0.01f ); | ||||
|                                   DescriptorMatcher::create("BruteForce"), 0.01f ); | ||||
|     test.safe_run(); | ||||
| } | ||||
|  | ||||
| TEST( Features2d_DescriptorMatcher_FlannBased, regression ) | ||||
| { | ||||
|     CV_DescriptorMatcherTest test( "descriptor-matcher-flann-based", | ||||
|                                   DescriptorMatcher::create("FlannBasedMatcher"), 0.04f ); | ||||
|                                   DescriptorMatcher::create("FlannBased"), 0.04f ); | ||||
|     test.safe_run(); | ||||
| } | ||||
|   | ||||
| @@ -595,7 +595,7 @@ protected: | ||||
|  | ||||
| TEST(Features2d_RotationInvariance_Detector_BRISK, regression) | ||||
| { | ||||
|     DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"), | ||||
|     DetectorRotationInvarianceTest test(BRISK::create(), | ||||
|                                         0.32f, | ||||
|                                         0.76f); | ||||
|     test.safe_run(); | ||||
| @@ -603,7 +603,7 @@ TEST(Features2d_RotationInvariance_Detector_BRISK, regression) | ||||
|  | ||||
| TEST(Features2d_RotationInvariance_Detector_ORB, regression) | ||||
| { | ||||
|     DetectorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"), | ||||
|     DetectorRotationInvarianceTest test(ORB::create(), | ||||
|                                         0.47f, | ||||
|                                         0.76f); | ||||
|     test.safe_run(); | ||||
|   | ||||
| @@ -321,7 +321,7 @@ SurfFeaturesFinder::SurfFeaturesFinder(double hess_thresh, int num_octaves, int | ||||
| { | ||||
|     if (num_octaves_descr == num_octaves && num_layers_descr == num_layers) | ||||
|     { | ||||
|         surf = Algorithm::create<Feature2D>("Feature2D.SURF"); | ||||
|         surf = xfeatures2d::SURF::create(); | ||||
|         if( !surf ) | ||||
|             CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" ); | ||||
|         surf->set("hessianThreshold", hess_thresh); | ||||
| @@ -330,8 +330,8 @@ SurfFeaturesFinder::SurfFeaturesFinder(double hess_thresh, int num_octaves, int | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         detector_ = Algorithm::create<FeatureDetector>("Feature2D.SURF"); | ||||
|         extractor_ = Algorithm::create<DescriptorExtractor>("Feature2D.SURF"); | ||||
|         detector_ = xfeatures2d::SURF::create(); | ||||
|         extractor_ = xfeatures2d::SURF::create(); | ||||
|  | ||||
|         if( !detector_ || !extractor_ ) | ||||
|             CV_Error( Error::StsNotImplemented, "OpenCV was built without SURF support" ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Vadim Pisarevsky
					Vadim Pisarevsky