1#include "perf_precomp.hpp"
2#include "opencv2/imgcodecs.hpp"
3#include "opencv2/flann.hpp"
4#include "opencv2/opencv_modules.hpp"
5
6using namespace std;
7using namespace cv;
8using namespace perf;
9using std::tr1::make_tuple;
10using std::tr1::get;
11
12#define SURF_MATCH_CONFIDENCE 0.65f
13#define ORB_MATCH_CONFIDENCE  0.3f
14#define WORK_MEGAPIX 0.6
15
16typedef TestBaseWithParam<string> stitch;
17typedef TestBaseWithParam<string> match;
18typedef std::tr1::tuple<string, int> matchVector_t;
19typedef TestBaseWithParam<matchVector_t> matchVector;
20
21#ifdef HAVE_OPENCV_XFEATURES2D_TODO_FIND_WHY_SURF_IS_NOT_ABLE_TO_STITCH_PANOS
22#define TEST_DETECTORS testing::Values("surf", "orb")
23#else
24#define TEST_DETECTORS testing::Values<string>("orb")
25#endif
26
27PERF_TEST_P(stitch, a123, TEST_DETECTORS)
28{
29    Mat pano;
30
31    vector<Mat> imgs;
32    imgs.push_back( imread( getDataPath("stitching/a1.png") ) );
33    imgs.push_back( imread( getDataPath("stitching/a2.png") ) );
34    imgs.push_back( imread( getDataPath("stitching/a3.png") ) );
35
36    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
37            ? Ptr<detail::FeaturesFinder>(new detail::OrbFeaturesFinder())
38            : Ptr<detail::FeaturesFinder>(new detail::SurfFeaturesFinder());
39
40    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
41            ? makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE)
42            : makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
43
44    declare.time(30 * 20).iterations(20);
45
46    while(next())
47    {
48        Stitcher stitcher = Stitcher::createDefault();
49        stitcher.setFeaturesFinder(featuresFinder);
50        stitcher.setFeaturesMatcher(featuresMatcher);
51        stitcher.setWarper(makePtr<SphericalWarper>());
52        stitcher.setRegistrationResol(WORK_MEGAPIX);
53
54        startTimer();
55        stitcher.stitch(imgs, pano);
56        stopTimer();
57    }
58
59    EXPECT_NEAR(pano.size().width, 1182, 50);
60    EXPECT_NEAR(pano.size().height, 682, 30);
61
62    SANITY_CHECK_NOTHING();
63}
64
65PERF_TEST_P(stitch, b12, TEST_DETECTORS)
66{
67    Mat pano;
68
69    vector<Mat> imgs;
70    imgs.push_back( imread( getDataPath("stitching/b1.png") ) );
71    imgs.push_back( imread( getDataPath("stitching/b2.png") ) );
72
73    Ptr<detail::FeaturesFinder> featuresFinder = GetParam() == "orb"
74            ? Ptr<detail::FeaturesFinder>(new detail::OrbFeaturesFinder())
75            : Ptr<detail::FeaturesFinder>(new detail::SurfFeaturesFinder());
76
77    Ptr<detail::FeaturesMatcher> featuresMatcher = GetParam() == "orb"
78            ? makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE)
79            : makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
80
81    declare.time(30 * 20).iterations(20);
82
83    while(next())
84    {
85        Stitcher stitcher = Stitcher::createDefault();
86        stitcher.setFeaturesFinder(featuresFinder);
87        stitcher.setFeaturesMatcher(featuresMatcher);
88        stitcher.setWarper(makePtr<SphericalWarper>());
89        stitcher.setRegistrationResol(WORK_MEGAPIX);
90
91        startTimer();
92        stitcher.stitch(imgs, pano);
93        stopTimer();
94    }
95
96    Mat pano_small;
97    if (!pano.empty())
98        resize(pano, pano_small, Size(320, 240), 0, 0, INTER_AREA);
99
100    SANITY_CHECK(pano_small, 5);
101}
102
103PERF_TEST_P( match, bestOf2Nearest, TEST_DETECTORS)
104{
105    Mat img1, img1_full = imread( getDataPath("stitching/b1.png") );
106    Mat img2, img2_full = imread( getDataPath("stitching/b2.png") );
107    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
108    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
109    resize(img1_full, img1, Size(), scale1, scale1);
110    resize(img2_full, img2, Size(), scale2, scale2);
111
112    Ptr<detail::FeaturesFinder> finder;
113    Ptr<detail::FeaturesMatcher> matcher;
114    if (GetParam() == "surf")
115    {
116        finder = makePtr<detail::SurfFeaturesFinder>();
117        matcher = makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
118    }
119    else if (GetParam() == "orb")
120    {
121        finder = makePtr<detail::OrbFeaturesFinder>();
122        matcher = makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE);
123    }
124    else
125    {
126        FAIL() << "Unknown 2D features type: " << GetParam();
127    }
128
129    detail::ImageFeatures features1, features2;
130    (*finder)(img1, features1);
131    (*finder)(img2, features2);
132
133    detail::MatchesInfo pairwise_matches;
134
135    declare.in(features1.descriptors, features2.descriptors);
136
137    while(next())
138    {
139        cvflann::seed_random(42);//for predictive FlannBasedMatcher
140        startTimer();
141        (*matcher)(features1, features2, pairwise_matches);
142        stopTimer();
143        matcher->collectGarbage();
144    }
145
146    std::vector<DMatch>& matches = pairwise_matches.matches;
147    if (GetParam() == "orb") matches.resize(0);
148    for(size_t q = 0; q < matches.size(); ++q)
149        if (matches[q].imgIdx < 0) { matches.resize(q); break;}
150    SANITY_CHECK_MATCHES(matches);
151}
152
153PERF_TEST_P( matchVector, bestOf2NearestVectorFeatures, testing::Combine(
154                 TEST_DETECTORS,
155                 testing::Values(2, 4, 8))
156             )
157{
158    Mat img1, img1_full = imread( getDataPath("stitching/b1.png") );
159    Mat img2, img2_full = imread( getDataPath("stitching/b2.png") );
160    float scale1 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img1_full.total()));
161    float scale2 = (float)std::min(1.0, sqrt(WORK_MEGAPIX * 1e6 / img2_full.total()));
162    resize(img1_full, img1, Size(), scale1, scale1);
163    resize(img2_full, img2, Size(), scale2, scale2);
164
165    Ptr<detail::FeaturesFinder> finder;
166    Ptr<detail::FeaturesMatcher> matcher;
167    string detectorName = get<0>(GetParam());
168    int featuresVectorSize = get<1>(GetParam());
169    if (detectorName == "surf")
170    {
171        finder = makePtr<detail::SurfFeaturesFinder>();
172        matcher = makePtr<detail::BestOf2NearestMatcher>(false, SURF_MATCH_CONFIDENCE);
173    }
174    else if (detectorName == "orb")
175    {
176        finder = makePtr<detail::OrbFeaturesFinder>();
177        matcher = makePtr<detail::BestOf2NearestMatcher>(false, ORB_MATCH_CONFIDENCE);
178    }
179    else
180    {
181        FAIL() << "Unknown 2D features type: " << get<0>(GetParam());
182    }
183
184    detail::ImageFeatures features1, features2;
185    (*finder)(img1, features1);
186    (*finder)(img2, features2);
187    vector<detail::ImageFeatures> features;
188    vector<detail::MatchesInfo> pairwise_matches;
189    for(int i = 0; i < featuresVectorSize/2; i++)
190    {
191        features.push_back(features1);
192        features.push_back(features2);
193    }
194
195    declare.time(200);
196    while(next())
197    {
198        cvflann::seed_random(42);//for predictive FlannBasedMatcher
199        startTimer();
200        (*matcher)(features, pairwise_matches);
201        stopTimer();
202        matcher->collectGarbage();
203    }
204
205
206    std::vector<DMatch>& matches = pairwise_matches[detectorName == "surf" ? 1 : 0].matches;
207    for(size_t q = 0; q < matches.size(); ++q)
208        if (matches[q].imgIdx < 0) { matches.resize(q); break;}
209    SANITY_CHECK_MATCHES(matches);
210}
211