Skip to content

Commit 73dd278

Browse files
author
AleksandrPanov
committed
add getDistanceVector
1 parent b89230f commit 73dd278

File tree

2 files changed

+75
-125
lines changed

2 files changed

+75
-125
lines changed

modules/aruco/perf/perf_aruco.cpp

Lines changed: 70 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
namespace opencv_test {
77
using namespace perf;
88

9-
typedef tuple<bool, int> ArucoTestParams;
10-
typedef TestBaseWithParam<ArucoTestParams> EstimateAruco;
9+
typedef tuple<bool, int> UseArucoParams;
10+
typedef TestBaseWithParam<UseArucoParams> EstimateAruco;
1111
#define ESTIMATE_PARAMS Combine(Values(false, true), Values(-1))
1212

1313
static double deg2rad(double deg) { return deg * CV_PI / 180.; }
1414

1515
class MarkerPainter
1616
{
1717
private:
18-
int imgMarkerSize;
18+
int imgMarkerSize = 0;
1919
Mat cameraMatrix;
2020
public:
2121
MarkerPainter(const int size)
@@ -28,8 +28,8 @@ class MarkerPainter
2828
imgMarkerSize = size;
2929
cameraMatrix = Mat::eye(3, 3, CV_64FC1);
3030
cameraMatrix.at<double>(0, 0) = cameraMatrix.at<double>(1, 1) = imgMarkerSize;
31-
cameraMatrix.at<double>(0, 2) = imgMarkerSize / 2;
32-
cameraMatrix.at<double>(1, 2) = imgMarkerSize / 2;
31+
cameraMatrix.at<double>(0, 2) = imgMarkerSize / 2.0;
32+
cameraMatrix.at<double>(1, 2) = imgMarkerSize / 2.0;
3333
}
3434

3535
static std::pair<Mat, Mat> getSyntheticRT(double yaw, double pitch, double distance)
@@ -99,20 +99,20 @@ class MarkerPainter
9999

100100
const float markerLength = 0.05f;
101101
vector<Point3f> markerObjPoints;
102-
markerObjPoints.push_back(Point3f(-markerLength / 2.f, +markerLength / 2.f, 0));
103-
markerObjPoints.push_back(markerObjPoints[0] + Point3f(markerLength, 0, 0));
104-
markerObjPoints.push_back(markerObjPoints[0] + Point3f(markerLength, -markerLength, 0));
105-
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));
106106

107107
// project markers and draw them
108108
Mat distCoeffs(5, 1, CV_64FC1, Scalar::all(0));
109109
projectPoints(markerObjPoints, rvec, tvec, cameraMatrix, distCoeffs, corners);
110110

111111
vector<Point2f> originalCorners;
112-
originalCorners.push_back(Point2f(0.f, 0.f));
113-
originalCorners.push_back(originalCorners[0]+Point2f((float)markerSizePixels, 0));
114-
originalCorners.push_back(originalCorners[0]+Point2f((float)markerSizePixels, (float)markerSizePixels));
115-
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));
116116

117117
Mat transformation = getPerspectiveTransform(originalCorners, corners);
118118

@@ -135,12 +135,12 @@ class MarkerPainter
135135
{
136136
int currentId = iter;
137137
auto marker_corners = getProjectMarker(currentId, deg2rad(70+yaw), deg2rad(pitch), params, dictionary);
138-
Point2f startPoint(j*imgMarkerSize, i*imgMarkerSize);
138+
Point2i startPoint(j*imgMarkerSize, i*imgMarkerSize);
139139
Mat tmp_roi = tileImage(Rect(startPoint.x, startPoint.y, imgMarkerSize, imgMarkerSize));
140140
marker_corners.first.copyTo(tmp_roi);
141141

142142
for (Point2f& point: marker_corners.second)
143-
point += startPoint;
143+
point += static_cast<Point2f>(startPoint);
144144
idCorners[currentId] = marker_corners.second;
145145
auto test = idCorners[currentId];
146146
yaw = (yaw + 10) % 51; // 70+yaw >= 70 && 70+yaw <= 120
@@ -152,9 +152,27 @@ class MarkerPainter
152152
}
153153
};
154154

