Skip to content

Commit 4970a6d

Browse files
author
AleksandrPanov
committed
add test_aruco_utils and code refactoring/fix tests
1 parent e11a6df commit 4970a6d

File tree

5 files changed

+151
-208
lines changed

5 files changed

+151
-208
lines changed

modules/aruco/include/opencv2/aruco.hpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,14 @@ class CV_EXPORTS_W Board {
294294
CV_WRAP void setIds(InputArray ids);
295295

296296
/// array of object points of all the marker corners in the board
297-
/// each marker include its 4 corners in CCW order. For M markers, the size is Mx4.
297+
/// each marker include its 4 corners in this order:
298+
///- objPoints[i][0] - left-top point of i-th marker
299+
///- objPoints[i][1] - right-top point of i-th marker
300+
///- objPoints[i][2] - right-bottom point of i-th marker
301+
///- objPoints[i][3] - left-bottom point of i-th marker
302+
///
303+
/// Markers are placed in a certain order - row by row, left to right in every row.
304+
/// For M markers, the size is Mx4.
298305
CV_PROP std::vector< std::vector< Point3f > > objPoints;
299306

300307
/// the dictionary of markers employed for this board
@@ -304,6 +311,7 @@ class CV_EXPORTS_W Board {
304311
/// The identifiers refers to the board dictionary
305312
CV_PROP_RW std::vector< int > ids;
306313

314+
/// coordinate of the bottom right corner of the board, is set when calling the function create()
307315
CV_PROP Point3f rightBottomBorder;
308316
};
309317

modules/aruco/src/charuco.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ Ptr<CharucoBoard> CharucoBoard::create(int squaresX, int squaresY, float squareL
163163
res->chessboardCorners.push_back(corner);
164164
}
165165
}
166-
166+
res->rightBottomBorder = Point3f(squaresX * squareLength,
167+
squaresY * squareLength, 0.f);
167168
res->_getNearestMarkerCorners();
168169

