Skip to content

Commit 42018ae

Browse files
author
AleksandrPanov
committed
add tile FHD perfomance test
1 parent 449ab66 commit 42018ae

File tree

3 files changed

+169
-136
lines changed

3 files changed

+169
-136
lines changed

modules/aruco/perf/perf_aruco.cpp

Lines changed: 163 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -6,80 +6,30 @@
66
namespace opencv_test {
77
using namespace perf;
88

9-
// useAruco3Detection
10-
// CORNER_REFINE_SUBPIX
11-
typedef tuple <bool, int> ArucoTestParams;
12-
typedef TestBaseWithParam<ArucoTestParams> EstimateAruco;
9+
typedef tuple<bool, int> UseArucoParams;
10+
typedef TestBaseWithParam<UseArucoParams> EstimateAruco;
1311
#define ESTIMATE_PARAMS Combine(Values(false, true), Values(-1))
1412

15-
PERF_TEST_P(EstimateAruco, ArucoFirst, ESTIMATE_PARAMS )
16-
{
17-
string imgPath = cvtest::findDataFile("gboriginal.png", false);
18-
Mat image = imread(imgPath);
19-
string dictPath = cvtest::findDataFile("tutorial_dict.yml", false);
20-
cv::Ptr<cv::aruco::Dictionary> dictionary;
21-
22-
FileStorage fs(dictPath, FileStorage::READ);
23-
if (!aruco::Dictionary::readDictionary(fs.root(), dictionary)) {
24-
cvtest::SkipTestException("Not founded tutorial_dict.yml");
25-
}
26-
27-
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
28-
ArucoTestParams params = GetParam();
29-
detectorParams->useAruco3Detection = get<0>(params);
30-
detectorParams->minMarkerLengthRatioOriginalImg = 0.01f;
31-
32-
vector<int> ids;
33-
vector<vector<Point2f> > corners, rejected;
34-
const size_t N = 35ull;
35-
// corners of ArUco markers with indices 0, 1, ..., 34
36-
const int goldCorners[N][8] = { {252,74, 286,81, 274,102, 238,95}, {295,82, 330,89, 319,111, 282,104},
37-
{338,91, 375,99, 365,121, 327,113}, {383,100, 421,107, 412,130, 374,123},
38-
{429,109, 468,116, 461,139, 421,132}, {235,100, 270,108, 257,130, 220,122},
39-
{279,109, 316,117, 304,140, 266,133}, {324,119, 362,126, 352,150, 313,143},
40-
{371,128, 410,136, 400,161, 360,152}, {418,139, 459,145, 451,170, 410,163},
41-
{216,128, 253,136, 239,161, 200,152}, {262,138, 300,146, 287,172, 248,164},
42-
{309,148, 349,156, 337,183, 296,174}, {358,158, 398,167, 388,194, 346,185},
43-
{407,169, 449,176, 440,205, 397,196}, {196,158, 235,168, 218,195, 179,185},
44-
{243,170, 283,178, 269,206, 228,197}, {293,180, 334,190, 321,218, 279,209},
45-
{343,192, 385,200, 374,230, 330,220}, {395,203, 438,211, 429,241, 384,233},
46-
{174,192, 215,201, 197,231, 156,221}, {223,204, 265,213, 249,244, 207,234},
47-
{275,215, 317,225, 303,257, 259,246}, {327,227, 371,238, 359,270, 313,259},
48-
{381,240, 426,249, 416,282, 369,273}, {151,228, 193,238, 173,271, 130,260},
49-
{202,241, 245,251, 228,285, 183,274}, {255,254, 300,264, 284,299, 238,288},
50-
{310,267, 355,278, 342,314, 295,302}, {366,281, 413,290, 402,327, 353,317},
51-
{125,267, 168,278, 147,314, 102,303}, {178,281, 223,293, 204,330, 157,317},
52-
{233,296, 280,307, 263,346, 214,333}, {291,310, 338,322, 323,363, 274,349},
53-
{349,325, 399,336, 386,378, 335,366} };
54-
map<int, const int*> mapGoldCorners;
55-
for (int i = 0; i < static_cast<int>(N); i++)
56-
mapGoldCorners[i] = goldCorners[i];
57-
58-
TEST_CYCLE() aruco::detectMarkers(image, dictionary, corners, ids, detectorParams, rejected);
59-
SANITY_CHECK_NOTHING();
60-
}
61-
6213
static double deg2rad(double deg) { return deg * CV_PI / 180.; }
6314

6415
class MarkerPainter
6516
{
6617
private:
67-
Size imgMarkerSize;
18+
int imgMarkerSize = 0;
6819
Mat cameraMatrix;
6920
public:
70-
MarkerPainter(const Size& size)
21+
MarkerPainter(const int size)
7122
{
7223
setImgMarkerSize(size);
7324
}
7425

75-
void setImgMarkerSize(const Size& size)
26+
void setImgMarkerSize(const int size)
7627
{
7728
imgMarkerSize = size;
78-
CV_Assert(imgMarkerSize.width == imgMarkerSize.height);
7929
cameraMatrix = Mat::eye(3, 3, CV_64FC1);
80-
cameraMatrix.at<double>(0, 0) = cameraMatrix.at<double>(1, 1) = 650;
81-
cameraMatrix.at<double>(0, 2) = imgMarkerSize.width / 2;
82-
cameraMatrix.at<double>(1, 2) = imgMarkerSize.height / 2;
30+
cameraMatrix.at<double>(0, 0) = cameraMatrix.at<double>(1, 1) = imgMarkerSize;
31+
cameraMatrix.at<double>(0, 2) = imgMarkerSize / 2.0;
32+
cameraMatrix.at<double>(1, 2) = imgMarkerSize / 2.0;
8333
}
8434

8535
static std::pair<Mat, Mat> getSyntheticRT(double yaw, double pitch, double distance)
@@ -133,122 +83,209 @@ class MarkerPainter
13383
const Ptr<aruco::DetectorParameters>& parameters,
13484
const Ptr<aruco::Dictionary>& dictionary)
13585
{
136-
CV_Assert(imgMarkerSize.width == imgMarkerSize.height);
137-
auto marker_corners = std::make_pair(Mat(imgMarkerSize, CV_8UC1, Scalar::all(255)), vector<Point2f>());
86+
auto marker_corners = std::make_pair(Mat(imgMarkerSize, imgMarkerSize, CV_8UC1, Scalar::all(255)), vector<Point2f>());
13887
Mat& img = marker_corners.first;
13988
vector<Point2f>& corners = marker_corners.second;
14089

14190
// canonical image
142-
const int markerSizePixels = static_cast<int>(imgMarkerSize.width/sqrt(2));
91+
const int markerSizePixels = static_cast<int>(imgMarkerSize/sqrt(2.f));
14392
aruco::drawMarker(dictionary, id, markerSizePixels, img, parameters->markerBorderBits);
14493

14594
// get rvec and tvec for the perspective
146-
const double distance = 0.4;
95+
const double distance = 0.1;
14796
auto rvec_tvec = MarkerPainter::getSyntheticRT(yaw, pitch, distance);
14897
Mat& rvec = rvec_tvec.first;
14998
Mat& tvec = rvec_tvec.second;
15099

151100
const float markerLength = 0.05f;
152101
vector<Point3f> markerObjPoints;
153-
markerObjPoints.push_back(Point3f(-markerLength / 2.f, +markerLength / 2.f, 0));
154-
markerObjPoints.push_back(markerObjPoints[0] + Point3f(markerLength, 0, 0));
155-
markerObjPoints.push_back(markerObjPoints[0] + Point3f(markerLength, -markerLength, 0));
156-
markerObjPoints.push_back(markerObjPoints[0] + Point3f(0, -markerLength, 0));
102+
markerObjPoints.emplace_back(Point3f(-markerLength / 2.f, +markerLength / 2.f, 0));
103+
markerObjPoints.emplace_back(markerObjPoints[0] + Point3f(markerLength, 0, 0));
104+
markerObjPoints.emplace_back(markerObjPoints[0] + Point3f(markerLength, -markerLength, 0));
105+
markerObjPoints.emplace_back(markerObjPoints[0] + Point3f(0, -markerLength, 0));
157106

158107
// project markers and draw them
159108
Mat distCoeffs(5, 1, CV_64FC1, Scalar::all(0));
160109
projectPoints(markerObjPoints, rvec, tvec, cameraMatrix, distCoeffs, corners);
161110

162111
vector<Point2f> originalCorners;
163-
originalCorners.push_back(Point2f(0.f, 0.f));
164-
originalCorners.push_back(originalCorners[0]+Point2f((float)markerSizePixels, 0));
165-
originalCorners.push_back(originalCorners[0]+Point2f((float)markerSizePixels, (float)markerSizePixels));
166-
originalCorners.push_back(originalCorners[0]+Point2f(0, (float)markerSizePixels));
112+
originalCorners.emplace_back(Point2f(0.f, 0.f));
113+
originalCorners.emplace_back(originalCorners[0]+Point2f((float)markerSizePixels, 0));
114+
originalCorners.emplace_back(originalCorners[0]+Point2f((float)markerSizePixels, (float)markerSizePixels));
115+
originalCorners.emplace_back(originalCorners[0]+Point2f(0, (float)markerSizePixels));
167116

168117
Mat transformation = getPerspectiveTransform(originalCorners, corners);
169118

170-
warpPerspective(img, img, transformation, imgMarkerSize, INTER_NEAREST, BORDER_CONSTANT,
119+
warpPerspective(img, img, transformation, Size(imgMarkerSize, imgMarkerSize), INTER_NEAREST, BORDER_CONSTANT,
171120
Scalar::all(255));
172121
return marker_corners;
173122
}
174123

175124
std::pair<Mat, map<int, vector<Point2f> > > getProjectMarkersTile(const int numMarkers,
176-
const Ptr<aruco::DetectorParameters>& params,
177-
const Ptr<aruco::Dictionary>& dictionary)
125+
const Ptr<aruco::DetectorParameters>& params,
126+
const Ptr<aruco::Dictionary>& dictionary)
178127
{
179-
params->minDistanceToBorder = 1;
180-
//USE_ARUCO3
181-
params->useAruco3Detection = true;
182-
params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
183-
params->minSideLengthCanonicalImg = 32;
184-
params->markerBorderBits = 1;
185-
//Mat tileImage(imgMarkerSize*numMarkers, CV_8UC1, Scalar::all(255));
186-
Mat tileImage(Size(240, 240), CV_8UC1, Scalar::all(255));
128+
Mat tileImage(imgMarkerSize*numMarkers, imgMarkerSize*numMarkers, CV_8UC1, Scalar::all(255));
187129
map<int, vector<Point2f> > idCorners;
188130

189-
int iter = 0, pitch = 0, yaw = 70;
131+
int iter = 0, pitch = 0, yaw = 0;
190132
for (int i = 0; i < numMarkers; i++)
191133
{
192134
for (int j = 0; j < numMarkers; j++)
193135
{
194-
int currentId = iter % 250;
195-
auto marker_corners = getProjectMarker(currentId, deg2rad(yaw), deg2rad(pitch), params, dictionary);
196-
Point2f startPoint(i*imgMarkerSize.height, j*imgMarkerSize.width);
197-
Mat tmp_roi = tileImage(Rect(startPoint.x, startPoint.y, imgMarkerSize.height, imgMarkerSize.width));
136+
int currentId = iter;
137+
auto marker_corners = getProjectMarker(currentId, deg2rad(70+yaw), deg2rad(pitch), params, dictionary);
138+
Point2i startPoint(j*imgMarkerSize, i*imgMarkerSize);
139+
Mat tmp_roi = tileImage(Rect(startPoint.x, startPoint.y, imgMarkerSize, imgMarkerSize));
198140
marker_corners.first.copyTo(tmp_roi);
199141

200142
for (Point2f& point: marker_corners.second)
201-
point += startPoint;
143+
point += static_cast<Point2f>(startPoint);
202144
idCorners[currentId] = marker_corners.second;
203-
yaw = (yaw + 40) % 120;
204-
currentId++;
145+
auto test = idCorners[currentId];
146+
yaw = (yaw + 10) % 51; // 70+yaw >= 70 && 70+yaw <= 120
147+
iter++;
205148
}
206-
pitch = (pitch + 70) % 360;
149+
pitch = (pitch + 60) % 360;
207150
}
208-
imwrite("tile_test" + std::to_string(iter) + ".jpg", tileImage);
209-
return std::make_pair(std::move(tileImage), std::move(idCorners));
151+
return std::make_pair(tileImage, idCorners);
210152
}
211153
};
212154