155+
static inline vector<double> getDistanceVector(map<int, vector<Point2f> > &golds, const vector<int>& ids,
156+
const vector<vector<Point2f> >& corners)
157+
{
158+
vector<double> distVector(ids.size(), numeric_limits<double>::max());
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+
{
166+
double distance = cv::norm(gold_corners->second[c] - corners[i][c]);
167+
distVector[i] = distance;
168+
}
169+
}
170+
return distVector;
171+
}
172+
155173
PERF_TEST_P(EstimateAruco, ArucoFirst, ESTIMATE_PARAMS)
156174
{
157-
ArucoTestParams testParams = GetParam();
175+
UseArucoParams testParams = GetParam();
158176
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
159177
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
160178
detectorParams->minDistanceToBorder = 1;
@@ -180,22 +198,13 @@ PERF_TEST_P(EstimateAruco, ArucoFirst, ESTIMATE_PARAMS)
180198
aruco::detectMarkers(image_map.first, dictionary, corners, ids, detectorParams);
181199
}
182200
ASSERT_EQ(numMarkersInRow*numMarkersInRow, ids.size());
183-
for (size_t i = 0; i < ids.size(); i++)
184-
{
185-
int id = ids[i];
186-
for (int c = 0; c < 4; c++)
187-
{
188-
std::vector<Point2f> test = image_map.second[id];
189-
double dist = cv::norm(image_map.second[id][c] - corners[i][c]);
190-
EXPECT_LE(dist, 5.0);
191-
}
192-
}
193-
SANITY_CHECK_NOTHING();
201+
auto distVector = getDistanceVector(image_map.second, ids, corners);
202+
SANITY_CHECK(distVector, 3.0*4.0, ERROR_ABSOLUTE);
194203
}
195204

196205
PERF_TEST_P(EstimateAruco, ArucoSecond, ESTIMATE_PARAMS)
197206
{
198-
ArucoTestParams testParams = GetParam();
207+
UseArucoParams testParams = GetParam();
199208
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
200209
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
201210
detectorParams->minDistanceToBorder = 1;
@@ -221,41 +230,50 @@ PERF_TEST_P(EstimateAruco, ArucoSecond, ESTIMATE_PARAMS)
221230
aruco::detectMarkers(image_map.first, dictionary, corners, ids, detectorParams);
222231
}
223232
ASSERT_EQ(numMarkersInRow*numMarkersInRow, ids.size());
224-
for (size_t i = 0; i < ids.size(); i++)
233+
auto distVector = getDistanceVector(image_map.second, ids, corners);
234+
SANITY_CHECK(distVector, 3.0*4.0, ERROR_ABSOLUTE);
235+
}
236+
237+
struct Aruco3Params
238+
{
239+
bool useAruco3Detection = false;
240+
float minMarkerLengthRatioOriginalImg = 0.f;
241+
int minSideLengthCanonicalImg = 0;
242+
243+
Aruco3Params(bool useAruco3, float minMarkerLen, int minSideLen): useAruco3Detection(useAruco3),
244+
minMarkerLengthRatioOriginalImg(minMarkerLen),
245+
minSideLengthCanonicalImg(minSideLen) {}
246+
friend std::ostream& operator<<(std::ostream& os, const Aruco3Params& d)
225247
{
226-
int id = ids[i];
227-
for (int c = 0; c < 4; c++)
228-
{
229-
std::vector<Point2f> test = image_map.second[id];
230-
double dist = cv::norm(image_map.second[id][c] - corners[i][c]);
231-
EXPECT_LE(dist, 5.0);
232-
}
248+
os << d.useAruco3Detection << " " << d.minMarkerLengthRatioOriginalImg << " " << d.minSideLengthCanonicalImg;
249+
return os;
233250
}
234-
SANITY_CHECK_NOTHING();
235-
}
251+
};
252+
typedef tuple<Aruco3Params, pair<int, int>> ArucoTestParams;
236253