169170
return res;
+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// This file is part of OpenCV project.
2+
// It is subject to the license terms in the LICENSE file found in the top-level directory
3+
// of this distribution and at http://opencv.org/license.html.
4+
#include "test_precomp.hpp"
5+
namespace opencv_test {
6+
namespace {
7+
8+
static inline double deg2rad(double deg) { return deg * CV_PI / 180.; }
9+
10+
/**
11+
* @brief Get rvec and tvec from yaw, pitch and distance
12+
*/
13+
static inline void getSyntheticRT(double yaw, double pitch, double distance, Mat& rvec, Mat& tvec) {
14+
rvec = Mat::zeros(3, 1, CV_64FC1);
15+
tvec = Mat::zeros(3, 1, CV_64FC1);
16+
17+
// rotate "scene" in pitch axis (x-axis)
18+
Mat rotPitch(3, 1, CV_64FC1);
19+
rotPitch.at<double>(0) = -pitch;
20+
rotPitch.at<double>(1) = 0;
21+
rotPitch.at<double>(2) = 0;
22+
23+
// rotate "scene" in yaw (y-axis)
24+
Mat rotYaw(3, 1, CV_64FC1);
25+
rotYaw.at<double>(0) = 0;
26+
rotYaw.at<double>(1) = yaw;
27+
rotYaw.at<double>(2) = 0;
28+
29+
// compose both rotations
30+
composeRT(rotPitch, Mat(3, 1, CV_64FC1, Scalar::all(0)), rotYaw,
31+
Mat(3, 1, CV_64FC1, Scalar::all(0)), rvec, tvec);
32+
33+
// Tvec, just move in z (camera) direction the specific distance
34+
tvec.at<double>(0) = 0.;
35+
tvec.at<double>(1) = 0.;
36+
tvec.at<double>(2) = distance;
37+
}
38+
39+
/**
40+
* @brief Project a synthetic marker
41+
*/
42+
static inline void projectMarker(Mat& img, Ptr<aruco::Board> board, int markerIndex, Mat cameraMatrix, Mat rvec, Mat tvec,
43+
int markerBorder) {
44+
// canonical image
45+
Mat markerImg;
46+
const int markerSizePixels = 100;
47+
aruco::drawMarker(board->dictionary, board->ids[markerIndex], markerSizePixels, markerImg, markerBorder);
48+
49+
// projected corners
50+
Mat distCoeffs(5, 1, CV_64FC1, Scalar::all(0));
51+
vector< Point2f > corners;
52+
53+
// get max coordinate of board
54+
Point3f maxCoord = board->rightBottomBorder;
55+
// copy objPoints
56+
vector<Point3f> objPoints = board->objPoints[markerIndex];
57+
// move the marker to the origin
58+
for (size_t i = 0; i < objPoints.size(); i++)
59+
objPoints[i] -= (maxCoord / 2.f);
60+
61+
projectPoints(objPoints, rvec, tvec, cameraMatrix, distCoeffs, corners);
62+
63+
// get perspective transform
64+
vector< Point2f > originalCorners;
65+
originalCorners.push_back(Point2f(0, 0));
66+
originalCorners.push_back(Point2f((float)markerSizePixels, 0));
67+
originalCorners.push_back(Point2f((float)markerSizePixels, (float)markerSizePixels));
68+
originalCorners.push_back(Point2f(0, (float)markerSizePixels));
69+
Mat transformation = getPerspectiveTransform(originalCorners, corners);
70+
71+
// apply transformation
72+
Mat aux;
73+
const char borderValue = 127;
74+
warpPerspective(markerImg, aux, transformation, img.size(), INTER_NEAREST, BORDER_CONSTANT,
75+
Scalar::all(borderValue));
76+
77+
// copy only not-border pixels
78+
for (int y = 0; y < aux.rows; y++) {
79+
for (int x = 0; x < aux.cols; x++) {
80+
if (aux.at< unsigned char >(y, x) == borderValue) continue;
81+
img.at< unsigned char >(y, x) = aux.at< unsigned char >(y, x);
82+
}
83+
}
84+
}
85+
86+
87+
/**
88+
* @brief Get a synthetic image of GridBoard in perspective
89+
*/
90+
static inline Mat projectBoard(Ptr<aruco::GridBoard>& board, Mat cameraMatrix, double yaw, double pitch,
91+
double distance, Size imageSize, int markerBorder) {
92+
93+
Mat rvec, tvec;
94+
getSyntheticRT(yaw, pitch, distance, rvec, tvec);
95+
96+
Mat img = Mat(imageSize, CV_8UC1, Scalar::all(255));
97+
for (unsigned int index = 0; index < board->ids.size(); index++) {
98+
projectMarker(img, board.staticCast<aruco::Board>(), index, cameraMatrix, rvec, tvec, markerBorder);
99+
}
100+
101+
return img;
102+
}
103+
104+
}
105+
106+
}

modules/aruco/test/test_boarddetection.cpp

+2-101
Original file line numberDiff line numberDiff line change
@@ -38,107 +38,10 @@ the use of this software, even if advised of the possibility of such damage.
3838

3939

4040
#include "test_precomp.hpp"
41+
#include "test_aruco_utils.hpp"
4142

