Skip to content

Commit 0f44c79

Browse files
add axes test, remove drawAxis(), update tutorial
1 parent c8936ad commit 0f44c79

27 files changed

+100
-102
lines changed

modules/aruco/include/opencv2/aruco.hpp

+5-25
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,9 @@ CV_EXPORTS_W void detectMarkers(InputArray image, const Ptr<Dictionary> &diction
250250
* The marker corrdinate system is centered on the middle of the marker, with the Z axis
251251
* perpendicular to the marker plane.
252252
* The coordinates of the four corners of the marker in its own coordinate system are:
253-
* (-markerLength/2, markerLength/2, 0), (markerLength/2, markerLength/2, 0),
254-
* (markerLength/2, -markerLength/2, 0), (-markerLength/2, -markerLength/2, 0)
253+
* (0, 0, 0), (markerLength, 0, 0),
254+
* (markerLength, markerLength, 0), (0, markerLength, 0)
255+
* @sa use cv::drawFrameAxes to get world coordinate system axis for object points
255256
*/
256257
CV_EXPORTS_W void estimatePoseSingleMarkers(InputArrayOfArrays corners, float markerLength,
257258
InputArray cameraMatrix, InputArray distCoeffs,
@@ -412,6 +413,7 @@ class CV_EXPORTS_W GridBoard : public Board {
412413
* Input markers that are not included in the board layout are ignored.
413414
* The function returns the number of markers from the input employed for the board pose estimation.
414415
* Note that returning a 0 means the pose has not been estimated.
416+
* @sa use cv::drawFrameAxes to get world coordinate system axis for object points
415417
*/
416418
CV_EXPORTS_W int estimatePoseBoard(InputArrayOfArrays corners, InputArray ids, const Ptr<Board> &board,
417419
InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec,
@@ -476,36 +478,14 @@ CV_EXPORTS_W void refineDetectedMarkers(
476478
* Given an array of detected marker corners and its corresponding ids, this functions draws
477479
* the markers in the image. The marker borders are painted and the markers identifiers if provided.
478480
* Useful for debugging purposes.
481+
*
479482
*/
480483
CV_EXPORTS_W void drawDetectedMarkers(InputOutputArray image, InputArrayOfArrays corners,
481484
InputArray ids = noArray(),
482485
Scalar borderColor = Scalar(0, 255, 0));
483486

484487

485488

486-
/**
487-
* @brief Draw coordinate system axis from pose estimation
488-
*
489-
* @param image input/output image. It must have 1 or 3 channels. The number of channels is not
490-
* altered.
491-
* @param cameraMatrix input 3x3 floating-point camera matrix
492-
* \f$A = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{1}\f$
493-
* @param distCoeffs vector of distortion coefficients
494-
* \f$(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6],[s_1, s_2, s_3, s_4]])\f$ of 4, 5, 8 or 12 elements
495-
* @param rvec rotation vector of the coordinate system that will be drawn. (@sa Rodrigues).
496-
* @param tvec translation vector of the coordinate system that will be drawn.
497-
* @param length length of the painted axis in the same unit than tvec (usually in meters)
498-
*
499-
* Given the pose estimation of a marker or board, this function draws the axis of the world
500-
* coordinate system, i.e. the system centered on the marker/board. Useful for debugging purposes.
501-
*
502-
* @deprecated use cv::drawFrameAxes
503-
*/
504-
CV_EXPORTS_W void drawAxis(InputOutputArray image, InputArray cameraMatrix, InputArray distCoeffs,
505-
InputArray rvec, InputArray tvec, float length, int thickness=3);
506-
507-
508-
509489
/**
510490
* @brief Draw a canonical marker image
511491
*

modules/aruco/include/opencv2/aruco/charuco.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ CV_EXPORTS_W int interpolateCornersCharuco(InputArrayOfArrays markerCorners, Inp
181181
* This function estimates a Charuco board pose from some detected corners.
182182
* The function checks if the input corners are enough and valid to perform pose estimation.
183183
* If pose estimation is valid, returns true, else returns false.
184+
* @sa use cv::drawFrameAxes to get world coordinate system axis for object points
184185
*/
185186
CV_EXPORTS_W bool estimatePoseCharucoBoard(InputArray charucoCorners, InputArray charucoIds,
186187
const Ptr<CharucoBoard> &board, InputArray cameraMatrix,
@@ -275,6 +276,7 @@ CV_EXPORTS_W double calibrateCameraCharuco(
275276
* diamond.
276277
* @param cameraMatrix Optional camera calibration matrix.
277278
* @param distCoeffs Optional camera distortion coefficients.
279+
* @param dictionary dictionary of markers indicating the type of markers.
278280
*
279281
* This function detects Diamond markers from the previous detected ArUco markers. The diamonds
280282
* are returned in the diamondCorners and diamondIds parameters. If camera calibration parameters
@@ -286,7 +288,7 @@ CV_EXPORTS_W void detectCharucoDiamond(InputArray image, InputArrayOfArrays mark
286288
OutputArrayOfArrays diamondCorners, OutputArray diamondIds,
287289
InputArray cameraMatrix = noArray(),
288290
InputArray distCoeffs = noArray(),
289-
Ptr<Dictionary> dict = getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME(0)));
291+
Ptr<Dictionary> dictionary = getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME(0)));
290292

291293

292294

modules/aruco/samples/calibrate_camera.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ int main(int argc, char *argv[]) {
101101
if(parser.get<bool>("zt")) calibrationFlags |= CALIB_ZERO_TANGENT_DIST;
102102
if(parser.get<bool>("pc")) calibrationFlags |= CALIB_FIX_PRINCIPAL_POINT;
103103

104-
Ptr<aruco::DetectorParameters> detectorParams;
104+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
105105
if(parser.has("dp")) {
106106
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
107107
bool readOk = aruco::DetectorParameters::readDetectorParameters(fs.root(), detectorParams);

modules/aruco/samples/calibrate_camera_charuco.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ int main(int argc, char *argv[]) {
102102
if(parser.get<bool>("zt")) calibrationFlags |= CALIB_ZERO_TANGENT_DIST;
103103
if(parser.get<bool>("pc")) calibrationFlags |= CALIB_FIX_PRINCIPAL_POINT;
104104

105-
Ptr<aruco::DetectorParameters> detectorParams;
105+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
106106
if(parser.has("dp")) {
107107
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
108108
bool readOk = aruco::DetectorParameters::readDetectorParameters(fs.root(), detectorParams);

modules/aruco/samples/detect_board.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ int main(int argc, char *argv[]) {
9797
}
9898
}
9999

100-
Ptr<aruco::DetectorParameters> detectorParams;
100+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
101101
if(parser.has("dp")) {
102102
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
103103
bool readOk = aruco::DetectorParameters::readDetectorParameters(fs.root(), detectorParams);
@@ -199,7 +199,7 @@ int main(int argc, char *argv[]) {
199199
aruco::drawDetectedMarkers(imageCopy, rejected, noArray(), Scalar(100, 0, 255));
200200

201201
if(markersOfBoardDetected > 0)
202-
aruco::drawAxis(imageCopy, camMatrix, distCoeffs, rvec, tvec, axisLength);
202+
cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvec, tvec, axisLength);
203203

204204
imshow("out", imageCopy);
205205
char key = (char)waitKey(waitTime);

modules/aruco/samples/detect_board_charuco.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ int main(int argc, char *argv[]) {
9999
}
100100
}
101101

102-
Ptr<aruco::DetectorParameters> detectorParams;
102+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
103103
if(parser.has("dp")) {
104104
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
105105
bool readOk = aruco::DetectorParameters::readDetectorParameters(fs.root(), detectorParams);
@@ -213,7 +213,7 @@ int main(int argc, char *argv[]) {
213213
}
214214

215215
if(validPose)
216-
aruco::drawAxis(imageCopy, camMatrix, distCoeffs, rvec, tvec, axisLength);
216+
cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvec, tvec, axisLength);
217217

218218
imshow("out", imageCopy);
219219
char key = (char)waitKey(waitTime);

modules/aruco/samples/detect_diamonds.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ int main(int argc, char *argv[]) {
8787
bool autoScale = parser.has("as");
8888
float autoScaleFactor = autoScale ? parser.get<float>("as") : 1.f;
8989

90-
Ptr<aruco::DetectorParameters> detectorParams;
90+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
9191
if(parser.has("dp")) {
9292
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
9393
bool readOk = aruco::DetectorParameters::readDetectorParameters(fs.root(), detectorParams);
@@ -219,8 +219,8 @@ int main(int argc, char *argv[]) {
219219

220220
if(estimatePose) {
221221
for(unsigned int i = 0; i < diamondIds.size(); i++)
222-
aruco::drawAxis(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i],
223-
squareLength * 0.5f);
222+
cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i],
223+
squareLength * 1.1f);
224224
}
225225
}
226226

modules/aruco/samples/detect_markers.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
8080
bool estimatePose = parser.has("c");
8181
float markerLength = parser.get<float>("l");
8282

83-
Ptr<aruco::DetectorParameters> detectorParams;
83+
Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
8484
if(parser.has("dp")) {
8585
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
8686
bool readOk = aruco::DetectorParameters::readDetectorParameters(fs.root(), detectorParams);
@@ -179,8 +179,7 @@ int main(int argc, char *argv[]) {
179179

180180
if(estimatePose) {
181181
for(unsigned int i = 0; i < ids.size(); i++)
182-
aruco::drawAxis(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i],
183-
markerLength * 0.5f);
182+
cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i], markerLength * 1.5f, 2);
184183
}
185184
}
186185

modules/aruco/samples/tutorial_charuco_create_detect.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static inline void detectCharucoBoardWithCalibrationPose()
7272
//! [pose]
7373
// if charuco pose is valid
7474
if (valid)
75-
cv::aruco::drawAxis(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1f);
75+
cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1f);
7676
}
7777
}
7878
cv::imshow("out", imageCopy);

modules/aruco/src/aruco.cpp

+5-23
Original file line numberDiff line numberDiff line change
@@ -811,11 +811,11 @@ static void _getSingleMarkerObjectPoints(float markerLength, OutputArray _objPoi
811811

812812
_objPoints.create(4, 1, CV_32FC3);
813813
Mat objPoints = _objPoints.getMat();
814-
// set coordinate system in the middle of the marker, with Z pointing out
815-
objPoints.ptr< Vec3f >(0)[0] = Vec3f(-markerLength / 2.f, markerLength / 2.f, 0);
816-
objPoints.ptr< Vec3f >(0)[1] = Vec3f(markerLength / 2.f, markerLength / 2.f, 0);
817-
objPoints.ptr< Vec3f >(0)[2] = Vec3f(markerLength / 2.f, -markerLength / 2.f, 0);
818-
objPoints.ptr< Vec3f >(0)[3] = Vec3f(-markerLength / 2.f, -markerLength / 2.f, 0);
814+
// set coordinate system in the top-left corner of the marker, with Z pointing out
815+
objPoints.ptr< Vec3f >(0)[0] = Vec3f(0.f, 0.f, 0);
816+
objPoints.ptr< Vec3f >(0)[1] = Vec3f(markerLength, 0.f, 0);
817+
objPoints.ptr< Vec3f >(0)[2] = Vec3f(markerLength, markerLength, 0);
818+
objPoints.ptr< Vec3f >(0)[3] = Vec3f(0.f, markerLength, 0);
819819
}
820820

821821

@@ -1783,24 +1783,6 @@ void drawDetectedMarkers(InputOutputArray _image, InputArrayOfArrays _corners,
17831783
}
17841784

17851785

1786-
1787-
/**
1788-
*/
1789-
void drawAxis(InputOutputArray _image, InputArray _cameraMatrix, InputArray _distCoeffs, InputArray _rvec,
1790-
InputArray _tvec, float length, int thickness)
1791-
{
1792-
vector<Point3f> axis;
1793-
axis.push_back(Point3f(0.f, 0.f, 0.f));
1794-
axis.push_back(Point3f(length, 0.f, 0.f));
1795-
axis.push_back(Point3f(0.f, length, 0.f));
1796-
axis.push_back(Point3f(0.f, 0.f, -length));
1797-
vector<Point2f> axis_to_img;
1798-
projectPoints(axis, _rvec, _tvec, _cameraMatrix, _distCoeffs, axis_to_img);
1799-
line(_image, Point2i(axis_to_img[0]), Point2i(axis_to_img[1]), Scalar(255,0,0), thickness);
1800-
line(_image, Point2i(axis_to_img[0]), Point2i(axis_to_img[2]), Scalar(0,255,0), thickness);
1801-
line(_image, Point2i(axis_to_img[0]), Point2i(axis_to_img[3]), Scalar(0,0,255), thickness);
1802-
}
1803-
18041786
/**
18051787
*/
18061788
void drawMarker(const Ptr<Dictionary> &dictionary, int id, int sidePixels, OutputArray _img, int borderBits) {

modules/aruco/src/charuco.cpp

+6-7
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ the use of this software, even if advised of the possibility of such damage.
4141
#include <opencv2/core.hpp>
4242
#include <opencv2/imgproc.hpp>
4343

44-
4544
namespace cv {
4645
namespace aruco {
4746

@@ -743,14 +742,14 @@ double calibrateCameraCharuco(InputArrayOfArrays _charucoCorners, InputArrayOfAr
743742
void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners,
744743
InputArray _markerIds, float squareMarkerLengthRate,
745744
OutputArrayOfArrays _diamondCorners, OutputArray _diamondIds,
746-
InputArray _cameraMatrix, InputArray _distCoeffs, Ptr<Dictionary> dict) {
745+
InputArray _cameraMatrix, InputArray _distCoeffs, Ptr<Dictionary> dictionary) {
747746

748747
CV_Assert(_markerIds.total() > 0 && _markerIds.total() == _markerCorners.total());
749748

750749
const float minRepDistanceRate = 1.302455f;
751750

752751
// create Charuco board layout for diamond (3x3 layout)
753-
Ptr<CharucoBoard> _charucoDiamondLayout = CharucoBoard::create(3, 3, squareMarkerLengthRate, 1., dict);
752+
Ptr<CharucoBoard> _charucoDiamondLayout = CharucoBoard::create(3, 3, squareMarkerLengthRate, 1., dictionary);
754753

755754

756755
vector< vector< Point2f > > diamondCorners;
@@ -842,10 +841,10 @@ void detectCharucoDiamond(InputArray _image, InputArrayOfArrays _markerCorners,
842841
// reorder corners
843842
vector< Point2f > currentMarkerCornersReorder;
844843
currentMarkerCornersReorder.resize(4);
845-
currentMarkerCornersReorder[0] = currentMarkerCorners[2];
846-
currentMarkerCornersReorder[1] = currentMarkerCorners[3];
847-
currentMarkerCornersReorder[2] = currentMarkerCorners[1];
848-
currentMarkerCornersReorder[3] = currentMarkerCorners[0];
844+
currentMarkerCornersReorder[0] = currentMarkerCorners[0];
845+
currentMarkerCornersReorder[1] = currentMarkerCorners[1];
846+
currentMarkerCornersReorder[2] = currentMarkerCorners[3];
847+
currentMarkerCornersReorder[3] = currentMarkerCorners[2];
849848

850849
diamondCorners.push_back(currentMarkerCornersReorder);
851850
diamondIds.push_back(markerId);

modules/aruco/test/test_aruco_utils.hpp

+21
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,27 @@
55
namespace opencv_test {
66
namespace {
77

8+
static inline vector<Point2f> getAxis(InputArray _cameraMatrix, InputArray _distCoeffs, InputArray _rvec,
9+
InputArray _tvec, float length, const float offset = 0.f)
10+
{
11+
vector<Point3f> axis;
12+
axis.push_back(Point3f(offset, offset, 0.f));
13+
axis.push_back(Point3f(length+offset, offset, 0.f));
14+
axis.push_back(Point3f(offset, length+offset, 0.f));
15+
axis.push_back(Point3f(offset, offset, length));
16+
vector<Point2f> axis_to_img;
17+
projectPoints(axis, _rvec, _tvec, _cameraMatrix, _distCoeffs, axis_to_img);
18+
return axis_to_img;
19+
}
20+
21+
static inline vector<Point2f> getMarkerById(int id, const vector<vector<Point2f> >& corners, const vector<int>& ids)
22+
{
23+
for (size_t i = 0ull; i < ids.size(); i++)
24+
if (ids[i] == id)
25+
return corners[i];
26+
return vector<Point2f>();
27+
}
28+
829
static inline double deg2rad(double deg) { return deg * CV_PI / 180.; }
930

1031
/**

modules/aruco/test/test_boarddetection.cpp

+17-9
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ void CV_ArucoBoardPose::run(int) {
7070
Mat distCoeffs(5, 1, CV_64FC1, Scalar::all(0));
7171

7272
// for different perspectives
73-
for(double distance = 0.2; distance <= 0.4; distance += 0.2) {
74-
for(int yaw = -60; yaw <= 60; yaw += 30) {
75-
for(int pitch = -60; pitch <= 60; pitch += 30) {
73+
for(double distance = 0.2; distance <= 0.4; distance += 0.15) {
74+
for(int yaw = -55; yaw <= 50; yaw += 25) {
75+
for(int pitch = -55; pitch <= 50; pitch += 25) {
7676
for(unsigned int i = 0; i < gridboard->ids.size(); i++)
7777
gridboard->ids[i] = (iter + int(i)) % 250;
7878
int markerBorder = iter % 2 + 1;
@@ -87,17 +87,25 @@ void CV_ArucoBoardPose::run(int) {
8787
params->markerBorderBits = markerBorder;
8888
aruco::detectMarkers(img, dictionary, corners, ids, params);
8989

90-
if(ids.size() == 0) {
91-
ts->printf(cvtest::TS::LOG, "Marker detection failed in Board test");
92-
ts->set_failed_test_info(cvtest::TS::FAIL_MISMATCH);
93-
return;
94-
}
90+
ASSERT_EQ(ids.size(), gridboard->ids.size());
9591

9692
// estimate pose
9793
Mat rvec, tvec;
9894
aruco::estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec);
9995

100-
// check result
96+
// check axes
97+
vector<Point2f> axes = getAxis(cameraMatrix, distCoeffs, rvec, tvec, gridboard->rightBottomBorder.x);
98+
vector<Point2f> topLeft = getMarkerById(gridboard->ids[0], corners, ids);
99+
ASSERT_NEAR(topLeft[0].x, axes[0].x, 2.f);
100+
ASSERT_NEAR(topLeft[0].y, axes[0].y, 2.f);
101+
vector<Point2f> topRight = getMarkerById(gridboard->ids[2], corners, ids);
102+
ASSERT_NEAR(topRight[1].x, axes[1].x, 2.f);
103+
ASSERT_NEAR(topRight[1].y, axes[1].y, 2.f);
104+
vector<Point2f> bottomLeft = getMarkerById(gridboard->ids[6], corners, ids);
105+
ASSERT_NEAR(bottomLeft[3].x, axes[2].x, 2.f);
106+
ASSERT_NEAR(bottomLeft[3].y, axes[2].y, 2.f);
107+
108+
// check estimate result
101109
for(unsigned int i = 0; i < ids.size(); i++) {
102110
int foundIdx = -1;
103111
for(unsigned int j = 0; j < gridboard->ids.size(); j++) {

0 commit comments

Comments
 (0)