237-
typedef tuple<tuple<bool, float>, int> ArucoLargeTestParams;
238-
typedef TestBaseWithParam<ArucoLargeTestParams> EstimateLargeAruco;
239-
#define ESTIMATE_LARGE_PARAMS Combine(Values(make_tuple(false, 0.f), make_tuple(true, 0.015f)), Values(-1))
254+
typedef TestBaseWithParam<ArucoTestParams> EstimateLargeAruco;
255+
#define ESTIMATE_FHD_PARAMS Combine(Values(Aruco3Params(false, 0.f, 0), Aruco3Params(true, 0.f, 32), \
256+
Aruco3Params(true, 0.015f, 32), Aruco3Params(true, 0.f, 16), Aruco3Params(true, 0.008, 16)), \
257+
Values(std::make_pair(1440, 1), std::make_pair(480, 3), std::make_pair(144, 10)))
240258

241-
PERF_TEST_P(EstimateLargeAruco, ArucoFHD, ESTIMATE_LARGE_PARAMS)
259+
PERF_TEST_P(EstimateLargeAruco, ArucoFHD, ESTIMATE_FHD_PARAMS)
242260
{
243-
ArucoLargeTestParams testParams = GetParam();
261+
ArucoTestParams testParams = GetParam();
244262
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
245263
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
246264
detectorParams->minDistanceToBorder = 1;
247265
detectorParams->markerBorderBits = 1;
248266
detectorParams->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
249267

250268
//USE_ARUCO3
251-
detectorParams->useAruco3Detection = get<0>(get<0>(testParams));
269+
detectorParams->useAruco3Detection = get<0>(testParams).useAruco3Detection;
252270
if (detectorParams->useAruco3Detection) {
253-
detectorParams->minSideLengthCanonicalImg = 32;
254-
detectorParams->minMarkerLengthRatioOriginalImg = get<1>(get<0>(testParams));
271+
detectorParams->minSideLengthCanonicalImg = get<0>(testParams).minSideLengthCanonicalImg;
272+
detectorParams->minMarkerLengthRatioOriginalImg = get<0>(testParams).minMarkerLengthRatioOriginalImg;
255273
}
256-
const int markerSize = 144;
257-
const size_t numMarkersInRow = 10; // 1440*1440 = 1920*1080
258-
MarkerPainter painter(markerSize);
274+
const int markerSize = get<1>(testParams).first; // 1440 or 480 or 144
275+
const int numMarkersInRow = get<1>(testParams).second; // 1 or 3 or 144
276+
MarkerPainter painter(markerSize); // num pixels is 1440x1440 as in FHD 1920x1080
259277
auto image_map = painter.getProjectMarkersTile(numMarkersInRow, detectorParams, dictionary);
260278

261279
// detect markers
@@ -265,78 +283,9 @@ PERF_TEST_P(EstimateLargeAruco, ArucoFHD, ESTIMATE_LARGE_PARAMS)
265283
{
266284
aruco::detectMarkers(image_map.first, dictionary, corners, ids, detectorParams);
267285
}
268-
ASSERT_EQ(numMarkersInRow*numMarkersInRow, ids.size());
269-
for (size_t i = 0; i < ids.size(); i++)
270-
{
271-
int id = ids[i];
272-
for (int c = 0; c < 4; c++)
273-
{
274-
std::vector<Point2f> test = image_map.second[id];
275-
double dist = cv::norm(image_map.second[id][c] - corners[i][c]);
276-
EXPECT_LE(dist, 5.0);
277-
}
278-
}
279-
SANITY_CHECK_NOTHING();
280-
}
281-
282-
// TODO: delete this test
283-
TEST(EstimateAruco, ArucoTryTest)
284-
{
285-
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
286-
Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create();
287-
params->minDistanceToBorder = 1;
288-
289-
//USE_ARUCO3
290-
params->useAruco3Detection = true;
291-
params->cornerRefinementMethod = cv::aruco::CORNER_REFINE_SUBPIX;
292-
params->minSideLengthCanonicalImg = 16;
293-
params->markerBorderBits = 1;
294-
MarkerPainter painter(100);
295-
int iter = 0;
296-
// detect from different positions
297-
for(int pitch = 0; pitch < 360; pitch += 70) {
298-
for (int yaw = 70; yaw <= 120; yaw += 40) {
299-
int currentId = iter % 250;
300-
auto marker_corners = painter.getProjectMarker(currentId, deg2rad(yaw), deg2rad(pitch), params, dictionary);
301-
302-
// detect markers
303-
vector<vector<Point2f> > corners;
304-
vector<int> ids;
305-
aruco::detectMarkers(marker_corners.first, dictionary, corners, ids, params);
306-
// check results
307-
ASSERT_EQ(1ull, ids.size());
308-
ASSERT_EQ(currentId, ids[0]);
309-
for (int c = 0; c < 4; c++)
310-
{
311-
double dist = cv::norm(marker_corners.second[c] - corners[0][c]);
312-
EXPECT_LE(dist, 5.0);
313-
}
314-
iter++;
315-
}
316-
}
317-
params->minMarkerLengthRatioOriginalImg = 0.1f;
318-
iter = 0;
319-
// detect from different positions
320-
for(int pitch = 0; pitch < 360; pitch += 70) {
321-
for (int yaw = 70; yaw <= 120; yaw += 40) {
322-
int currentId = iter % 250;
323-
auto marker_corners = painter.getProjectMarker(currentId, deg2rad(yaw), deg2rad(pitch), params, dictionary);
324-
325-
// detect markers
326-
vector<vector<Point2f> > corners;
327-
vector<int> ids;
328-
aruco::detectMarkers(marker_corners.first, dictionary, corners, ids, params);
329-
// check results
330-
ASSERT_EQ(1ull, ids.size());
331-
ASSERT_EQ(currentId, ids[0]);
332-
for (int c = 0; c < 4; c++)
333-
{
334-
double dist = cv::norm(marker_corners.second[c] - corners[0][c]);
335-
EXPECT_LE(dist, 5.0);
336-
}
337-
iter++;
338-
}
339-
}
286+
ASSERT_EQ(numMarkersInRow*numMarkersInRow, static_cast<int>(ids.size()));
287+
auto distVector = getDistanceVector(image_map.second, ids, corners);
288+
SANITY_CHECK(distVector, 3.0*4.0, ERROR_ABSOLUTE);
340289
}
341290

