1 /*M/////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 4 // 5 // By downloading, copying, installing or using the software you agree to this license. 6 // If you do not agree to this license, do not download, install, 7 // copy or use the software. 8 // 9 // 10 // Intel License Agreement 11 // For Open Source Computer Vision Library 12 // 13 // Copyright (C) 2000, Intel Corporation, all rights reserved. 14 // Third party copyrights are property of their respective owners. 15 // 16 // Redistribution and use in source and binary forms, with or without modification, 17 // are permitted provided that the following conditions are met: 18 // 19 // * Redistribution's of source code must retain the above copyright notice, 20 // this list of conditions and the following disclaimer. 21 // 22 // * Redistribution's in binary form must reproduce the above copyright notice, 23 // this list of conditions and the following disclaimer in the documentation 24 // and/or other materials provided with the distribution. 25 // 26 // * The name of Intel Corporation may not be used to endorse or promote products 27 // derived from this software without specific prior written permission. 28 // 29 // This software is provided by the copyright holders and contributors "as is" and 30 // any express or implied warranties, including, but not limited to, the implied 31 // warranties of merchantability and fitness for a particular purpose are disclaimed. 32 // In no event shall the Intel Corporation or contributors be liable for any direct, 33 // indirect, incidental, special, exemplary, or consequential damages 34 // (including, but not limited to, procurement of substitute goods or services; 35 // loss of use, data, or profits; or business interruption) however caused 36 // and on any theory of liability, whether in contract, strict liability, 37 // or tort (including negligence or otherwise) arising in any way out of 38 // the use of this software, even if advised of the possibility of such damage. 39 // 40 //M*/ 41 42 #include "test_precomp.hpp" 43 #include "opencv2/highgui.hpp" 44 45 using namespace std; 46 using namespace cv; 47 48 const string IMAGE_TSUKUBA = "/features2d/tsukuba.png"; 49 const string IMAGE_BIKES = "/detectors_descriptors_evaluation/images_datasets/bikes/img1.png"; 50 51 #define SHOW_DEBUG_LOG 0 52 53 static 54 Mat generateHomography(float angle) 55 { 56 // angle - rotation around Oz in degrees 57 float angleRadian = static_cast<float>(angle * CV_PI / 180); 58 Mat H = Mat::eye(3, 3, CV_32FC1); 59 H.at<float>(0,0) = H.at<float>(1,1) = std::cos(angleRadian); 60 H.at<float>(0,1) = -std::sin(angleRadian); 61 H.at<float>(1,0) = std::sin(angleRadian); 62 63 return H; 64 } 65 66 static 67 Mat rotateImage(const Mat& srcImage, float angle, Mat& dstImage, Mat& dstMask) 68 { 69 // angle - rotation around Oz in degrees 70 float diag = std::sqrt(static_cast<float>(srcImage.cols * srcImage.cols + srcImage.rows * srcImage.rows)); 71 Mat LUShift = Mat::eye(3, 3, CV_32FC1); // left up 72 LUShift.at<float>(0,2) = static_cast<float>(-srcImage.cols/2); 73 LUShift.at<float>(1,2) = static_cast<float>(-srcImage.rows/2); 74 Mat RDShift = Mat::eye(3, 3, CV_32FC1); // right down 75 RDShift.at<float>(0,2) = diag/2; 76 RDShift.at<float>(1,2) = diag/2; 77 Size sz(cvRound(diag), cvRound(diag)); 78 79 Mat srcMask(srcImage.size(), CV_8UC1, Scalar(255)); 80 81 Mat H = RDShift * generateHomography(angle) * LUShift; 82 warpPerspective(srcImage, dstImage, H, sz); 83 warpPerspective(srcMask, dstMask, H, sz); 84 85 return H; 86 } 87 88 void rotateKeyPoints(const vector<KeyPoint>& src, const Mat& H, float angle, vector<KeyPoint>& dst) 89 { 90 // suppose that H is rotation given from rotateImage() and angle has value passed to rotateImage() 91 vector<Point2f> srcCenters, dstCenters; 92 KeyPoint::convert(src, srcCenters); 93 94 perspectiveTransform(srcCenters, dstCenters, H); 95 96 dst = src; 97 for(size_t i = 0; i < dst.size(); i++) 98 { 99 dst[i].pt = dstCenters[i]; 100 float dstAngle = src[i].angle + angle; 101 if(dstAngle >= 360.f) 102 dstAngle -= 360.f; 103 dst[i].angle = dstAngle; 104 } 105 } 106 107 void scaleKeyPoints(const vector<KeyPoint>& src, vector<KeyPoint>& dst, float scale) 108 { 109 dst.resize(src.size()); 110 for(size_t i = 0; i < src.size(); i++) 111 dst[i] = KeyPoint(src[i].pt.x * scale, src[i].pt.y * scale, src[i].size * scale, src[i].angle); 112 } 113 114 static 115 float calcCirclesIntersectArea(const Point2f& p0, float r0, const Point2f& p1, float r1) 116 { 117 float c = static_cast<float>(norm(p0 - p1)), sqr_c = c * c; 118 119 float sqr_r0 = r0 * r0; 120 float sqr_r1 = r1 * r1; 121 122 if(r0 + r1 <= c) 123 return 0; 124 125 float minR = std::min(r0, r1); 126 float maxR = std::max(r0, r1); 127 if(c + minR <= maxR) 128 return static_cast<float>(CV_PI * minR * minR); 129 130 float cos_halfA0 = (sqr_r0 + sqr_c - sqr_r1) / (2 * r0 * c); 131 float cos_halfA1 = (sqr_r1 + sqr_c - sqr_r0) / (2 * r1 * c); 132 133 float A0 = 2 * acos(cos_halfA0); 134 float A1 = 2 * acos(cos_halfA1); 135 136 return 0.5f * sqr_r0 * (A0 - sin(A0)) + 137 0.5f * sqr_r1 * (A1 - sin(A1)); 138 } 139 140 static 141 float calcIntersectRatio(const Point2f& p0, float r0, const Point2f& p1, float r1) 142 { 143 float intersectArea = calcCirclesIntersectArea(p0, r0, p1, r1); 144 float unionArea = static_cast<float>(CV_PI) * (r0 * r0 + r1 * r1) - intersectArea; 145 return intersectArea / unionArea; 146 } 147 148 static 149 void matchKeyPoints(const vector<KeyPoint>& keypoints0, const Mat& H, 150 const vector<KeyPoint>& keypoints1, 151 vector<DMatch>& matches) 152 { 153 vector<Point2f> points0; 154 KeyPoint::convert(keypoints0, points0); 155 Mat points0t; 156 if(H.empty()) 157 points0t = Mat(points0); 158 else 159 perspectiveTransform(Mat(points0), points0t, H); 160 161 matches.clear(); 162 vector<uchar> usedMask(keypoints1.size(), 0); 163 for(int i0 = 0; i0 < static_cast<int>(keypoints0.size()); i0++) 164 { 165 int nearestPointIndex = -1; 166 float maxIntersectRatio = 0.f; 167 const float r0 = 0.5f * keypoints0[i0].size; 168 for(size_t i1 = 0; i1 < keypoints1.size(); i1++) 169 { 170 if(nearestPointIndex >= 0 && usedMask[i1]) 171 continue; 172 173 float r1 = 0.5f * keypoints1[i1].size; 174 float intersectRatio = calcIntersectRatio(points0t.at<Point2f>(i0), r0, 175 keypoints1[i1].pt, r1); 176 if(intersectRatio > maxIntersectRatio) 177 { 178 maxIntersectRatio = intersectRatio; 179 nearestPointIndex = static_cast<int>(i1); 180 } 181 } 182 183 matches.push_back(DMatch(i0, nearestPointIndex, maxIntersectRatio)); 184 if(nearestPointIndex >= 0) 185 usedMask[nearestPointIndex] = 1; 186 } 187 } 188 189 class DetectorRotationInvarianceTest : public cvtest::BaseTest 190 { 191 public: 192 DetectorRotationInvarianceTest(const Ptr<FeatureDetector>& _featureDetector, 193 float _minKeyPointMatchesRatio, 194 float _minAngleInliersRatio) : 195 featureDetector(_featureDetector), 196 minKeyPointMatchesRatio(_minKeyPointMatchesRatio), 197 minAngleInliersRatio(_minAngleInliersRatio) 198 { 199 CV_Assert(featureDetector); 200 } 201 202 protected: 203 204 void run(int) 205 { 206 const string imageFilename = string(ts->get_data_path()) + IMAGE_TSUKUBA; 207 208 // Read test data 209 Mat image0 = imread(imageFilename), image1, mask1; 210 if(image0.empty()) 211 { 212 ts->printf(cvtest::TS::LOG, "Image %s can not be read.\n", imageFilename.c_str()); 213 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); 214 return; 215 } 216 217 vector<KeyPoint> keypoints0; 218 featureDetector->detect(image0, keypoints0); 219 if(keypoints0.size() < 15) 220 CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); 221 222 const int maxAngle = 360, angleStep = 15; 223 for(int angle = 0; angle < maxAngle; angle += angleStep) 224 { 225 Mat H = rotateImage(image0, static_cast<float>(angle), image1, mask1); 226 227 vector<KeyPoint> keypoints1; 228 featureDetector->detect(image1, keypoints1, mask1); 229 230 vector<DMatch> matches; 231 matchKeyPoints(keypoints0, H, keypoints1, matches); 232 233 int angleInliersCount = 0; 234 235 const float minIntersectRatio = 0.5f; 236 int keyPointMatchesCount = 0; 237 for(size_t m = 0; m < matches.size(); m++) 238 { 239 if(matches[m].distance < minIntersectRatio) 240 continue; 241 242 keyPointMatchesCount++; 243 244 // Check does this inlier have consistent angles 245 const float maxAngleDiff = 15.f; // grad 246 float angle0 = keypoints0[matches[m].queryIdx].angle; 247 float angle1 = keypoints1[matches[m].trainIdx].angle; 248 if(angle0 == -1 || angle1 == -1) 249 CV_Error(Error::StsBadArg, "Given FeatureDetector is not rotation invariant, it can not be tested here.\n"); 250 CV_Assert(angle0 >= 0.f && angle0 < 360.f); 251 CV_Assert(angle1 >= 0.f && angle1 < 360.f); 252 253 float rotAngle0 = angle0 + angle; 254 if(rotAngle0 >= 360.f) 255 rotAngle0 -= 360.f; 256 257 float angleDiff = std::max(rotAngle0, angle1) - std::min(rotAngle0, angle1); 258 angleDiff = std::min(angleDiff, static_cast<float>(360.f - angleDiff)); 259 CV_Assert(angleDiff >= 0.f); 260 bool isAngleCorrect = angleDiff < maxAngleDiff; 261 if(isAngleCorrect) 262 angleInliersCount++; 263 } 264 265 float keyPointMatchesRatio = static_cast<float>(keyPointMatchesCount) / keypoints0.size(); 266 if(keyPointMatchesRatio < minKeyPointMatchesRatio) 267 { 268 ts->printf(cvtest::TS::LOG, "Incorrect keyPointMatchesRatio: curr = %f, min = %f.\n", 269 keyPointMatchesRatio, minKeyPointMatchesRatio); 270 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); 271 return; 272 } 273 274 if(keyPointMatchesCount) 275 { 276 float angleInliersRatio = static_cast<float>(angleInliersCount) / keyPointMatchesCount; 277 if(angleInliersRatio < minAngleInliersRatio) 278 { 279 ts->printf(cvtest::TS::LOG, "Incorrect angleInliersRatio: curr = %f, min = %f.\n", 280 angleInliersRatio, minAngleInliersRatio); 281 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); 282 return; 283 } 284 } 285 #if SHOW_DEBUG_LOG 286 std::cout << "keyPointMatchesRatio - " << keyPointMatchesRatio 287 << " - angleInliersRatio " << static_cast<float>(angleInliersCount) / keyPointMatchesCount << std::endl; 288 #endif 289 } 290 ts->set_failed_test_info( cvtest::TS::OK ); 291 } 292 293 Ptr<FeatureDetector> featureDetector; 294 float minKeyPointMatchesRatio; 295 float minAngleInliersRatio; 296 }; 297 298 class DescriptorRotationInvarianceTest : public cvtest::BaseTest 299 { 300 public: 301 DescriptorRotationInvarianceTest(const Ptr<FeatureDetector>& _featureDetector, 302 const Ptr<DescriptorExtractor>& _descriptorExtractor, 303 int _normType, 304 float _minDescInliersRatio) : 305 featureDetector(_featureDetector), 306 descriptorExtractor(_descriptorExtractor), 307 normType(_normType), 308 minDescInliersRatio(_minDescInliersRatio) 309 { 310 CV_Assert(featureDetector); 311 CV_Assert(descriptorExtractor); 312 } 313 314 protected: 315 316 void run(int) 317 { 318 const string imageFilename = string(ts->get_data_path()) + IMAGE_TSUKUBA; 319 320 // Read test data 321 Mat image0 = imread(imageFilename), image1, mask1; 322 if(image0.empty()) 323 { 324 ts->printf(cvtest::TS::LOG, "Image %s can not be read.\n", imageFilename.c_str()); 325 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); 326 return; 327 } 328 329 vector<KeyPoint> keypoints0; 330 Mat descriptors0; 331 featureDetector->detect(image0, keypoints0); 332 if(keypoints0.size() < 15) 333 CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); 334 descriptorExtractor->compute(image0, keypoints0, descriptors0); 335 336 BFMatcher bfmatcher(normType); 337 338 const float minIntersectRatio = 0.5f; 339 const int maxAngle = 360, angleStep = 15; 340 for(int angle = 0; angle < maxAngle; angle += angleStep) 341 { 342 Mat H = rotateImage(image0, static_cast<float>(angle), image1, mask1); 343 344 vector<KeyPoint> keypoints1; 345 rotateKeyPoints(keypoints0, H, static_cast<float>(angle), keypoints1); 346 Mat descriptors1; 347 descriptorExtractor->compute(image1, keypoints1, descriptors1); 348 349 vector<DMatch> descMatches; 350 bfmatcher.match(descriptors0, descriptors1, descMatches); 351 352 int descInliersCount = 0; 353 for(size_t m = 0; m < descMatches.size(); m++) 354 { 355 const KeyPoint& transformed_p0 = keypoints1[descMatches[m].queryIdx]; 356 const KeyPoint& p1 = keypoints1[descMatches[m].trainIdx]; 357 if(calcIntersectRatio(transformed_p0.pt, 0.5f * transformed_p0.size, 358 p1.pt, 0.5f * p1.size) >= minIntersectRatio) 359 { 360 descInliersCount++; 361 } 362 } 363 364 float descInliersRatio = static_cast<float>(descInliersCount) / keypoints0.size(); 365 if(descInliersRatio < minDescInliersRatio) 366 { 367 ts->printf(cvtest::TS::LOG, "Incorrect descInliersRatio: curr = %f, min = %f.\n", 368 descInliersRatio, minDescInliersRatio); 369 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); 370 return; 371 } 372 #if SHOW_DEBUG_LOG 373 std::cout << "descInliersRatio " << static_cast<float>(descInliersCount) / keypoints0.size() << std::endl; 374 #endif 375 } 376 ts->set_failed_test_info( cvtest::TS::OK ); 377 } 378 379 Ptr<FeatureDetector> featureDetector; 380 Ptr<DescriptorExtractor> descriptorExtractor; 381 int normType; 382 float minDescInliersRatio; 383 }; 384 385 class DetectorScaleInvarianceTest : public cvtest::BaseTest 386 { 387 public: 388 DetectorScaleInvarianceTest(const Ptr<FeatureDetector>& _featureDetector, 389 float _minKeyPointMatchesRatio, 390 float _minScaleInliersRatio) : 391 featureDetector(_featureDetector), 392 minKeyPointMatchesRatio(_minKeyPointMatchesRatio), 393 minScaleInliersRatio(_minScaleInliersRatio) 394 { 395 CV_Assert(featureDetector); 396 } 397 398 protected: 399 400 void run(int) 401 { 402 const string imageFilename = string(ts->get_data_path()) + IMAGE_BIKES; 403 404 // Read test data 405 Mat image0 = imread(imageFilename); 406 if(image0.empty()) 407 { 408 ts->printf(cvtest::TS::LOG, "Image %s can not be read.\n", imageFilename.c_str()); 409 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); 410 return; 411 } 412 413 vector<KeyPoint> keypoints0; 414 featureDetector->detect(image0, keypoints0); 415 if(keypoints0.size() < 15) 416 CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); 417 418 for(int scaleIdx = 1; scaleIdx <= 3; scaleIdx++) 419 { 420 float scale = 1.f + scaleIdx * 0.5f; 421 Mat image1; 422 resize(image0, image1, Size(), 1./scale, 1./scale); 423 424 vector<KeyPoint> keypoints1, osiKeypoints1; // osi - original size image 425 featureDetector->detect(image1, keypoints1); 426 if(keypoints1.size() < 15) 427 CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); 428 429 if(keypoints1.size() > keypoints0.size()) 430 { 431 ts->printf(cvtest::TS::LOG, "Strange behavior of the detector. " 432 "It gives more points count in an image of the smaller size.\n" 433 "original size (%d, %d), keypoints count = %d\n" 434 "reduced size (%d, %d), keypoints count = %d\n", 435 image0.cols, image0.rows, keypoints0.size(), 436 image1.cols, image1.rows, keypoints1.size()); 437 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT); 438 return; 439 } 440 441 scaleKeyPoints(keypoints1, osiKeypoints1, scale); 442 443 vector<DMatch> matches; 444 // image1 is query image (it's reduced image0) 445 // image0 is train image 446 matchKeyPoints(osiKeypoints1, Mat(), keypoints0, matches); 447 448 const float minIntersectRatio = 0.5f; 449 int keyPointMatchesCount = 0; 450 int scaleInliersCount = 0; 451 452 for(size_t m = 0; m < matches.size(); m++) 453 { 454 if(matches[m].distance < minIntersectRatio) 455 continue; 456 457 keyPointMatchesCount++; 458 459 // Check does this inlier have consistent sizes 460 const float maxSizeDiff = 0.8f;//0.9f; // grad 461 float size0 = keypoints0[matches[m].trainIdx].size; 462 float size1 = osiKeypoints1[matches[m].queryIdx].size; 463 CV_Assert(size0 > 0 && size1 > 0); 464 if(std::min(size0, size1) > maxSizeDiff * std::max(size0, size1)) 465 scaleInliersCount++; 466 } 467 468 float keyPointMatchesRatio = static_cast<float>(keyPointMatchesCount) / keypoints1.size(); 469 if(keyPointMatchesRatio < minKeyPointMatchesRatio) 470 { 471 ts->printf(cvtest::TS::LOG, "Incorrect keyPointMatchesRatio: curr = %f, min = %f.\n", 472 keyPointMatchesRatio, minKeyPointMatchesRatio); 473 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); 474 return; 475 } 476 477 if(keyPointMatchesCount) 478 { 479 float scaleInliersRatio = static_cast<float>(scaleInliersCount) / keyPointMatchesCount; 480 if(scaleInliersRatio < minScaleInliersRatio) 481 { 482 ts->printf(cvtest::TS::LOG, "Incorrect scaleInliersRatio: curr = %f, min = %f.\n", 483 scaleInliersRatio, minScaleInliersRatio); 484 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); 485 return; 486 } 487 } 488 #if SHOW_DEBUG_LOG 489 std::cout << "keyPointMatchesRatio - " << keyPointMatchesRatio 490 << " - scaleInliersRatio " << static_cast<float>(scaleInliersCount) / keyPointMatchesCount << std::endl; 491 #endif 492 } 493 ts->set_failed_test_info( cvtest::TS::OK ); 494 } 495 496 Ptr<FeatureDetector> featureDetector; 497 float minKeyPointMatchesRatio; 498 float minScaleInliersRatio; 499 }; 500 501 class DescriptorScaleInvarianceTest : public cvtest::BaseTest 502 { 503 public: 504 DescriptorScaleInvarianceTest(const Ptr<FeatureDetector>& _featureDetector, 505 const Ptr<DescriptorExtractor>& _descriptorExtractor, 506 int _normType, 507 float _minDescInliersRatio) : 508 featureDetector(_featureDetector), 509 descriptorExtractor(_descriptorExtractor), 510 normType(_normType), 511 minDescInliersRatio(_minDescInliersRatio) 512 { 513 CV_Assert(featureDetector); 514 CV_Assert(descriptorExtractor); 515 } 516 517 protected: 518 519 void run(int) 520 { 521 const string imageFilename = string(ts->get_data_path()) + IMAGE_BIKES; 522 523 // Read test data 524 Mat image0 = imread(imageFilename); 525 if(image0.empty()) 526 { 527 ts->printf(cvtest::TS::LOG, "Image %s can not be read.\n", imageFilename.c_str()); 528 ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA); 529 return; 530 } 531 532 vector<KeyPoint> keypoints0; 533 featureDetector->detect(image0, keypoints0); 534 if(keypoints0.size() < 15) 535 CV_Error(Error::StsAssert, "Detector gives too few points in a test image\n"); 536 Mat descriptors0; 537 descriptorExtractor->compute(image0, keypoints0, descriptors0); 538 539 BFMatcher bfmatcher(normType); 540 for(int scaleIdx = 1; scaleIdx <= 3; scaleIdx++) 541 { 542 float scale = 1.f + scaleIdx * 0.5f; 543 544 Mat image1; 545 resize(image0, image1, Size(), 1./scale, 1./scale); 546 547 vector<KeyPoint> keypoints1; 548 scaleKeyPoints(keypoints0, keypoints1, 1.0f/scale); 549 Mat descriptors1; 550 descriptorExtractor->compute(image1, keypoints1, descriptors1); 551 552 vector<DMatch> descMatches; 553 bfmatcher.match(descriptors0, descriptors1, descMatches); 554 555 const float minIntersectRatio = 0.5f; 556 int descInliersCount = 0; 557 for(size_t m = 0; m < descMatches.size(); m++) 558 { 559 const KeyPoint& transformed_p0 = keypoints0[descMatches[m].queryIdx]; 560 const KeyPoint& p1 = keypoints0[descMatches[m].trainIdx]; 561 if(calcIntersectRatio(transformed_p0.pt, 0.5f * transformed_p0.size, 562 p1.pt, 0.5f * p1.size) >= minIntersectRatio) 563 { 564 descInliersCount++; 565 } 566 } 567 568 float descInliersRatio = static_cast<float>(descInliersCount) / keypoints0.size(); 569 if(descInliersRatio < minDescInliersRatio) 570 { 571 ts->printf(cvtest::TS::LOG, "Incorrect descInliersRatio: curr = %f, min = %f.\n", 572 descInliersRatio, minDescInliersRatio); 573 ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); 574 return; 575 } 576 #if SHOW_DEBUG_LOG 577 std::cout << "descInliersRatio " << static_cast<float>(descInliersCount) / keypoints0.size() << std::endl; 578 #endif 579 } 580 ts->set_failed_test_info( cvtest::TS::OK ); 581 } 582 583 Ptr<FeatureDetector> featureDetector; 584 Ptr<DescriptorExtractor> descriptorExtractor; 585 int normType; 586 float minKeyPointMatchesRatio; 587 float minDescInliersRatio; 588 }; 589 590 // Tests registration 591 592 /* 593 * Detector's rotation invariance check 594 */ 595 596 TEST(Features2d_RotationInvariance_Detector_BRISK, regression) 597 { 598 DetectorRotationInvarianceTest test(BRISK::create(), 599 0.32f, 600 0.76f); 601 test.safe_run(); 602 } 603 604 TEST(Features2d_RotationInvariance_Detector_ORB, regression) 605 { 606 DetectorRotationInvarianceTest test(ORB::create(), 607 0.47f, 608 0.76f); 609 test.safe_run(); 610 } 611 612 /* 613 * Descriptors's rotation invariance check 614 */ 615 616 TEST(Features2d_RotationInvariance_Descriptor_BRISK, regression) 617 { 618 Ptr<Feature2D> f2d = BRISK::create(); 619 DescriptorRotationInvarianceTest test(f2d, f2d, f2d->defaultNorm(), 0.99f); 620 test.safe_run(); 621 } 622 623 TEST(Features2d_RotationInvariance_Descriptor_ORB, regression) 624 { 625 Ptr<Feature2D> f2d = ORB::create(); 626 DescriptorRotationInvarianceTest test(f2d, f2d, f2d->defaultNorm(), 0.99f); 627 test.safe_run(); 628 } 629 630 //TEST(Features2d_RotationInvariance_Descriptor_FREAK, regression) 631 //{ 632 // DescriptorRotationInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"), 633 // Algorithm::create<DescriptorExtractor>("Feature2D.FREAK"), 634 // Algorithm::create<DescriptorExtractor>("Feature2D.FREAK")->defaultNorm(), 635 // 0.f); 636 // test.safe_run(); 637 //} 638 639 /* 640 * Detector's scale invariance check 641 */ 642 643 TEST(Features2d_ScaleInvariance_Detector_BRISK, regression) 644 { 645 DetectorScaleInvarianceTest test(BRISK::create(), 0.08f, 0.49f); 646 test.safe_run(); 647 } 648 649 TEST(Features2d_ScaleInvariance_Detector_KAZE, regression) 650 { 651 DetectorScaleInvarianceTest test(KAZE::create(), 0.08f, 0.49f); 652 test.safe_run(); 653 } 654 655 TEST(Features2d_ScaleInvariance_Detector_AKAZE, regression) 656 { 657 DetectorScaleInvarianceTest test(AKAZE::create(), 0.08f, 0.49f); 658 test.safe_run(); 659 } 660 661 //TEST(Features2d_ScaleInvariance_Detector_ORB, regression) 662 //{ 663 // DetectorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"), 664 // 0.22f, 665 // 0.83f); 666 // test.safe_run(); 667 //} 668 669 /* 670 * Descriptor's scale invariance check 671 */ 672 673 //TEST(Features2d_ScaleInvariance_Descriptor_BRISK, regression) 674 //{ 675 // DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.BRISK"), 676 // Algorithm::create<DescriptorExtractor>("Feature2D.BRISK"), 677 // Algorithm::create<DescriptorExtractor>("Feature2D.BRISK")->defaultNorm(), 678 // 0.99f); 679 // test.safe_run(); 680 //} 681 682 //TEST(Features2d_ScaleInvariance_Descriptor_ORB, regression) 683 //{ 684 // DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"), 685 // Algorithm::create<DescriptorExtractor>("Feature2D.ORB"), 686 // Algorithm::create<DescriptorExtractor>("Feature2D.ORB")->defaultNorm(), 687 // 0.01f); 688 // test.safe_run(); 689 //} 690 691 //TEST(Features2d_ScaleInvariance_Descriptor_FREAK, regression) 692 //{ 693 // DescriptorScaleInvarianceTest test(Algorithm::create<FeatureDetector>("Feature2D.ORB"), 694 // Algorithm::create<DescriptorExtractor>("Feature2D.FREAK"), 695 // Algorithm::create<DescriptorExtractor>("Feature2D.FREAK")->defaultNorm(), 696 // 0.01f); 697 // test.safe_run(); 698 //} 699