Skip to content

Commit 03dd8c5

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

File tree

5 files changed

+139
-208
lines changed

5 files changed

+139
-208
lines changed

modules/aruco/include/opencv2/aruco.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ 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 CW order. For M markers, the size is Mx4.
298298
CV_PROP std::vector< std::vector< Point3f > > objPoints;
299299

300300
/// the dictionary of markers employed for this board
@@ -304,6 +304,7 @@ class CV_EXPORTS_W Board {
304304
/// The identifiers refers to the board dictionary
305305
CV_PROP_RW std::vector< int > ids;
306306

307+
/// coordinate of the bottom right corner of the board, is set when calling the function create()
307308
CV_PROP Point3f rightBottomBorder;
308309
};
309310

modules/aruco/src/charuco.cpp

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

modules/aruco/test/test_boarddetection.cpp

Lines changed: 2 additions & 101 deletions
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)