342291
}

modules/aruco/src/aruco.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ static size_t _findOptPyrImageForCanonicalImg(
738738
/**
739739
* @brief Identify square candidates according to a marker dictionary
740740
*/
741+
741742
static void _identifyCandidates(InputArray _image,
742743
const std::vector<cv::Mat>& _image_pyr,
743744
const std::vector<cv::Size>& _image_pyr_sizes,
@@ -771,8 +772,8 @@ static void _identifyCandidates(InputArray _image,
771772

772773
// implements equation (4)
773774
if (params->useAruco3Detection) {
774-
const int perimeter_in_seg_img = (int)contourS[i].size();
775-
const size_t n = _findOptPyrImageForCanonicalImg(_image_pyr_sizes, _image.size(), perimeter_in_seg_img, min_perimeter);
775+
const int perimeter_scaled_img = (int)contourS[i].size();
776+
const size_t n = _findOptPyrImageForCanonicalImg(_image_pyr_sizes, _image.size(), perimeter_scaled_img, min_perimeter);
776777
const Mat& pyr_img = _image_pyr[n];
777778
const float scale = (float)_image_pyr_sizes[n].width / _image.cols();
778779
validCandidates[i] = _identifyOneCandidate(_dictionary, pyr_img, candidates[i], currId, params, rotated[i], scale);
@@ -1154,8 +1155,8 @@ float detectMarkers(InputArray _image, const Ptr<Dictionary> &_dictionary, Outpu
11541155
const float scale_pyr = 2.f;
11551156
//// Step 1.1: resize image with equation (1) from paper [1]
11561157
if (_params->useAruco3Detection) {
1157-
const float img_area = grey.rows * grey.cols;
1158-
const float min_area_marker = _params->minSideLengthCanonicalImg * _params->minSideLengthCanonicalImg;
1158+
const float img_area = static_cast<float>(grey.rows*grey.cols);
1159+
const float min_area_marker = static_cast<float>(_params->minSideLengthCanonicalImg*_params->minSideLengthCanonicalImg);
11591160
// find max level
11601161
num_levels = static_cast<int>(log2(img_area / min_area_marker)/scale_pyr);
11611162
// the closest pyramid image to the downsampled segmentation image

0 commit comments

Comments
 (0)