213-
TEST(EstimateAruco, ArucoThird)
155+
static inline double getMaxDistance(map<int, vector<Point2f> > &golds, const vector<int>& ids,
156+
const vector<vector<Point2f> >& corners)
157+
{
158+
double distance = 0.;
159+
for (size_t i = 0; i < ids.size(); i++)
160+
{
161+
int id = ids[i];
162+
const auto gold_corners = golds.find(id);
163+
if (gold_corners != golds.end())
164+
for (int c = 0; c < 4; c++)
165+
distance = std::max(distance, cv::norm(gold_corners->second[c] - corners[i][c]));
166+
}
167+
return distance;
168+
}
169+
170+
PERF_TEST_P(EstimateAruco, ArucoFirst, ESTIMATE_PARAMS)
214171
{
215-
//setNumThreads(1);
172+
UseArucoParams testParams = GetParam();
216173
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
217-
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
218-
params->minDistanceToBorder = 1;
174+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
175+
detectorParams->minDistanceToBorder = 1;
176+
detectorParams->markerBorderBits = 1;
177+
detectorParams->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
219178

179+
const int markerSize = 100;
180+
const int numMarkersInRow = 9;
220181
//USE_ARUCO3
221-
params->useAruco3Detection = true;
222-
params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
223-
params->minSideLengthCanonicalImg = 16;
224-
params->markerBorderBits = 1;
225-
MarkerPainter painter(Size(2000, 2000));
226-
//painter.getProjectMarkersTile(2, params, dictionary);
227-
int iter = 0;
228-
// detect from different positions
229-
for(int pitch = 0; pitch < 360; pitch += 70) {
230-
for (int yaw = 70; yaw <= 120; yaw += 40) {
231-
int currentId = iter % 250;
232-
auto marker_corners = painter.getProjectMarker(currentId, deg2rad(yaw), deg2rad(pitch), params, dictionary);
233-
//rectangle(img, groundTruthCorners[0]/4, 3*groundTruthCorners[0]/4, Scalar(0, 0, 0), 4);
234-
//rectangle(img, Point2i(img.rows, img.cols)*0.9, Point2i(img.rows, img.cols)*0.95, Scalar(0, 0, 0), 4);
235-
imwrite("test" + std::to_string(iter) + ".jpg", marker_corners.first);
236-
237-
// detect markers
238-
vector<vector<Point2f> > corners;
239-
vector<int> ids;
240-
aruco::detectMarkers(marker_corners.first, dictionary, corners, ids, params);
241-
// check results
242-
ASSERT_EQ(1ull, ids.size());
243-
ASSERT_EQ(currentId, ids[0]);
244-
for (int c = 0; c < 4; c++)
245-
{
246-
double dist = cv::norm(marker_corners.second[c] - corners[0][c]);
247-
EXPECT_LE(dist, 5.0);
248-
}
249-
iter++;
250-
}
182+
detectorParams->useAruco3Detection = get<0>(testParams);
183+
if (detectorParams->useAruco3Detection) {
184+
detectorParams->minSideLengthCanonicalImg = 32;
185+
detectorParams->minMarkerLengthRatioOriginalImg = 0.04f / numMarkersInRow;
186+
}
187+
MarkerPainter painter(markerSize);
188+
auto image_map = painter.getProjectMarkersTile(numMarkersInRow, detectorParams, dictionary);
189+
190+
// detect markers
191+
vector<vector<Point2f> > corners;
192+
vector<int> ids;
193+
TEST_CYCLE_N(10)
194+
{
195+
aruco::detectMarkers(image_map.first, dictionary, corners, ids, detectorParams);
251196
}
197+
ASSERT_EQ(numMarkersInRow*numMarkersInRow, static_cast<int>(ids.size()));
198+
double maxDistance = getMaxDistance(image_map.second, ids, corners);
199+
ASSERT_LT(maxDistance, 3.);
200+
SANITY_CHECK_NOTHING();
201+
}
202+
203+
PERF_TEST_P(EstimateAruco, ArucoSecond, ESTIMATE_PARAMS)
204+
{
205+
UseArucoParams testParams = GetParam();
206+
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
207+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
208+
detectorParams->minDistanceToBorder = 1;
209+
detectorParams->markerBorderBits = 1;
210+
detectorParams->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
211+
212+
//USE_ARUCO3
213+
detectorParams->useAruco3Detection = get<0>(testParams);
214+
if (detectorParams->useAruco3Detection) {
215+
detectorParams->minSideLengthCanonicalImg = 64;
216+
detectorParams->minMarkerLengthRatioOriginalImg = 0.f;
217+
}
218+
const int markerSize = 200;
219+
const int numMarkersInRow = 11;
220+
MarkerPainter painter(markerSize);
221+
auto image_map = painter.getProjectMarkersTile(numMarkersInRow, detectorParams, dictionary);
222+
223+
// detect markers
224+
vector<vector<Point2f> > corners;
225+
vector<int> ids;
226+
TEST_CYCLE_N(10)
227+
{
228+
aruco::detectMarkers(image_map.first, dictionary, corners, ids, detectorParams);
229+
}
230+
ASSERT_EQ(numMarkersInRow*numMarkersInRow, static_cast<int>(ids.size()));
231+
double maxDistance = getMaxDistance(image_map.second, ids, corners);
232+
ASSERT_LT(maxDistance, 3.);
233+
SANITY_CHECK_NOTHING();
234+
}
235+
236+
struct Aruco3Params
237+
{
238+
bool useAruco3Detection = false;
239+
float minMarkerLengthRatioOriginalImg = 0.f;
240+
int minSideLengthCanonicalImg = 0;
241+
242+
Aruco3Params(bool useAruco3, float minMarkerLen, int minSideLen): useAruco3Detection(useAruco3),
243+
minMarkerLengthRatioOriginalImg(minMarkerLen),
244+
minSideLengthCanonicalImg(minSideLen) {}
245+
friend std::ostream& operator<<(std::ostream& os, const Aruco3Params& d)
246+
{
247+
os << d.useAruco3Detection << " " << d.minMarkerLengthRatioOriginalImg << " " << d.minSideLengthCanonicalImg;
248+
return os;
249+
}
250+
};
251+
typedef tuple<Aruco3Params, pair<int, int>> ArucoTestParams;
252+
253+
typedef TestBaseWithParam<ArucoTestParams> EstimateLargeAruco;
254+
#define ESTIMATE_FHD_PARAMS Combine(Values(Aruco3Params(false, 0.f, 0), Aruco3Params(true, 0.f, 32), \
255+
Aruco3Params(true, 0.015f, 32), Aruco3Params(true, 0.f, 16), Aruco3Params(true, 0.0069f, 16)), \
256+
Values(std::make_pair(1440, 1), std::make_pair(480, 3), std::make_pair(144, 10)))
257+
258+
PERF_TEST_P(EstimateLargeAruco, ArucoFHD, ESTIMATE_FHD_PARAMS)
259+
{
260+
ArucoTestParams testParams = GetParam();
261+
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
262+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
263+
detectorParams->minDistanceToBorder = 1;
264+
detectorParams->markerBorderBits = 1;
265+
detectorParams->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
266+
267+
//USE_ARUCO3
268+
detectorParams->useAruco3Detection = get<0>(testParams).useAruco3Detection;
269+
if (detectorParams->useAruco3Detection) {
270+
detectorParams->minSideLengthCanonicalImg = get<0>(testParams).minSideLengthCanonicalImg;
271+
detectorParams->minMarkerLengthRatioOriginalImg = get<0>(testParams).minMarkerLengthRatioOriginalImg;
272+
}
273+
const int markerSize = get<1>(testParams).first; // 1440 or 480 or 144
274+
const int numMarkersInRow = get<1>(testParams).second; // 1 or 3 or 144
275+
MarkerPainter painter(markerSize); // num pixels is 1440x1440 as in FHD 1920x1080
276+
auto image_map = painter.getProjectMarkersTile(numMarkersInRow, detectorParams, dictionary);
277+
278+
// detect markers
279+
vector<vector<Point2f> > corners;
280+
vector<int> ids;
281+
TEST_CYCLE_N(10)
282+
{
283+
aruco::detectMarkers(image_map.first, dictionary, corners, ids, detectorParams);
284+
}
285+
ASSERT_EQ(numMarkersInRow*numMarkersInRow, static_cast<int>(ids.size()));
286+
double maxDistance = getMaxDistance(image_map.second, ids, corners);
287+
ASSERT_LT(maxDistance, 3.);
288+
SANITY_CHECK_NOTHING();
252289
}
253290

254291
}

modules/aruco/perf/perf_main.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,3 @@
11
#include "perf_precomp.hpp"
22

3-
static void initTests()
4-
{
5-
cvtest::addDataSearchSubDirectory("contrib/aruco");
6-
}
7-
8-
CV_PERF_TEST_MAIN(aruco, initTests())
3+
CV_PERF_TEST_MAIN(aruco)

0 commit comments

Comments
 (0)