test_features2d.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. #include "test_precomp.hpp"
  42. namespace opencv_test { namespace {
  43. const string FEATURES2D_DIR = "features2d";
  44. const string DETECTOR_DIR = FEATURES2D_DIR + "/feature_detectors";
  45. const string DESCRIPTOR_DIR = FEATURES2D_DIR + "/descriptor_extractors";
  46. const string IMAGE_FILENAME = "tsukuba.png";
  47. }} // namespace
  48. #include "features2d/test/test_detectors_regression.impl.hpp"
  49. #include "features2d/test/test_descriptors_regression.impl.hpp"
  50. namespace opencv_test { namespace {
  51. #ifdef OPENCV_ENABLE_NONFREE
  52. TEST( Features2d_Detector_SURF, regression )
  53. {
  54. CV_FeatureDetectorTest test( "detector-surf", SURF::create() );
  55. test.safe_run();
  56. }
  57. #endif
  58. TEST( Features2d_Detector_STAR, regression )
  59. {
  60. CV_FeatureDetectorTest test( "detector-star", StarDetector::create() );
  61. test.safe_run();
  62. }
  63. TEST( Features2d_Detector_Harris_Laplace, regression )
  64. {
  65. CV_FeatureDetectorTest test( "detector-harris-laplace", HarrisLaplaceFeatureDetector::create() );
  66. test.safe_run();
  67. }
  68. TEST( Features2d_Detector_Harris_Laplace_Affine_Keypoint_Invariance, regression )
  69. {
  70. CV_FeatureDetectorTest test( "detector-harris-laplace", AffineFeature2D::create(HarrisLaplaceFeatureDetector::create()));
  71. test.safe_run();
  72. }
  73. TEST( Features2d_Detector_Harris_Laplace_Affine, regression )
  74. {
  75. CV_FeatureDetectorTest test( "detector-harris-laplace-affine", AffineFeature2D::create(HarrisLaplaceFeatureDetector::create()));
  76. test.safe_run();
  77. }
  78. TEST(Features2d_Detector_TBMR_Affine, regression)
  79. {
  80. CV_FeatureDetectorTest test("detector-tbmr-affine", TBMR::create());
  81. test.safe_run();
  82. }
  83. /*
  84. * Descriptors
  85. */
  86. #ifdef OPENCV_ENABLE_NONFREE
  87. TEST( Features2d_DescriptorExtractor_SURF, regression )
  88. {
  89. #ifdef HAVE_OPENCL
  90. bool useOCL = cv::ocl::useOpenCL();
  91. cv::ocl::setUseOpenCL(false);
  92. #endif
  93. CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf", 0.05f,
  94. SURF::create() );
  95. test.safe_run();
  96. #ifdef HAVE_OPENCL
  97. cv::ocl::setUseOpenCL(useOCL);
  98. #endif
  99. }
  100. #ifdef HAVE_OPENCL
  101. TEST( Features2d_DescriptorExtractor_SURF_OCL, regression )
  102. {
  103. bool useOCL = cv::ocl::useOpenCL();
  104. cv::ocl::setUseOpenCL(true);
  105. if(cv::ocl::useOpenCL())
  106. {
  107. CV_DescriptorExtractorTest<L2<float> > test( "descriptor-surf_ocl", 0.05f,
  108. SURF::create() );
  109. test.safe_run();
  110. }
  111. cv::ocl::setUseOpenCL(useOCL);
  112. }
  113. #endif
  114. #endif // NONFREE
  115. TEST( Features2d_DescriptorExtractor_DAISY, regression )
  116. {
  117. CV_DescriptorExtractorTest<L2<float> > test( "descriptor-daisy", 0.05f,
  118. DAISY::create() );
  119. test.safe_run();
  120. }
  121. TEST( Features2d_DescriptorExtractor_FREAK, regression )
  122. {
  123. CV_DescriptorExtractorTest<Hamming> test("descriptor-freak", (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
  124. FREAK::create());
  125. test.safe_run();
  126. }
  127. TEST( Features2d_DescriptorExtractor_BRIEF, regression )
  128. {
  129. CV_DescriptorExtractorTest<Hamming> test( "descriptor-brief", 1,
  130. BriefDescriptorExtractor::create() );
  131. test.safe_run();
  132. }
  133. template <int threshold = 0>
  134. struct LUCIDEqualityDistance
  135. {
  136. typedef unsigned char ValueType;
  137. typedef int ResultType;
  138. ResultType operator()( const unsigned char* a, const unsigned char* b, int size ) const
  139. {
  140. int res = 0;
  141. for (int i = 0; i < size; i++)
  142. {
  143. if (threshold == 0)
  144. res += (a[i] != b[i]) ? 1 : 0;
  145. else
  146. res += abs(a[i] - b[i]) > threshold ? 1 : 0;
  147. }
  148. return res;
  149. }
  150. };
  151. TEST( Features2d_DescriptorExtractor_LUCID, regression )
  152. {
  153. CV_DescriptorExtractorTest< LUCIDEqualityDistance<1/*used blur is not bit-exact*/> > test(
  154. "descriptor-lucid", 2,
  155. LUCID::create(1, 2)
  156. );
  157. test.safe_run();
  158. }
  159. TEST( Features2d_DescriptorExtractor_LATCH, regression )
  160. {
  161. CV_DescriptorExtractorTest<Hamming> test( "descriptor-latch", 1,
  162. LATCH::create(32, true, 3, 0) );
  163. test.safe_run();
  164. }
  165. TEST(Features2d_DescriptorExtractor_BEBLID, regression )
  166. {
  167. CV_DescriptorExtractorTest<Hamming> test("descriptor-beblid", 1,
  168. BEBLID::create(6.75));
  169. test.safe_run();
  170. }
  171. #ifdef OPENCV_XFEATURES2D_HAS_VGG_DATA
  172. TEST( Features2d_DescriptorExtractor_VGG, regression )
  173. {
  174. CV_DescriptorExtractorTest<L2<float> > test( "descriptor-vgg", 0.03f,
  175. VGG::create() );
  176. test.safe_run();
  177. }
  178. #endif // OPENCV_XFEATURES2D_HAS_VGG_DATA
  179. #ifdef OPENCV_XFEATURES2D_HAS_BOOST_DATA
  180. TEST( Features2d_DescriptorExtractor_BGM, regression )
  181. {
  182. CV_DescriptorExtractorTest<Hamming> test( "descriptor-boostdesc-bgm",
  183. (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
  184. BoostDesc::create(BoostDesc::BGM) );
  185. test.safe_run();
  186. }
  187. TEST( Features2d_DescriptorExtractor_BGM_HARD, regression )
  188. {
  189. CV_DescriptorExtractorTest<Hamming> test( "descriptor-boostdesc-bgm_hard",
  190. (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
  191. BoostDesc::create(BoostDesc::BGM_HARD) );
  192. test.safe_run();
  193. }
  194. TEST( Features2d_DescriptorExtractor_BGM_BILINEAR, regression )
  195. {
  196. CV_DescriptorExtractorTest<Hamming> test( "descriptor-boostdesc-bgm_bilinear",
  197. (CV_DescriptorExtractorTest<Hamming>::DistanceType)15.f,
  198. BoostDesc::create(BoostDesc::BGM_BILINEAR) );
  199. test.safe_run();
  200. }
  201. TEST( Features2d_DescriptorExtractor_LBGM, regression )
  202. {
  203. CV_DescriptorExtractorTest<L2<float> > test( "descriptor-boostdesc-lbgm",
  204. 1.0f,
  205. BoostDesc::create(BoostDesc::LBGM) );
  206. test.safe_run();
  207. }
  208. TEST( Features2d_DescriptorExtractor_BINBOOST_64, regression )
  209. {
  210. CV_DescriptorExtractorTest<Hamming> test( "descriptor-boostdesc-binboost_64",
  211. (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
  212. BoostDesc::create(BoostDesc::BINBOOST_64) );
  213. test.safe_run();
  214. }
  215. TEST( Features2d_DescriptorExtractor_BINBOOST_128, regression )
  216. {
  217. CV_DescriptorExtractorTest<Hamming> test( "descriptor-boostdesc-binboost_128",
  218. (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
  219. BoostDesc::create(BoostDesc::BINBOOST_128) );
  220. test.safe_run();
  221. }
  222. TEST( Features2d_DescriptorExtractor_BINBOOST_256, regression )
  223. {
  224. CV_DescriptorExtractorTest<Hamming> test( "descriptor-boostdesc-binboost_256",
  225. (CV_DescriptorExtractorTest<Hamming>::DistanceType)12.f,
  226. BoostDesc::create(BoostDesc::BINBOOST_256) );
  227. test.safe_run();
  228. }
  229. #endif // OPENCV_XFEATURES2D_HAS_BOOST_DATA
  230. #ifdef OPENCV_ENABLE_NONFREE
  231. TEST(Features2d_BruteForceDescriptorMatcher_knnMatch, regression)
  232. {
  233. const int sz = 100;
  234. const int k = 3;
  235. Ptr<DescriptorExtractor> ext = SURF::create();
  236. ASSERT_TRUE(ext);
  237. Ptr<FeatureDetector> det = SURF::create();
  238. //"%YAML:1.0\nhessianThreshold: 8000.\noctaves: 3\noctaveLayers: 4\nupright: 0\n"
  239. ASSERT_TRUE(det);
  240. Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce");
  241. ASSERT_TRUE(matcher);
  242. Mat imgT(256, 256, CV_8U, Scalar(255));
  243. line(imgT, Point(20, sz/2), Point(sz-21, sz/2), Scalar(100), 2);
  244. line(imgT, Point(sz/2, 20), Point(sz/2, sz-21), Scalar(100), 2);
  245. vector<KeyPoint> kpT;
  246. kpT.push_back( KeyPoint(50, 50, 16, 0, 20000, 1, -1) );
  247. kpT.push_back( KeyPoint(42, 42, 16, 160, 10000, 1, -1) );
  248. Mat descT;
  249. ext->compute(imgT, kpT, descT);
  250. Mat imgQ(256, 256, CV_8U, Scalar(255));
  251. line(imgQ, Point(30, sz/2), Point(sz-31, sz/2), Scalar(100), 3);
  252. line(imgQ, Point(sz/2, 30), Point(sz/2, sz-31), Scalar(100), 3);
  253. vector<KeyPoint> kpQ;
  254. det->detect(imgQ, kpQ);
  255. Mat descQ;
  256. ext->compute(imgQ, kpQ, descQ);
  257. vector<vector<DMatch> > matches;
  258. matcher->knnMatch(descQ, descT, matches, k);
  259. //cout << "\nBest " << k << " matches to " << descT.rows << " train desc-s." << endl;
  260. ASSERT_EQ(descQ.rows, static_cast<int>(matches.size()));
  261. for(size_t i = 0; i<matches.size(); i++)
  262. {
  263. //cout << "\nmatches[" << i << "].size()==" << matches[i].size() << endl;
  264. ASSERT_GE(min(k, descT.rows), static_cast<int>(matches[i].size()));
  265. for(size_t j = 0; j<matches[i].size(); j++)
  266. {
  267. //cout << "\t" << matches[i][j].queryIdx << " -> " << matches[i][j].trainIdx << endl;
  268. ASSERT_EQ(matches[i][j].queryIdx, static_cast<int>(i));
  269. }
  270. }
  271. }
  272. #endif
  273. class CV_DetectPlanarTest : public cvtest::BaseTest
  274. {
  275. public:
  276. CV_DetectPlanarTest(const string& _fname, int _min_ninliers, const Ptr<Feature2D>& _f2d)
  277. : fname(_fname), min_ninliers(_min_ninliers), f2d(_f2d) {}
  278. protected:
  279. void run(int)
  280. {
  281. if(f2d.empty())
  282. return;
  283. string path = string(ts->get_data_path()) + "detectors_descriptors_evaluation/planar/";
  284. string imgname1 = path + "box.png";
  285. string imgname2 = path + "box_in_scene.png";
  286. Mat img1 = imread(imgname1, 0);
  287. Mat img2 = imread(imgname2, 0);
  288. if( img1.empty() || img2.empty() )
  289. {
  290. ts->printf( cvtest::TS::LOG, "missing %s and/or %s\n", imgname1.c_str(), imgname2.c_str());
  291. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
  292. return;
  293. }
  294. vector<KeyPoint> kpt1, kpt2;
  295. Mat d1, d2;
  296. #ifdef HAVE_OPENCL
  297. if (cv::ocl::useOpenCL())
  298. {
  299. cv::UMat uimg1;
  300. img1.copyTo(uimg1);
  301. f2d->detectAndCompute(uimg1, Mat(), kpt1, d1);
  302. f2d->detectAndCompute(uimg1, Mat(), kpt2, d2);
  303. }
  304. else
  305. #endif
  306. {
  307. f2d->detectAndCompute(img1, Mat(), kpt1, d1);
  308. f2d->detectAndCompute(img1, Mat(), kpt2, d2);
  309. }
  310. for( size_t i = 0; i < kpt1.size(); i++ )
  311. CV_Assert(kpt1[i].response > 0 );
  312. for( size_t i = 0; i < kpt2.size(); i++ )
  313. CV_Assert(kpt2[i].response > 0 );
  314. vector<DMatch> matches;
  315. BFMatcher(f2d->defaultNorm(), true).match(d1, d2, matches);
  316. vector<Point2f> pt1, pt2;
  317. for( size_t i = 0; i < matches.size(); i++ ) {
  318. pt1.push_back(kpt1[matches[i].queryIdx].pt);
  319. pt2.push_back(kpt2[matches[i].trainIdx].pt);
  320. }
  321. Mat inliers, H = findHomography(pt1, pt2, RANSAC, 10, inliers);
  322. int ninliers = countNonZero(inliers);
  323. if( ninliers < min_ninliers )
  324. {
  325. ts->printf( cvtest::TS::LOG, "too little inliers (%d) vs expected %d\n", ninliers, min_ninliers);
  326. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_TEST_DATA );
  327. return;
  328. }
  329. }
  330. string fname;
  331. int min_ninliers;
  332. Ptr<Feature2D> f2d;
  333. };
  334. TEST(Features2d_SIFTHomographyTest, regression) { CV_DetectPlanarTest test("SIFT", 80, SIFT::create()); test.safe_run(); }
  335. #ifdef OPENCV_ENABLE_NONFREE
  336. TEST(Features2d_SURFHomographyTest, regression) { CV_DetectPlanarTest test("SURF", 80, SURF::create()); test.safe_run(); }
  337. #endif
  338. class FeatureDetectorUsingMaskTest : public cvtest::BaseTest
  339. {
  340. public:
  341. FeatureDetectorUsingMaskTest(const Ptr<FeatureDetector>& featureDetector) :
  342. featureDetector_(featureDetector)
  343. {
  344. CV_Assert(featureDetector_);
  345. }
  346. protected:
  347. void run(int)
  348. {
  349. const int nStepX = 2;
  350. const int nStepY = 2;
  351. const string imageFilename = string(ts->get_data_path()) + "/features2d/tsukuba.png";
  352. Mat image = imread(imageFilename);
  353. if(image.empty())
  354. {
  355. ts->printf(cvtest::TS::LOG, "Image %s can not be read.\n", imageFilename.c_str());
  356. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
  357. return;
  358. }
  359. Mat mask(image.size(), CV_8U);
  360. const int stepX = image.size().width / nStepX;
  361. const int stepY = image.size().height / nStepY;
  362. vector<KeyPoint> keyPoints;
  363. vector<Point2f> points;
  364. for(int i=0; i<nStepX; ++i)
  365. for(int j=0; j<nStepY; ++j)
  366. {
  367. mask.setTo(0);
  368. Rect whiteArea(i * stepX, j * stepY, stepX, stepY);
  369. mask(whiteArea).setTo(255);
  370. featureDetector_->detect(image, keyPoints, mask);
  371. KeyPoint::convert(keyPoints, points);
  372. for(size_t k=0; k<points.size(); ++k)
  373. {
  374. if ( !whiteArea.contains(points[k]) )
  375. {
  376. ts->printf(cvtest::TS::LOG, "The feature point is outside of the mask.");
  377. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  378. return;
  379. }
  380. }
  381. }
  382. ts->set_failed_test_info( cvtest::TS::OK );
  383. }
  384. Ptr<FeatureDetector> featureDetector_;
  385. };
  386. TEST(Features2d_SIFT_using_mask, regression)
  387. {
  388. FeatureDetectorUsingMaskTest test(SIFT::create());
  389. test.safe_run();
  390. }
  391. #ifdef OPENCV_ENABLE_NONFREE
  392. TEST(DISABLED_Features2d_SURF_using_mask, regression)
  393. {
  394. FeatureDetectorUsingMaskTest test(SURF::create());
  395. test.safe_run();
  396. }
  397. #endif // NONFREE
  398. }} // namespace