4243
namespace opencv_test { namespace {
4344

44-
static double deg2rad(double deg) { return deg * CV_PI / 180.; }
45-
46-
/**
47-
* @brief Get rvec and tvec from yaw, pitch and distance
48-
*/
49-
static void getSyntheticRT(double yaw, double pitch, double distance, Mat &rvec, Mat &tvec) {
50-
51-
rvec = Mat::zeros(3, 1, CV_64FC1);
52-
tvec = Mat::zeros(3, 1, CV_64FC1);
53-
54-
// rotate camera in pitch axis
55-
Mat rotPitch(3, 1, CV_64FC1);
56-
rotPitch.ptr< double >(0)[0] = pitch;
57-
rotPitch.ptr< double >(0)[1] = 0;
58-
rotPitch.ptr< double >(0)[2] = 0;
59-
60-
// rotate camera in yaw axis
61-
Mat rotYaw(3, 1, CV_64FC1);
62-
rotYaw.ptr< double >(0)[0] = 0;
63-
rotYaw.ptr< double >(0)[1] = yaw;
64-
rotYaw.ptr< double >(0)[2] = 0;
65-
66-
// compose both rotations
67-
composeRT(rotPitch, Mat(3, 1, CV_64FC1, Scalar::all(0)), rotYaw,
68-
Mat(3, 1, CV_64FC1, Scalar::all(0)), rvec, tvec);
69-
70-
// Tvec, just move in z (camera) direction the specific distance
71-
tvec.ptr< double >(0)[0] = 0.;
72-
tvec.ptr< double >(0)[1] = 0.;
73-
tvec.ptr< double >(0)[2] = distance;
74-
}
75-
76-
/**
77-
* @brief Project a synthetic marker
78-
*/
79-
static void projectMarker(Mat &img, Ptr<aruco::Board> &board, int markerIndex, Mat cameraMatrix, Mat rvec, Mat tvec,
80-
int markerBorder) {
81-
// canonical image
82-
Mat markerImg;
83-
const int markerSizePixels = 100;
84-
aruco::drawMarker(board->dictionary, board->ids[markerIndex], markerSizePixels, markerImg, markerBorder);
85-
86-
// projected corners
87-
Mat distCoeffs(5, 1, CV_64FC1, Scalar::all(0));
88-
vector< Point2f > corners;
89-
90-
// get max coordinate of board
91-
Point3f maxCoord = board->objPoints.back()[2];
92-
vector<Point3f> objPoints(board->objPoints[markerIndex]);
93-
// move the marker to the origin
94-
for (size_t i = 0; i < objPoints.size(); i++)
95-
objPoints[i] -= maxCoord / 2.0;
96-
97-
projectPoints(objPoints, rvec, tvec, cameraMatrix, distCoeffs, corners);
98-
99-
// get perspective transform
100-
vector< Point2f > originalCorners;
101-
originalCorners.push_back(Point2f(0, 0));
102-
originalCorners.push_back(Point2f((float)markerSizePixels, 0));
103-
originalCorners.push_back(Point2f((float)markerSizePixels, (float)markerSizePixels));
104-
originalCorners.push_back(Point2f(0, (float)markerSizePixels));
105-
Mat transformation = getPerspectiveTransform(originalCorners, corners);
106-
107-
// apply transformation
108-
Mat aux;
109-
const char borderValue = 127;
110-
warpPerspective(markerImg, aux, transformation, img.size(), INTER_NEAREST, BORDER_CONSTANT,
111-
Scalar::all(borderValue));
112-
113-
// copy only not-border pixels
114-
for(int y = 0; y < aux.rows; y++) {
115-
for(int x = 0; x < aux.cols; x++) {
116-
if(aux.at< unsigned char >(y, x) == borderValue) continue;
117-
img.at< unsigned char >(y, x) = aux.at< unsigned char >(y, x);
118-
}
119-
}
120-
}
121-
122-
123-
/**
124-
* @brief Get a synthetic image of GridBoard in perspective
125-
*/
126-
static Mat projectBoard(Ptr<aruco::GridBoard> &board, Mat cameraMatrix, double yaw, double pitch,
127-
double distance, Size imageSize, int markerBorder) {
128-
129-
Mat rvec, tvec;
130-
getSyntheticRT(yaw, pitch, distance, rvec, tvec);
131-
132-
Mat img = Mat(imageSize, CV_8UC1, Scalar::all(255));
133-
for(unsigned int index = 0; index < board->ids.size(); index++) {
134-
projectMarker(img, board.staticCast<aruco::Board>(), index, cameraMatrix, rvec, tvec, markerBorder);
135-
}
136-
137-
return img;
138-
}
139-
140-
141-
14245
/**
14346
* @brief Check pose estimation of aruco board
14447
*/
@@ -169,7 +72,7 @@ void CV_ArucoBoardPose::run(int) {
16972
// for different perspectives
17073
for(double distance = 0.2; distance <= 0.4; distance += 0.2) {
17174
for(int yaw = -60; yaw <= 60; yaw += 30) {
172-
for(int pitch = -0; pitch <= 0; pitch += 30) {
75+
for(int pitch = -60; pitch <= 60; pitch += 30) {
17376
for(unsigned int i = 0; i < gridboard->ids.size(); i++)
17477
gridboard->ids[i] = (iter + int(i)) % 250;
17578
int markerBorder = iter % 2 + 1;
@@ -270,8 +173,6 @@ void CV_ArucoRefine::run(int) {
270173
// create synthetic image
271174
Mat img = projectBoard(gridboard, cameraMatrix, deg2rad(yaw), deg2rad(pitch), distance,
272175
imgSize, markerBorder);
273-
274-
275176
// detect markers
276177
vector< vector< Point2f > > corners, rejected;
277178
vector< int > ids;

0 commit comments

Comments
 (0)