From 6f3163f62d4234a862a18af274503cefa9e352a3 Mon Sep 17 00:00:00 2001 From: Peter Andreas Entschev Date: Wed, 27 Nov 2013 17:58:40 -0200 Subject: [PATCH] DescriptorExtractor: added defaultNorm() to return default norm type. Added the defaultNorm() method to the DescriptorExtractor class. This method returns the default norm type for each descriptor type. The tests and C/C++ samples were updated to get the norm type directly from the DescriptorExtractor inherited classes. This was reported in feature report #2182 (http://code.opencv.org/issues/2182). It will make it possible to get the norm type usually applied matching method for each descriptor, instead of passing it manually. --- .../common_interfaces_of_descriptor_extractors.rst | 3 +++ modules/features2d/include/opencv2/features2d.hpp | 10 +++++++++ modules/features2d/src/brief.cpp | 5 +++++ modules/features2d/src/brisk.cpp | 6 +++++ modules/features2d/src/descriptors.cpp | 5 +++++ modules/features2d/src/freak.cpp | 5 +++++ modules/features2d/src/orb.cpp | 5 +++++ .../test/test_rotation_and_scale_invariance.cpp | 26 +++++++++++----------- .../common_interfaces_of_descriptor_extractors.rst | 1 + modules/legacy/include/opencv2/legacy.hpp | 1 + modules/nonfree/include/opencv2/nonfree/cuda.hpp | 2 ++ .../nonfree/include/opencv2/nonfree/features2d.hpp | 6 +++++ modules/nonfree/include/opencv2/nonfree/ocl.hpp | 2 ++ modules/nonfree/src/sift.cpp | 5 +++++ modules/nonfree/src/surf.cpp | 1 + modules/nonfree/src/surf.cuda.cpp | 5 +++++ modules/nonfree/src/surf.ocl.cpp | 5 +++++ modules/nonfree/test/test_features2d.cpp | 2 +- modules/nonfree/test/test_surf.cuda.cpp | 2 +- modules/nonfree/test/test_surf.ocl.cpp | 2 +- samples/c/find_obj_calonder.cpp | 2 +- samples/cpp/brief_match_test.cpp | 2 +- samples/cpp/detector_descriptor_evaluation.cpp | 5 +++-- samples/cpp/freak_demo.cpp | 2 +- samples/cpp/matcher_simple.cpp | 2 +- samples/cpp/shape_transformation.cpp | 2 +- .../tutorial_code/features2D/SURF_descriptor.cpp | 2 +- samples/cpp/video_homography.cpp | 2 +- samples/gpu/surf_keypoint_matcher.cpp | 2 +- 29 files changed, 94 insertions(+), 26 deletions(-) diff --git a/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst b/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst index 83688c0..bf84ed0 100644 --- a/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst +++ b/modules/features2d/doc/common_interfaces_of_descriptor_extractors.rst @@ -35,6 +35,7 @@ Abstract base class for computing descriptors for image keypoints. :: virtual int descriptorSize() const = 0; virtual int descriptorType() const = 0; + virtual int defaultNorm() const = 0; static Ptr create( const String& descriptorExtractorType ); @@ -114,6 +115,7 @@ them into a single color descriptor. :: virtual void write( FileStorage& ) const; virtual int descriptorSize() const; virtual int descriptorType() const; + virtual int defaultNorm() const; protected: ... }; @@ -141,6 +143,7 @@ Strecha C., Fua P. *BRIEF: Binary Robust Independent Elementary Features* , virtual void write( FileStorage& ) const; virtual int descriptorSize() const; virtual int descriptorType() const; + virtual int defaultNorm() const; protected: ... }; diff --git a/modules/features2d/include/opencv2/features2d.hpp b/modules/features2d/include/opencv2/features2d.hpp index 9cbae22..75b591c 100644 --- a/modules/features2d/include/opencv2/features2d.hpp +++ b/modules/features2d/include/opencv2/features2d.hpp @@ -169,6 +169,7 @@ public: CV_WRAP virtual int descriptorSize() const = 0; CV_WRAP virtual int descriptorType() const = 0; + CV_WRAP virtual int defaultNorm() const = 0; CV_WRAP virtual bool empty() const; @@ -226,6 +227,8 @@ public: int descriptorSize() const; // returns the descriptor type int descriptorType() const; + // returns the default norm type + int defaultNorm() const; // Compute the BRISK features on an image void operator()(InputArray image, InputArray mask, std::vector& keypoints) const; @@ -320,6 +323,8 @@ public: int descriptorSize() const; // returns the descriptor type int descriptorType() const; + // returns the default norm type + int defaultNorm() const; // Compute the ORB features and descriptors on an image void operator()(InputArray image, InputArray mask, std::vector& keypoints) const; @@ -377,6 +382,9 @@ public: /** returns the descriptor type */ virtual int descriptorType() const; + /** returns the default norm type */ + virtual int defaultNorm() const; + /** select the 512 "best description pairs" * @param images grayscale images set * @param keypoints set of detected keypoints @@ -837,6 +845,7 @@ public: virtual int descriptorSize() const; virtual int descriptorType() const; + virtual int defaultNorm() const; virtual bool empty() const; @@ -863,6 +872,7 @@ public: virtual int descriptorSize() const; virtual int descriptorType() const; + virtual int defaultNorm() const; /// @todo read and write for brief diff --git a/modules/features2d/src/brief.cpp b/modules/features2d/src/brief.cpp index a429451..2521919 100644 --- a/modules/features2d/src/brief.cpp +++ b/modules/features2d/src/brief.cpp @@ -125,6 +125,11 @@ int BriefDescriptorExtractor::descriptorType() const return CV_8UC1; } +int BriefDescriptorExtractor::defaultNorm() const +{ + return NORM_HAMMING; +} + void BriefDescriptorExtractor::read( const FileNode& fn) { int dSize = fn["descriptorSize"]; diff --git a/modules/features2d/src/brisk.cpp b/modules/features2d/src/brisk.cpp index 76bded6..a3c5d7e 100644 --- a/modules/features2d/src/brisk.cpp +++ b/modules/features2d/src/brisk.cpp @@ -712,6 +712,12 @@ BRISK::descriptorType() const return CV_8U; } +int +BRISK::defaultNorm() const +{ + return NORM_HAMMING; +} + BRISK::~BRISK() { delete[] patternPoints_; diff --git a/modules/features2d/src/descriptors.cpp b/modules/features2d/src/descriptors.cpp index b79768a..9e0ac5c 100644 --- a/modules/features2d/src/descriptors.cpp +++ b/modules/features2d/src/descriptors.cpp @@ -247,6 +247,11 @@ int OpponentColorDescriptorExtractor::descriptorType() const return descriptorExtractor->descriptorType(); } +int OpponentColorDescriptorExtractor::defaultNorm() const +{ + return descriptorExtractor->defaultNorm(); +} + bool OpponentColorDescriptorExtractor::empty() const { return !descriptorExtractor || descriptorExtractor->empty(); diff --git a/modules/features2d/src/freak.cpp b/modules/features2d/src/freak.cpp index 086a2e2..4aca4c1 100644 --- a/modules/features2d/src/freak.cpp +++ b/modules/features2d/src/freak.cpp @@ -623,4 +623,9 @@ int FREAK::descriptorType() const { return CV_8U; } +int FREAK::defaultNorm() const +{ + return NORM_HAMMING; +} + } // END NAMESPACE CV diff --git a/modules/features2d/src/orb.cpp b/modules/features2d/src/orb.cpp index a6e8ffa..ed9716d 100644 --- a/modules/features2d/src/orb.cpp +++ b/modules/features2d/src/orb.cpp @@ -575,6 +575,11 @@ int ORB::descriptorType() const return CV_8U; } +int ORB::defaultNorm() const +{ + return NORM_HAMMING; +} + /** Compute the ORB features and descriptors on an image * @param img the image to compute the features and descriptors on * @param mask the mask to apply diff --git a/modules/features2d/test/test_rotation_and_scale_invariance.cpp b/modules/features2d/test/test_rotation_and_scale_invariance.cpp index adfe428..2fe59ca 100644 --- a/modules/features2d/test/test_rotation_and_scale_invariance.cpp +++ b/modules/features2d/test/test_rotation_and_scale_invariance.cpp @@ -616,8 +616,8 @@ TEST(Features2d_RotationInvariance_Detector_ORB, regression) TEST(Features2d_RotationInvariance_Descriptor_BRISK, regression) { DescriptorRotationInvarianceTest test(Algorithm::create("Feature2D.BRISK"), - Algorithm::create("Feature2D.BRISK"), - NORM_HAMMING, + Algorithm::create("Feature2D.BRISK"), + Algorithm::create("Feature2D.BRISK")->defaultNorm(), 0.99f); test.safe_run(); } @@ -626,7 +626,7 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression) { DescriptorRotationInvarianceTest test(Algorithm::create("Feature2D.ORB"), Algorithm::create("Feature2D.ORB"), - NORM_HAMMING, + Algorithm::create("Feature2D.ORB")->defaultNorm(), 0.99f); test.safe_run(); } @@ -635,7 +635,7 @@ TEST(Features2d_RotationInvariance_Descriptor_ORB, regression) //{ // DescriptorRotationInvarianceTest test(Algorithm::create("Feature2D.ORB"), // Algorithm::create("Feature2D.FREAK"), -// NORM_HAMMING, +// Algorithm::create("Feature2D.FREAK")->defaultNorm(), // 0.f); // test.safe_run(); //} @@ -667,26 +667,26 @@ TEST(Features2d_ScaleInvariance_Detector_BRISK, regression) //TEST(Features2d_ScaleInvariance_Descriptor_BRISK, regression) //{ // DescriptorScaleInvarianceTest test(Algorithm::create("Feature2D.BRISK"), -// Algorithm::create("Feature2D.BRISK"), -// NORM_HAMMING, -// 0.99f); +// Algorithm::create("Feature2D.BRISK"), +// Algorithm::create("Feature2D.BRISK")->defaultNorm(), +// 0.99f); // test.safe_run(); //} //TEST(Features2d_ScaleInvariance_Descriptor_ORB, regression) //{ // DescriptorScaleInvarianceTest test(Algorithm::create("Feature2D.ORB"), -// Algorithm::create("Feature2D.ORB"), -// NORM_HAMMING, -// 0.01f); +// Algorithm::create("Feature2D.ORB"), +// Algorithm::create("Feature2D.ORB")->defaultNorm(), +// 0.01f); // test.safe_run(); //} //TEST(Features2d_ScaleInvariance_Descriptor_FREAK, regression) //{ // DescriptorScaleInvarianceTest test(Algorithm::create("Feature2D.ORB"), -// Algorithm::create("Feature2D.FREAK"), -// NORM_HAMMING, -// 0.01f); +// Algorithm::create("Feature2D.FREAK"), +// Algorithm::create("Feature2D.FREAK")->defaultNorm(), +// 0.01f); // test.safe_run(); //} diff --git a/modules/legacy/doc/common_interfaces_of_descriptor_extractors.rst b/modules/legacy/doc/common_interfaces_of_descriptor_extractors.rst index 4f13385..2b59a4e 100644 --- a/modules/legacy/doc/common_interfaces_of_descriptor_extractors.rst +++ b/modules/legacy/doc/common_interfaces_of_descriptor_extractors.rst @@ -28,6 +28,7 @@ Wrapping class for computing descriptors by using the virtual void write( FileStorage &fs ) const; virtual int descriptorSize() const; virtual int descriptorType() const; + virtual int defaultNorm() const; protected: ... } diff --git a/modules/legacy/include/opencv2/legacy.hpp b/modules/legacy/include/opencv2/legacy.hpp index ed0ac9c..01f726b 100644 --- a/modules/legacy/include/opencv2/legacy.hpp +++ b/modules/legacy/include/opencv2/legacy.hpp @@ -2765,6 +2765,7 @@ public: virtual int descriptorSize() const { return classifier_.classes(); } virtual int descriptorType() const { return DataType::type; } + virtual int defaultNorm() const { return NORM_L1; } virtual bool empty() const; diff --git a/modules/nonfree/include/opencv2/nonfree/cuda.hpp b/modules/nonfree/include/opencv2/nonfree/cuda.hpp index 1a5d3b9..0e1f8e5 100644 --- a/modules/nonfree/include/opencv2/nonfree/cuda.hpp +++ b/modules/nonfree/include/opencv2/nonfree/cuda.hpp @@ -70,6 +70,8 @@ public: //! returns the descriptor size in float's (64 or 128) int descriptorSize() const; + //! returns the default norm type + int defaultNorm() const; //! upload host keypoints to device memory void uploadKeypoints(const std::vector& keypoints, GpuMat& keypointsGPU); diff --git a/modules/nonfree/include/opencv2/nonfree/features2d.hpp b/modules/nonfree/include/opencv2/nonfree/features2d.hpp index 4acd747..88a1731 100644 --- a/modules/nonfree/include/opencv2/nonfree/features2d.hpp +++ b/modules/nonfree/include/opencv2/nonfree/features2d.hpp @@ -66,6 +66,9 @@ public: //! returns the descriptor type CV_WRAP int descriptorType() const; + //! returns the default norm type + CV_WRAP int defaultNorm() const; + //! finds the keypoints using SIFT algorithm void operator()(InputArray img, InputArray mask, std::vector& keypoints) const; @@ -118,6 +121,9 @@ public: //! returns the descriptor type CV_WRAP int descriptorType() const; + //! returns the descriptor type + CV_WRAP int defaultNorm() const; + //! finds the keypoints using fast hessian detector used in SURF void operator()(InputArray img, InputArray mask, CV_OUT std::vector& keypoints) const; diff --git a/modules/nonfree/include/opencv2/nonfree/ocl.hpp b/modules/nonfree/include/opencv2/nonfree/ocl.hpp index 22b40ae..b06fa39 100644 --- a/modules/nonfree/include/opencv2/nonfree/ocl.hpp +++ b/modules/nonfree/include/opencv2/nonfree/ocl.hpp @@ -76,6 +76,8 @@ namespace cv //! returns the descriptor size in float's (64 or 128) int descriptorSize() const; + //! returns the default norm type + int defaultNorm() const; //! upload host keypoints to device memory void uploadKeypoints(const std::vector &keypoints, oclMat &keypointsocl); //! download keypoints from device to host memory diff --git a/modules/nonfree/src/sift.cpp b/modules/nonfree/src/sift.cpp index e67138c..4a36c2d 100644 --- a/modules/nonfree/src/sift.cpp +++ b/modules/nonfree/src/sift.cpp @@ -717,6 +717,11 @@ int SIFT::descriptorType() const return CV_32F; } +int SIFT::defaultNorm() const +{ + return NORM_L2; +} + void SIFT::operator()(InputArray _image, InputArray _mask, std::vector& keypoints) const diff --git a/modules/nonfree/src/surf.cpp b/modules/nonfree/src/surf.cpp index 98d1449..be8d14d 100644 --- a/modules/nonfree/src/surf.cpp +++ b/modules/nonfree/src/surf.cpp @@ -884,6 +884,7 @@ SURF::SURF(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended, int SURF::descriptorSize() const { return extended ? 128 : 64; } int SURF::descriptorType() const { return CV_32F; } +int SURF::defaultNorm() const { return NORM_L2; } void SURF::operator()(InputArray imgarg, InputArray maskarg, CV_OUT std::vector& keypoints) const diff --git a/modules/nonfree/src/surf.cuda.cpp b/modules/nonfree/src/surf.cuda.cpp index 2912d04..4089b50 100644 --- a/modules/nonfree/src/surf.cuda.cpp +++ b/modules/nonfree/src/surf.cuda.cpp @@ -265,6 +265,11 @@ int cv::cuda::SURF_CUDA::descriptorSize() const return extended ? 128 : 64; } +int cv::cuda::SURF_CUDA::defaultNorm() const +{ + return NORM_L2; +} + void cv::cuda::SURF_CUDA::uploadKeypoints(const std::vector& keypoints, GpuMat& keypointsGPU) { if (keypoints.empty()) diff --git a/modules/nonfree/src/surf.ocl.cpp b/modules/nonfree/src/surf.ocl.cpp index 3b30663..5ade5e5 100644 --- a/modules/nonfree/src/surf.ocl.cpp +++ b/modules/nonfree/src/surf.ocl.cpp @@ -299,6 +299,11 @@ int cv::ocl::SURF_OCL::descriptorSize() const return extended ? 128 : 64; } +int cv::ocl::SURF_OCL::defaultNorm() const +{ + return NORM_L2; +} + void cv::ocl::SURF_OCL::uploadKeypoints(const std::vector &keypoints, oclMat &keypointsGPU) { if (keypoints.empty()) diff --git a/modules/nonfree/test/test_features2d.cpp b/modules/nonfree/test/test_features2d.cpp index 03041b0..3cc5b47 100644 --- a/modules/nonfree/test/test_features2d.cpp +++ b/modules/nonfree/test/test_features2d.cpp @@ -1124,7 +1124,7 @@ protected: CV_Assert(kpt2[i].response > 0 ); vector matches; - BFMatcher(NORM_L2, true).match(d1, d2, matches); + BFMatcher(f->defaultNorm(), true).match(d1, d2, matches); vector pt1, pt2; for( size_t i = 0; i < matches.size(); i++ ) { diff --git a/modules/nonfree/test/test_surf.cuda.cpp b/modules/nonfree/test/test_surf.cuda.cpp index 360b798..4011f3c 100644 --- a/modules/nonfree/test/test_surf.cuda.cpp +++ b/modules/nonfree/test/test_surf.cuda.cpp @@ -176,7 +176,7 @@ CUDA_TEST_P(SURF, Descriptor) cv::Mat descriptors_gold; surf_gold(image, cv::noArray(), keypoints, descriptors_gold, true); - cv::BFMatcher matcher(cv::NORM_L2); + cv::BFMatcher matcher(surf.defaultNorm()); std::vector matches; matcher.match(descriptors_gold, cv::Mat(descriptors), matches); diff --git a/modules/nonfree/test/test_surf.ocl.cpp b/modules/nonfree/test/test_surf.ocl.cpp index c52b6e3..217460a 100644 --- a/modules/nonfree/test/test_surf.ocl.cpp +++ b/modules/nonfree/test/test_surf.ocl.cpp @@ -195,7 +195,7 @@ TEST_P(SURF, DISABLED_Descriptor) cv::Mat descriptors_gold; surf_gold(image, cv::noArray(), keypoints, descriptors_gold, true); - cv::BFMatcher matcher(cv::NORM_L2); + cv::BFMatcher matcher(surf.defaultNorm()); std::vector matches; matcher.match(descriptors_gold, cv::Mat(descriptors), matches); diff --git a/samples/c/find_obj_calonder.cpp b/samples/c/find_obj_calonder.cpp index cb65517..a7b01c8 100644 --- a/samples/c/find_obj_calonder.cpp +++ b/samples/c/find_obj_calonder.cpp @@ -125,7 +125,7 @@ static void testCalonderClassifier( const string& classifierFilename, const stri Mat descriptors2; de.compute( img2, keypoints2, descriptors2 ); // Match descriptors - BFMatcher matcher(NORM_L1); + BFMatcher matcher(de.defaultNorm()); vector matches; matcher.match( descriptors1, descriptors2, matches ); diff --git a/samples/cpp/brief_match_test.cpp b/samples/cpp/brief_match_test.cpp index 1f12132..bf99ec7 100644 --- a/samples/cpp/brief_match_test.cpp +++ b/samples/cpp/brief_match_test.cpp @@ -106,7 +106,7 @@ int main(int argc, const char ** argv) //Do matching using features2d cout << "matching with BruteForceMatcher" << endl; - BFMatcher matcher_popcount(NORM_HAMMING); + BFMatcher matcher_popcount(extractor.defaultNorm()); vector matches_popcount; double pop_time = match(kpts_1, kpts_2, matcher_popcount, desc_1, desc_2, matches_popcount); cout << "done BruteForceMatcher matching. took " << pop_time << " seconds" << endl; diff --git a/samples/cpp/detector_descriptor_evaluation.cpp b/samples/cpp/detector_descriptor_evaluation.cpp index dd3cd80..ccb8979 100644 --- a/samples/cpp/detector_descriptor_evaluation.cpp +++ b/samples/cpp/detector_descriptor_evaluation.cpp @@ -881,9 +881,10 @@ public: virtual void readAlgorithm( ) { string classifierFile = data_path + "/features2d/calonder_classifier.rtc"; + Ptr extractor = makePtr >( classifierFile ); defaultDescMatcher = makePtr( - makePtr >( classifierFile ), - makePtr(int(NORM_L2))); + extractor, + makePtr(extractor->defaultNorm())); specificDescMatcher = defaultDescMatcher; } }; diff --git a/samples/cpp/freak_demo.cpp b/samples/cpp/freak_demo.cpp index fa58d20..e6429ae 100644 --- a/samples/cpp/freak_demo.cpp +++ b/samples/cpp/freak_demo.cpp @@ -96,7 +96,7 @@ int main( int argc, char** argv ) { // The standard Hamming distance can be used such as // BFMatcher matcher(NORM_HAMMING); // or the proposed cascade of hamming distance using SSSE3 - BFMatcher matcher(NORM_HAMMING); + BFMatcher matcher(extractor.defaultNorm()); // detect double t = (double)getTickCount(); diff --git a/samples/cpp/matcher_simple.cpp b/samples/cpp/matcher_simple.cpp index c1cd6e4..39d3620 100644 --- a/samples/cpp/matcher_simple.cpp +++ b/samples/cpp/matcher_simple.cpp @@ -44,7 +44,7 @@ int main(int argc, char** argv) extractor.compute(img2, keypoints2, descriptors2); // matching descriptors - BFMatcher matcher(NORM_L2); + BFMatcher matcher(extractor.defaultNorm()); vector matches; matcher.match(descriptors1, descriptors2, matches); diff --git a/samples/cpp/shape_transformation.cpp b/samples/cpp/shape_transformation.cpp index abd7eab..5dac0a5 100644 --- a/samples/cpp/shape_transformation.cpp +++ b/samples/cpp/shape_transformation.cpp @@ -45,7 +45,7 @@ int main(int argc, char** argv) extractor.compute(img2, keypoints2, descriptors2); // matching descriptors - BFMatcher matcher(NORM_L2); + BFMatcher matcher(extractor.defaultNorm()); vector matches; matcher.match(descriptors1, descriptors2, matches); diff --git a/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp b/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp index 56067c8..89b60d4 100644 --- a/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp +++ b/samples/cpp/tutorial_code/features2D/SURF_descriptor.cpp @@ -49,7 +49,7 @@ int main( int argc, char** argv ) extractor.compute( img_2, keypoints_2, descriptors_2 ); //-- Step 3: Matching descriptor vectors with a brute force matcher - BFMatcher matcher(NORM_L2); + BFMatcher matcher(extractor.defaultNorm()); std::vector< DMatch > matches; matcher.match( descriptors_1, descriptors_2, matches ); diff --git a/samples/cpp/video_homography.cpp b/samples/cpp/video_homography.cpp index bf2559f..cefdc89 100644 --- a/samples/cpp/video_homography.cpp +++ b/samples/cpp/video_homography.cpp @@ -140,7 +140,7 @@ int main(int ac, char ** av) vector matches; - BFMatcher desc_matcher(NORM_HAMMING); + BFMatcher desc_matcher(brief.defaultNorm()); vector train_pts, query_pts; vector train_kpts, query_kpts; diff --git a/samples/gpu/surf_keypoint_matcher.cpp b/samples/gpu/surf_keypoint_matcher.cpp index ba5e364..c267dd4 100644 --- a/samples/gpu/surf_keypoint_matcher.cpp +++ b/samples/gpu/surf_keypoint_matcher.cpp @@ -62,7 +62,7 @@ int main(int argc, char* argv[]) cout << "FOUND " << keypoints2GPU.cols << " keypoints on second image" << endl; // matching descriptors - BFMatcher_CUDA matcher(NORM_L2); + BFMatcher_CUDA matcher(surf.defaultNorm()); GpuMat trainIdx, distance; matcher.matchSingle(descriptors1GPU, descriptors2GPU, trainIdx, distance); -- 2.7.4