perf_matchers.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. #include "perf_precomp.hpp"
  2. #include "opencv2/imgcodecs.hpp"
  3. #include "opencv2/opencv_modules.hpp"
  4. #include "opencv2/flann.hpp"
  5. namespace opencv_test
  6. {
  7. using namespace perf;
  8. typedef TestBaseWithParam<size_t> FeaturesFinderVec;
  9. typedef TestBaseWithParam<string> match;
  10. typedef tuple<string, int> matchVector_t;
  11. typedef TestBaseWithParam<matchVector_t> matchVector;
  12. #define NUMBER_IMAGES testing::Values(1, 5, 20)
  13. #define SURF_MATCH_CONFIDENCE 0.65f
  14. #define ORB_MATCH_CONFIDENCE 0.3f
  15. #define WORK_MEGAPIX 0.6
  16. #if defined(HAVE_OPENCV_XFEATURES2D) && defined(OPENCV_ENABLE_NONFREE)
  17. #define TEST_DETECTORS testing::Values("surf", "orb")
  18. #else
  19. #define TEST_DETECTORS testing::Values<string>("orb")
  20. #endif
  21. PERF_TEST_P(FeaturesFinderVec, ParallelFeaturesFinder, NUMBER_IMAGES)
  22. {
  23. Mat img = imread( getDataPath("stitching/a1.png") );
  24. vector<Mat> imgs(GetParam(), img);
  25. vector<detail::ImageFeatures> features(imgs.size());
  26. Ptr<Feature2D> finder = ORB::create();
  27. TEST_CYCLE()
  28. {
  29. detail::computeImageFeatures(finder, imgs, features);
  30. }
  31. SANITY_CHECK_NOTHING();
  32. }
  33. PERF_TEST_P(FeaturesFinderVec, SerialFeaturesFinder, NUMBER_IMAGES)
  34. {
  35. Mat img = imread( getDataPath("stitching/a1.png") );
  36. vector<Mat> imgs(GetParam(), img);
  37. vector<detail::ImageFeatures> features(imgs.size());
  38. Ptr<Feature2D> finder = ORB::create();
  39. TEST_CYCLE()
  40. {
  41. for (size_t i = 0; i < imgs.size(); ++i)
  42. detail::computeImageFeatures(finder, imgs[i], features[i]);
  43. }
  44. SANITY_CHECK_NOTHING();
  45. }
  46. PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
  47. {
  48. Mat img1, img1_full = imread( getDataPath("stitching/boat1.jpg") );
  49. Mat img2, img2_full = imread( getDataPath("stitching/boat2.jpg") );
  50. float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
  51. float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
  52. resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
  53. resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
  54. Ptr<Feature2D> finder = getFeatureFinder(GetParam());
  55. Ptr<detail::FeaturesMatcher> matcher;
  56. if (GetParam() == "surf")
  57. {
  58. matcher = makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
  59. }
  60. else if (GetParam() == "orb")
  61. {
  62. matcher = makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE);
  63. }
  64. else
  65. {
  66. FAIL() << "Unknown 2D features type: " << GetParam();
  67. }
  68. detail::ImageFeatures features1, features2;
  69. detail::computeImageFeatures(finder, img1, features1);
  70. detail::computeImageFeatures(finder, img2, features2);
  71. detail::MatchesInfo pairwise_matches;
  72. declare.in(features1.descriptors, features2.descriptors);
  73. while(next())
  74. {
  75. cvflann::seed_random(42);//for predictive FlannBasedMatcher
  76. startTimer();
  77. (*matcher)(features1, features2, pairwise_matches);
  78. stopTimer();
  79. matcher->collectGarbage();
  80. }
  81. Mat dist (pairwise_matches.H, Range::all(), Range(2, 3));
  82. Mat R (pairwise_matches.H, Range::all(), Range(0, 2));
  83. // separate transform matrix, use lower error on rotations
  84. SANITY_CHECK(dist, 3., ERROR_ABSOLUTE);
  85. SANITY_CHECK(R, .06, ERROR_ABSOLUTE);
  86. }
  87. PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine(
  88. TEST_DETECTORS,
  89. testing::Values(2, 4, 8))
  90. )
  91. {
  92. Mat img1, img1_full = imread( getDataPath("stitching/boat1.jpg") );
  93. Mat img2, img2_full = imread( getDataPath("stitching/boat2.jpg") );
  94. float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
  95. float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
  96. resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
  97. resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
  98. string detectorName = get<0>(GetParam());
  99. int featuresVectorSize = get<1>(GetParam());
  100. Ptr<Feature2D> finder = getFeatureFinder(detectorName);
  101. Ptr<detail::FeaturesMatcher> matcher;
  102. if (detectorName == "surf")
  103. {
  104. matcher = makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
  105. }
  106. else if (detectorName == "orb")
  107. {
  108. matcher = makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE);
  109. }
  110. else
  111. {
  112. FAIL() << "Unknown 2D features type: " << get<0>(GetParam());
  113. }
  114. detail::ImageFeatures features1, features2;
  115. detail::computeImageFeatures(finder, img1, features1);
  116. detail::computeImageFeatures(finder, img2, features2);
  117. vector<detail::ImageFeatures> features;
  118. vector<detail::MatchesInfo> pairwise_matches;
  119. for(int i = 0; i < featuresVectorSize/2; i++)
  120. {
  121. features.push_back(features1);
  122. features.push_back(features2);
  123. }
  124. declare.time(200);
  125. while(next())
  126. {
  127. cvflann::seed_random(42);//for predictive FlannBasedMatcher
  128. startTimer();
  129. (*matcher)(features, pairwise_matches);
  130. stopTimer();
  131. matcher->collectGarbage();
  132. }
  133. size_t matches_count = 0;
  134. for (size_t i = 0; i < pairwise_matches.size(); ++i)
  135. {
  136. if (pairwise_matches[i].src_img_idx < 0)
  137. continue;
  138. EXPECT_GT(pairwise_matches[i].matches.size(), 95u);
  139. EXPECT_FALSE(pairwise_matches[i].H.empty());
  140. ++matches_count;
  141. }
  142. EXPECT_GT(matches_count, 0u);
  143. SANITY_CHECK_NOTHING();
  144. }
  145. PERF_TEST_P( match, affineBestOf2Nearest, TEST_DETECTORS)
  146. {
  147. Mat img1, img1_full = imread( getDataPath("stitching/s1.jpg") );
  148. Mat img2, img2_full = imread( getDataPath("stitching/s2.jpg") );
  149. float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
  150. float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
  151. resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
  152. resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
  153. Ptr<Feature2D> finder = getFeatureFinder(GetParam());
  154. Ptr<detail::FeaturesMatcher> matcher;
  155. if (GetParam() == "surf")
  156. {
  157. matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, SURF_MATCH_CONFIDENCE);
  158. }
  159. else if (GetParam() == "orb")
  160. {
  161. matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, ORB_MATCH_CONFIDENCE);
  162. }
  163. else
  164. {
  165. FAIL() << "Unknown 2D features type: " << GetParam();
  166. }
  167. detail::ImageFeatures features1, features2;
  168. detail::computeImageFeatures(finder, img1, features1);
  169. detail::computeImageFeatures(finder, img2, features2);
  170. detail::MatchesInfo pairwise_matches;
  171. declare.in(features1.descriptors, features2.descriptors);
  172. while(next())
  173. {
  174. cvflann::seed_random(42);//for predictive FlannBasedMatcher
  175. startTimer();
  176. (*matcher)(features1, features2, pairwise_matches);
  177. stopTimer();
  178. matcher->collectGarbage();
  179. }
  180. // separate rotation and translation in transform matrix
  181. Mat T (pairwise_matches.H, Range(0, 2), Range(2, 3));
  182. Mat R (pairwise_matches.H, Range(0, 2), Range(0, 2));
  183. Mat h (pairwise_matches.H, Range(2, 3), Range::all());
  184. SANITY_CHECK(T, 5, ERROR_ABSOLUTE); // allow 5 pixels diff in translations
  185. SANITY_CHECK(R, .01, ERROR_ABSOLUTE); // rotations must be more precise
  186. // last row should be precisely (0, 0, 1) as it is just added for representation in homogeneous
  187. // coordinates
  188. EXPECT_DOUBLE_EQ(h.at<double>(0), 0.);
  189. EXPECT_DOUBLE_EQ(h.at<double>(1), 0.);
  190. EXPECT_DOUBLE_EQ(h.at<double>(2), 1.);
  191. }
  192. PERF_TEST_P( matchVector, affineBestOf2NearestVectorFeatures, testing::Combine(
  193. TEST_DETECTORS,
  194. testing::Values(2, 4, 8))
  195. )
  196. {
  197. Mat img1, img1_full = imread( getDataPath("stitching/s1.jpg") );
  198. Mat img2, img2_full = imread( getDataPath("stitching/s2.jpg") );
  199. float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
  200. float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
  201. resize(img1_full, img1, Size(), scale1, scale1, INTER_LINEAR_EXACT);
  202. resize(img2_full, img2, Size(), scale2, scale2, INTER_LINEAR_EXACT);
  203. string detectorName = get<0>(GetParam());
  204. int featuresVectorSize = get<1>(GetParam());
  205. Ptr<Feature2D> finder = getFeatureFinder(detectorName);
  206. Ptr<detail::FeaturesMatcher> matcher;
  207. if (detectorName == "surf")
  208. {
  209. matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, SURF_MATCH_CONFIDENCE);
  210. }
  211. else if (detectorName == "orb")
  212. {
  213. matcher = makePtr<detail::AffineBestOf2NearestMatcher>(false, false, ORB_MATCH_CONFIDENCE);
  214. }
  215. else
  216. {
  217. FAIL() << "Unknown 2D features type: " << get<0>(GetParam());
  218. }
  219. detail::ImageFeatures features1, features2;
  220. detail::computeImageFeatures(finder, img1, features1);
  221. detail::computeImageFeatures(finder, img2, features2);
  222. vector<detail::ImageFeatures> features;
  223. vector<detail::MatchesInfo> pairwise_matches;
  224. for(int i = 0; i < featuresVectorSize/2; i++)
  225. {
  226. features.push_back(features1);
  227. features.push_back(features2);
  228. }
  229. declare.time(200);
  230. while(next())
  231. {
  232. cvflann::seed_random(42);//for predictive FlannBasedMatcher
  233. startTimer();
  234. (*matcher)(features, pairwise_matches);
  235. stopTimer();
  236. matcher->collectGarbage();
  237. }
  238. size_t matches_count = 0;
  239. for (size_t i = 0; i < pairwise_matches.size(); ++i)
  240. {
  241. if (pairwise_matches[i].src_img_idx < 0)
  242. continue;
  243. EXPECT_GT(pairwise_matches[i].matches.size(), 150u);
  244. EXPECT_FALSE(pairwise_matches[i].H.empty());
  245. ++matches_count;
  246. }
  247. EXPECT_GT(matches_count, 0u);
  248. SANITY_CHECK_NOTHING();
  249. }
  250. } // namespace