From a3274187671c4b4c2868f2ca8dd3face19f2176f Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Tue, 21 Apr 2020 06:58:21 +0000 Subject: [PATCH] features2d(sift): move SIFT tests / headers / build fixes --- doc/opencv.bib | 2 +- .../py_feature_homography.markdown | 2 +- .../py_matcher/py_matcher.markdown | 4 +- .../py_sift_intro/py_sift_intro.markdown | 4 +- .../feature_flann_matcher.markdown | 2 +- .../features2d/include/opencv2/features2d.hpp | 33 ++++++++++++++++ .../test/SIFTDescriptorExtractorTest.java | 3 +- modules/features2d/perf/perf_sift.cpp | 21 ++++++++-- modules/features2d/src/sift.cpp | 6 --- .../test/test_descriptors_invariance.cpp | 7 ++++ .../test/test_descriptors_regression.cpp | 38 ++++++++++++++++++- .../test/test_detectors_invariance.cpp | 7 ++++ .../test/test_detectors_regression.cpp | 6 +++ modules/features2d/test/test_keypoints.cpp | 7 ++++ modules/stitching/src/matchers.cpp | 7 ---- .../real_time_pose_estimation/src/Utils.cpp | 11 +----- samples/python/find_obj.py | 2 +- 17 files changed, 126 insertions(+), 36 deletions(-) diff --git a/doc/opencv.bib b/doc/opencv.bib index 0135418d4a..901fbe86ee 100644 --- a/doc/opencv.bib +++ b/doc/opencv.bib @@ -620,7 +620,7 @@ volume = {1}, publisher = {IEEE} } -@article{Lowe:2004:DIF:993451.996342, +@article{Lowe04, author = {Lowe, David G.}, title = {Distinctive Image Features from Scale-Invariant Keypoints}, journal = {Int. J. Comput. Vision}, diff --git a/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown b/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown index ed76d638f5..8602cc9398 100644 --- a/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown +++ b/doc/py_tutorials/py_feature2d/py_feature_homography/py_feature_homography.markdown @@ -44,7 +44,7 @@ img1 = cv.imread('box.png',0) # queryImage img2 = cv.imread('box_in_scene.png',0) # trainImage # Initiate SIFT detector -sift = cv.xfeatures2d.SIFT_create() +sift = cv.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) diff --git a/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.markdown b/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.markdown index d8ba8f856d..aeab98bfd6 100644 --- a/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.markdown +++ b/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.markdown @@ -110,7 +110,7 @@ img1 = cv.imread('box.png',cv.IMREAD_GRAYSCALE) # queryImage img2 = cv.imread('box_in_scene.png',cv.IMREAD_GRAYSCALE) # trainImage # Initiate SIFT detector -sift = cv.xfeatures2d.SIFT_create() +sift = cv.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) @@ -174,7 +174,7 @@ img1 = cv.imread('box.png',cv.IMREAD_GRAYSCALE) # queryImage img2 = cv.imread('box_in_scene.png',cv.IMREAD_GRAYSCALE) # trainImage # Initiate SIFT detector -sift = cv.xfeatures2d.SIFT_create() +sift = cv.SIFT_create() # find the keypoints and descriptors with SIFT kp1, des1 = sift.detectAndCompute(img1,None) diff --git a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown index f9d70938eb..656f5423c5 100644 --- a/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown +++ b/doc/py_tutorials/py_feature2d/py_sift_intro/py_sift_intro.markdown @@ -119,7 +119,7 @@ import cv2 as cv img = cv.imread('home.jpg') gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY) -sift = cv.xfeatures2d.SIFT_create() +sift = cv.SIFT_create() kp = sift.detect(gray,None) img=cv.drawKeypoints(gray,kp,img) @@ -151,7 +151,7 @@ Now to calculate the descriptor, OpenCV provides two methods. We will see the second method: @code{.py} -sift = cv.xfeatures2d.SIFT_create() +sift = cv.SIFT_create() kp, des = sift.detectAndCompute(gray,None) @endcode Here kp will be a list of keypoints and des is a numpy array of shape diff --git a/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown b/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown index 4b3f3daddf..47ba7a0460 100644 --- a/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown +++ b/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.markdown @@ -27,7 +27,7 @@ Binary descriptors (ORB, BRISK, ...) are matched using the sift; +typedef perf::TestBaseWithParam SIFT_detect; +typedef perf::TestBaseWithParam SIFT_extract; +typedef perf::TestBaseWithParam SIFT_full; #define SIFT_IMAGES \ "cv/detectors_descriptors_evaluation/images_datasets/leuven/img1.png",\ "stitching/a3.png" -PERF_TEST_P(sift, detect, testing::Values(SIFT_IMAGES)) +PERF_TEST_P_(SIFT_detect, SIFT) { string filename = getDataPath(GetParam()); Mat frame = imread(filename, IMREAD_GRAYSCALE); @@ -29,7 +31,7 @@ PERF_TEST_P(sift, detect, testing::Values(SIFT_IMAGES)) SANITY_CHECK_NOTHING(); } -PERF_TEST_P(sift, extract, testing::Values(SIFT_IMAGES)) +PERF_TEST_P_(SIFT_extract, SIFT) { string filename = getDataPath(GetParam()); Mat frame = imread(filename, IMREAD_GRAYSCALE); @@ -50,7 +52,7 @@ PERF_TEST_P(sift, extract, testing::Values(SIFT_IMAGES)) SANITY_CHECK_NOTHING(); } -PERF_TEST_P(sift, full, testing::Values(SIFT_IMAGES)) +PERF_TEST_P_(SIFT_full, SIFT) { string filename = getDataPath(GetParam()); Mat frame = imread(filename, IMREAD_GRAYSCALE); @@ -69,4 +71,15 @@ PERF_TEST_P(sift, full, testing::Values(SIFT_IMAGES)) SANITY_CHECK_NOTHING(); } + +INSTANTIATE_TEST_CASE_P(/*nothing*/, SIFT_detect, + testing::Values(SIFT_IMAGES) +); +INSTANTIATE_TEST_CASE_P(/*nothing*/, SIFT_extract, + testing::Values(SIFT_IMAGES) +); +INSTANTIATE_TEST_CASE_P(/*nothing*/, SIFT_full, + testing::Values(SIFT_IMAGES) +); + }} // namespace diff --git a/modules/features2d/src/sift.cpp b/modules/features2d/src/sift.cpp index 74e46c5a72..81254ecbd8 100644 --- a/modules/features2d/src/sift.cpp +++ b/modules/features2d/src/sift.cpp @@ -355,7 +355,6 @@ static float calcOrientationHist( const Mat& img, Point pt, int radius, k = 0; #if CV_AVX2 - if( USE_AVX2 ) { __m256 __nd360 = _mm256_set1_ps(n/360.f); __m256i __n = _mm256_set1_epi32(n); @@ -402,7 +401,6 @@ static float calcOrientationHist( const Mat& img, Point pt, int radius, i = 0; #if CV_AVX2 - if( USE_AVX2 ) { __m256 __d_1_16 = _mm256_set1_ps(1.f/16.f); __m256 __d_4_16 = _mm256_set1_ps(4.f/16.f); @@ -784,7 +782,6 @@ static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float sc k = 0; #if CV_AVX2 - if( USE_AVX2 ) { int CV_DECL_ALIGNED(32) idx_buf[8]; float CV_DECL_ALIGNED(32) rco_buf[64]; @@ -928,7 +925,6 @@ static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float sc len = d*d*n; k = 0; #if CV_AVX2 - if( USE_AVX2 ) { float CV_DECL_ALIGNED(32) nrm2_buf[8]; __m256 __nrm2 = _mm256_setzero_ps(); @@ -956,7 +952,6 @@ static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float sc #if 0 //CV_AVX2 // This code cannot be enabled because it sums nrm2 in a different order, // thus producing slightly different results - if( USE_AVX2 ) { float CV_DECL_ALIGNED(32) nrm2_buf[8]; __m256 __dst; @@ -989,7 +984,6 @@ static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float sc #if 1 k = 0; #if CV_AVX2 - if( USE_AVX2 ) { __m256 __dst; __m256 __min = _mm256_setzero_ps(); diff --git a/modules/features2d/test/test_descriptors_invariance.cpp b/modules/features2d/test/test_descriptors_invariance.cpp index f9c65067c5..0bbcad43c5 100644 --- a/modules/features2d/test/test_descriptors_invariance.cpp +++ b/modules/features2d/test/test_descriptors_invariance.cpp @@ -167,6 +167,9 @@ TEST_P(DescriptorScaleInvariance, scale) * Descriptors's rotation invariance check */ +INSTANTIATE_TEST_CASE_P(SIFT, DescriptorRotationInvariance, + Value(IMAGE_TSUKUBA, SIFT::create(), SIFT::create(), 0.98f)); + INSTANTIATE_TEST_CASE_P(BRISK, DescriptorRotationInvariance, Value(IMAGE_TSUKUBA, BRISK::create(), BRISK::create(), 0.99f)); @@ -183,6 +186,10 @@ INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DescriptorRotationInvariance, * Descriptor's scale invariance check */ +// TODO: Expected: (descInliersRatio) >= (minInliersRatio), actual: 0.330378 vs 0.78 +INSTANTIATE_TEST_CASE_P(DISABLED_SIFT, DescriptorScaleInvariance, + Value(IMAGE_BIKES, SIFT::create(), SIFT::create(), 0.78f)); + INSTANTIATE_TEST_CASE_P(AKAZE, DescriptorScaleInvariance, Value(IMAGE_BIKES, AKAZE::create(), AKAZE::create(), 0.6f)); diff --git a/modules/features2d/test/test_descriptors_regression.cpp b/modules/features2d/test/test_descriptors_regression.cpp index c63b9a56ce..f8760d6478 100644 --- a/modules/features2d/test/test_descriptors_regression.cpp +++ b/modules/features2d/test/test_descriptors_regression.cpp @@ -342,6 +342,13 @@ private: * Tests registrations * \****************************************************************************************/ +TEST( Features2d_DescriptorExtractor_SIFT, regression ) +{ + CV_DescriptorExtractorTest > test( "descriptor-sift", 1.0f, + SIFT::create() ); + test.safe_run(); +} + TEST( Features2d_DescriptorExtractor_BRISK, regression ) { CV_DescriptorExtractorTest test( "descriptor-brisk", @@ -388,7 +395,7 @@ TEST( Features2d_DescriptorExtractor_AKAZE_DESCRIPTOR_KAZE, regression ) test.safe_run(); } -TEST( Features2d_DescriptorExtractor, batch ) +TEST( Features2d_DescriptorExtractor, batch_ORB ) { string path = string(cvtest::TS::ptr()->get_data_path() + "detectors_descriptors_evaluation/images_datasets/graf"); vector imgs, descriptors; @@ -416,6 +423,35 @@ TEST( Features2d_DescriptorExtractor, batch ) } } +TEST( Features2d_DescriptorExtractor, batch_SIFT ) +{ + string path = string(cvtest::TS::ptr()->get_data_path() + "detectors_descriptors_evaluation/images_datasets/graf"); + vector imgs, descriptors; + vector > keypoints; + int i, n = 6; + Ptr sift = SIFT::create(); + + for( i = 0; i < n; i++ ) + { + string imgname = format("%s/img%d.png", path.c_str(), i+1); + Mat img = imread(imgname, 0); + imgs.push_back(img); + } + + sift->detect(imgs, keypoints); + sift->compute(imgs, keypoints, descriptors); + + ASSERT_EQ((int)keypoints.size(), n); + ASSERT_EQ((int)descriptors.size(), n); + + for( i = 0; i < n; i++ ) + { + EXPECT_GT((int)keypoints[i].size(), 100); + EXPECT_GT(descriptors[i].rows, 100); + } +} + + class DescriptorImage : public TestWithParam { protected: diff --git a/modules/features2d/test/test_detectors_invariance.cpp b/modules/features2d/test/test_detectors_invariance.cpp index c4c6874509..31ba12e60e 100644 --- a/modules/features2d/test/test_detectors_invariance.cpp +++ b/modules/features2d/test/test_detectors_invariance.cpp @@ -220,6 +220,9 @@ TEST_P(DetectorScaleInvariance, scale) * Detector's rotation invariance check */ +INSTANTIATE_TEST_CASE_P(SIFT, DetectorRotationInvariance, + Value(IMAGE_TSUKUBA, SIFT::create(), 0.45f, 0.70f)); + INSTANTIATE_TEST_CASE_P(BRISK, DetectorRotationInvariance, Value(IMAGE_TSUKUBA, BRISK::create(), 0.45f, 0.76f)); @@ -236,6 +239,10 @@ INSTANTIATE_TEST_CASE_P(AKAZE_DESCRIPTOR_KAZE, DetectorRotationInvariance, * Detector's scale invariance check */ +// TODO: Expected: (keyPointMatchesRatio) >= (minKeyPointMatchesRatio), actual: 0.596752 vs 0.69 +INSTANTIATE_TEST_CASE_P(DISABLED_SIFT, DetectorScaleInvariance, + Value(IMAGE_BIKES, SIFT::create(), 0.69f, 0.98f)); + INSTANTIATE_TEST_CASE_P(BRISK, DetectorScaleInvariance, Value(IMAGE_BIKES, BRISK::create(), 0.08f, 0.49f)); diff --git a/modules/features2d/test/test_detectors_regression.cpp b/modules/features2d/test/test_detectors_regression.cpp index 733841287a..5bdede7508 100644 --- a/modules/features2d/test/test_detectors_regression.cpp +++ b/modules/features2d/test/test_detectors_regression.cpp @@ -245,6 +245,12 @@ void CV_FeatureDetectorTest::run( int /*start_from*/ ) * Tests registrations * \****************************************************************************************/ +TEST( Features2d_Detector_SIFT, regression ) +{ + CV_FeatureDetectorTest test( "detector-sift", SIFT::create() ); + test.safe_run(); +} + TEST( Features2d_Detector_BRISK, regression ) { CV_FeatureDetectorTest test( "detector-brisk", BRISK::create() ); diff --git a/modules/features2d/test/test_keypoints.cpp b/modules/features2d/test/test_keypoints.cpp index b09d7ebf60..c169c97163 100644 --- a/modules/features2d/test/test_keypoints.cpp +++ b/modules/features2d/test/test_keypoints.cpp @@ -177,4 +177,11 @@ TEST(Features2d_Detector_Keypoints_AKAZE, validation) test_mldb.safe_run(); } +TEST(Features2d_Detector_Keypoints_SIFT, validation) +{ + CV_FeatureDetectorKeypointsTest test(SIFT::create()); + test.safe_run(); +} + + }} // namespace diff --git a/modules/stitching/src/matchers.cpp b/modules/stitching/src/matchers.cpp index 6105c67631..4c6cce8038 100644 --- a/modules/stitching/src/matchers.cpp +++ b/modules/stitching/src/matchers.cpp @@ -51,7 +51,6 @@ using namespace cv::cuda; #ifdef HAVE_OPENCV_XFEATURES2D #include "opencv2/xfeatures2d.hpp" using xfeatures2d::SURF; -using xfeatures2d::SIFT; #else # if defined(_MSC_VER) # pragma warning(disable:4702) // unreachable code @@ -487,14 +486,8 @@ void SurfFeaturesFinder::find(InputArray image, ImageFeatures &features) SiftFeaturesFinder::SiftFeaturesFinder() { -#ifdef HAVE_OPENCV_XFEATURES2D Ptr sift_ = SIFT::create(); - if( !sift_ ) - CV_Error( Error::StsNotImplemented, "OpenCV was built without SIFT support" ); sift = sift_; -#else - CV_Error( Error::StsNotImplemented, "OpenCV was built without SIFT support" ); -#endif } void SiftFeaturesFinder::find(InputArray image, ImageFeatures &features) diff --git a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp index 23ea221eb4..6b1d553330 100644 --- a/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp +++ b/samples/cpp/tutorial_code/calib3d/real_time_pose_estimation/src/Utils.cpp @@ -323,15 +323,8 @@ void createFeatures(const std::string &featureName, int numKeypoints, cv::Ptr