Skip to content

Commit 976d76e

Browse files
author
AleksandrPanov
committed
fix charuco_diamond_detection.markdown
1 parent 85d802e commit 976d76e

11 files changed

+132
-215
lines changed
Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,5 @@
1-
/*
2-
By downloading, copying, installing or using the software you agree to this
3-
license. If you do not agree to this license, do not download, install,
4-
copy or use the software.
5-
6-
License Agreement
7-
For Open Source Computer Vision Library
8-
(3-clause BSD License)
9-
10-
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
11-
Third party copyrights are property of their respective owners.
12-
13-
Redistribution and use in source and binary forms, with or without modification,
14-
are permitted provided that the following conditions are met:
15-
16-
* Redistributions of source code must retain the above copyright notice,
17-
this list of conditions and the following disclaimer.
18-
19-
* Redistributions in binary form must reproduce the above copyright notice,
20-
this list of conditions and the following disclaimer in the documentation
21-
and/or other materials provided with the distribution.
22-
23-
* Neither the names of the copyright holders nor the names of the contributors
24-
may be used to endorse or promote products derived from this software
25-
without specific prior written permission.
26-
27-
This software is provided by the copyright holders and contributors "as is" and
28-
any express or implied warranties, including, but not limited to, the implied
29-
warranties of merchantability and fitness for a particular purpose are
30-
disclaimed. In no event shall copyright holders or contributors be liable for
31-
any direct, indirect, incidental, special, exemplary, or consequential damages
32-
(including, but not limited to, procurement of substitute goods or services;
33-
loss of use, data, or profits; or business interruption) however caused
34-
and on any theory of liability, whether in contract, strict liability,
35-
or tort (including negligence or otherwise) arising in any way out of
36-
the use of this software, even if advised of the possibility of such damage.
37-
*/
38-
39-
401
#include <opencv2/highgui.hpp>
41-
#include <opencv2/aruco/charuco.hpp>
2+
#include <opencv2/objdetect/charuco_detector.hpp>
423
#include <vector>
434
#include <iostream>
445

@@ -48,28 +9,25 @@ using namespace cv;
489
namespace {
4910
const char* about = "Create a ChArUco marker image";
5011
const char* keys =
51-
"{@outfile |<none> | Output image }"
52-
"{sl | | Square side length (in pixels) }"
53-
"{ml | | Marker side length (in pixels) }"
54-
"{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
12+
"{@outfile | res.png | Output image }"
13+
"{sl | 100 | Square side length (in pixels) }"
14+
"{ml | 60 | Marker side length (in pixels) }"
15+
"{cd | | Input file with custom dictionary }"
16+
"{d | 10 | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
5517
"DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "
5618
"DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
5719
"DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"
58-
"{ids |<none> | Four ids for the ChArUco marker: id1,id2,id3,id4 }"
59-
"{m | 0 | Margins size (in pixels) }"
60-
"{bb | 1 | Number of bits in marker borders }"
61-
"{si | false | show generated image }";
20+
"{ids |0, 1, 2, 3 | Four ids for the ChArUco marker: id1,id2,id3,id4 }"
21+
"{m | 0 | Margins size (in pixels) }"
22+
"{bb | 1 | Number of bits in marker borders }"
23+
"{si | false | show generated image }";
6224
}
6325

64-
/**
65-
*/
6626
int main(int argc, char *argv[]) {
6727
CommandLineParser parser(argc, argv, keys);
6828
parser.about(about);
69-
70-
if(argc < 4) {
29+
if (argc == 1) {
7130
parser.printMessage();
72-
return 0;
7331
}
7432

7533
int squareLength = parser.get<int>("sl");
@@ -79,17 +37,25 @@ int main(int argc, char *argv[]) {
7937
int margins = parser.get<int>("m");
8038
int borderBits = parser.get<int>("bb");
8139
bool showImage = parser.get<bool>("si");
82-
String out = parser.get<String>(0);
40+
string out = parser.get<string>(0);
8341

8442
if(!parser.check()) {
8543
parser.printErrors();
8644
return 0;
8745
}
8846

8947
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::PredefinedDictionaryType(dictionaryId));
48+
if (parser.has("cd")) {
49+
FileStorage fs(parser.get<std::string>("cd"), FileStorage::READ);
50+
bool readOk = dictionary.aruco::Dictionary::readDictionary(fs.root());
51+
if(!readOk) {
52+
cerr << "Invalid dictionary file" << endl;
53+
return 0;
54+
}
55+
}
9056

9157
istringstream ss(idsString);
92-
vector< string > splittedIds;
58+
vector<string> splittedIds;
9359
string token;
9460
while(getline(ss, token, ','))
9561
splittedIds.push_back(token);
@@ -102,16 +68,19 @@ int main(int argc, char *argv[]) {
10268
for(int i = 0; i < 4; i++)
10369
ids[i] = atoi(splittedIds[i].c_str());
10470

71+
//! [generate_diamond]
72+
vector<int> diamondIds = {ids[0], ids[1], ids[2], ids[3]};
73+
aruco::CharucoBoard charucoBoard(Size(3, 3), (float)squareLength, (float)markerLength, dictionary, diamondIds);
10574
Mat markerImg;
106-
aruco::drawCharucoDiamond(makePtr<aruco::Dictionary>(dictionary), ids, squareLength, markerLength, markerImg, margins,
107-
borderBits);
75+
charucoBoard.generateImage(Size(3*squareLength + 2*margins, 3*squareLength + 2*margins), markerImg, margins, borderBits);
76+
//! [generate_diamond]
10877

10978
if(showImage) {
11079
imshow("board", markerImg);
11180
waitKey(0);
11281
}
11382

114-
imwrite(out, markerImg);
115-
83+
if (out != "")
84+
imwrite(out, markerImg);
11685
return 0;
11786
}

modules/aruco/samples/detect_board_charuco.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,14 @@ int main(int argc, char *argv[]) {
121121
float axisLength = 0.5f * ((float)min(squaresX, squaresY) * (squareLength));
122122

123123
// create charuco board object
124-
aruco::CharucoBoard charucoboard(Size(squaresX, squaresY), squareLength, markerLength, dictionary);
124+
aruco::CharucoBoard charucoBoard(Size(squaresX, squaresY), squareLength, markerLength, dictionary);
125125

126126
// create charuco detector
127127
aruco::CharucoParameters charucoParams;
128128
charucoParams.tryRefineMarkers = refine; // if tryRefineMarkers, refineDetectedMarkers() will be used in detectBoard()
129129
charucoParams.cameraMatrix = camMatrix; // cameraMatrix can be used in detectBoard()
130130
charucoParams.distCoeffs = distCoeffs; // distCoeffs can be used in detectBoard()
131-
aruco::CharucoDetector charucoDetector(charucoboard, charucoParams, detectorParams);
131+
aruco::CharucoDetector charucoDetector(charucoBoard, charucoParams, detectorParams);
132132

133133
double totalTime = 0;
134134
int totalIterations = 0;
@@ -156,7 +156,7 @@ int main(int argc, char *argv[]) {
156156
bool validPose = false;
157157
if(camMatrix.total() != 0 && distCoeffs.total() != 0 && charucoIds.size() >= 4) {
158158
Mat objPoints, imgPoints;
159-
charucoboard.matchImagePoints(charucoCorners, charucoIds, objPoints, imgPoints);
159+
charucoBoard.matchImagePoints(charucoCorners, charucoIds, objPoints, imgPoints);
160160
validPose = solvePnP(objPoints, imgPoints, camMatrix, distCoeffs, rvec, tvec);
161161
}
162162
//! [poseCharuco]

modules/aruco/samples/detect_diamonds.cpp

Lines changed: 59 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,9 @@
1-
/*
2-
By downloading, copying, installing or using the software you agree to this
3-
license. If you do not agree to this license, do not download, install,
4-
copy or use the software.
5-
6-
License Agreement
7-
For Open Source Computer Vision Library
8-
(3-clause BSD License)
9-
10-
Copyright (C) 2013, OpenCV Foundation, all rights reserved.
11-
Third party copyrights are property of their respective owners.
12-
13-
Redistribution and use in source and binary forms, with or without modification,
14-
are permitted provided that the following conditions are met:
15-
16-
* Redistributions of source code must retain the above copyright notice,
17-
this list of conditions and the following disclaimer.
18-
19-
* Redistributions in binary form must reproduce the above copyright notice,
20-
this list of conditions and the following disclaimer in the documentation
21-
and/or other materials provided with the distribution.
22-
23-
* Neither the names of the copyright holders nor the names of the contributors
24-
may be used to endorse or promote products derived from this software
25-
without specific prior written permission.
26-
27-
This software is provided by the copyright holders and contributors "as is" and
28-
any express or implied warranties, including, but not limited to, the implied
29-
warranties of merchantability and fitness for a particular purpose are
30-
disclaimed. In no event shall copyright holders or contributors be liable for
31-
any direct, indirect, incidental, special, exemplary, or consequential damages
32-
(including, but not limited to, procurement of substitute goods or services;
33-
loss of use, data, or profits; or business interruption) however caused
34-
and on any theory of liability, whether in contract, strict liability,
35-
or tort (including negligence or otherwise) arising in any way out of
36-
the use of this software, even if advised of the possibility of such damage.
37-
*/
38-
39-
401
#include <opencv2/highgui.hpp>
412
#include <opencv2/aruco/charuco.hpp>
423
#include <vector>
434
#include <iostream>
5+
#include <opencv2/objdetect/aruco_detector.hpp>
6+
#include <opencv2/objdetect/charuco_detector.hpp>
447
#include "aruco_samples_utility.hpp"
458

469
using namespace std;
@@ -87,20 +50,20 @@ int main(int argc, char *argv[]) {
8750
bool autoScale = parser.has("as");
8851
float autoScaleFactor = autoScale ? parser.get<float>("as") : 1.f;
8952

90-
Ptr<aruco::DetectorParameters> detectorParams = makePtr<aruco::DetectorParameters>();
53+
aruco::DetectorParameters detectorParams;
9154
if(parser.has("dp")) {
9255
FileStorage fs(parser.get<string>("dp"), FileStorage::READ);
93-
bool readOk = detectorParams->readDetectorParameters(fs.root());
56+
bool readOk = detectorParams.readDetectorParameters(fs.root());
9457
if(!readOk) {
9558
cerr << "Invalid detector parameters file" << endl;
9659
return 0;
9760
}
9861
}
9962
if (parser.has("refine")) {
10063
//override cornerRefinementMethod read from config file
101-
detectorParams->cornerRefinementMethod = parser.get<aruco::CornerRefineMethod>("refine");
64+
detectorParams.cornerRefinementMethod = parser.get<aruco::CornerRefineMethod>("refine");
10265
}
103-
std::cout << "Corner refinement method (0: None, 1: Subpixel, 2:contour, 3: AprilTag 2): " << (int)detectorParams->cornerRefinementMethod << std::endl;
66+
std::cout << "Corner refinement method (0: None, 1: Subpixel, 2:contour, 3: AprilTag 2): " << (int)detectorParams.cornerRefinementMethod << std::endl;
10467

10568
int camId = parser.get<int>("ci");
10669
String video;
@@ -154,43 +117,65 @@ int main(int argc, char *argv[]) {
154117
double totalTime = 0;
155118
int totalIterations = 0;
156119

120+
aruco::CharucoBoard charucoBoard(Size(3, 3), squareLength, markerLength, dictionary);
121+
aruco::CharucoDetector detector(charucoBoard, aruco::CharucoParameters(), detectorParams);
122+
157123
while(inputVideo.grab()) {
158124
Mat image, imageCopy;
159125
inputVideo.retrieve(image);
160126

161127
double tick = (double)getTickCount();
162128

163-
vector< int > markerIds;
164-
vector< Vec4i > diamondIds;
165-
vector< vector< Point2f > > markerCorners, rejectedMarkers, diamondCorners;
166-
vector< Vec3d > rvecs, tvecs;
129+
//! [detect_diamonds]
130+
vector<int> markerIds;
131+
vector<Vec4i> diamondIds;
132+
vector<vector<Point2f> > markerCorners, rejectedMarkers, diamondCorners;
133+
vector<Vec3d> rvecs, tvecs;
167134

168-
// detect markers
169-
aruco::detectMarkers(image, makePtr<aruco::Dictionary>(dictionary), markerCorners, markerIds, detectorParams,
170-
rejectedMarkers);
171-
172-
// detect diamonds
173-
if(markerIds.size() > 0)
174-
aruco::detectCharucoDiamond(image, markerCorners, markerIds,
175-
squareLength / markerLength, diamondCorners, diamondIds,
176-
camMatrix, distCoeffs);
135+
detector.detectDiamonds(image, diamondCorners, diamondIds, markerCorners, markerIds);
136+
//! [detect_diamonds]
177137

138+
//! [diamond_pose_estimation]
178139
// estimate diamond pose
179-
if(estimatePose && diamondIds.size() > 0) {
140+
size_t N = diamondIds.size();
141+
if(estimatePose && N > 0) {
142+
cv::Mat objPoints(4, 1, CV_32FC3);
143+
rvecs.resize(N);
144+
tvecs.resize(N);
180145
if(!autoScale) {
181-
aruco::estimatePoseSingleMarkers(diamondCorners, squareLength, camMatrix,
182-
distCoeffs, rvecs, tvecs);
183-
} else {
146+
// set coordinate system
147+
objPoints.ptr<Vec3f>(0)[0] = Vec3f(-squareLength/2.f, squareLength/2.f, 0);
148+
objPoints.ptr<Vec3f>(0)[1] = Vec3f(squareLength/2.f, squareLength/2.f, 0);
149+
objPoints.ptr<Vec3f>(0)[2] = Vec3f(squareLength/2.f, -squareLength/2.f, 0);
150+
objPoints.ptr<Vec3f>(0)[3] = Vec3f(-squareLength/2.f, -squareLength/2.f, 0);
151+
// Calculate pose for each marker
152+
for (size_t i = 0ull; i < N; i++)
153+
solvePnP(objPoints, diamondCorners.at(i), camMatrix, distCoeffs, rvecs.at(i), tvecs.at(i));
154+
//! [diamond_pose_estimation]
155+
/* //! [diamond_pose_estimation_as_charuco]
156+
for (size_t i = 0ull; i < N; i++) { // estimate diamond pose as Charuco board
157+
Mat objPoints_b, imgPoints;
158+
// The coordinate system of the diamond is placed in the board plane centered in the bottom left corner
159+
vector<int> charucoIds = {0, 1, 3, 2}; // if CCW order, Z axis pointing in the plane
160+
// vector<int> charucoIds = {0, 2, 3, 1}; // if CW order, Z axis pointing out the plane
161+
charucoBoard.matchImagePoints(diamondCorners[i], charucoIds, objPoints_b, imgPoints);
162+
solvePnP(objPoints_b, imgPoints, camMatrix, distCoeffs, rvecs[i], tvecs[i]);
163+
}
164+
//! [diamond_pose_estimation_as_charuco] */
165+
}
166+
else {
184167
// if autoscale, extract square size from last diamond id
185-
for(unsigned int i = 0; i < diamondCorners.size(); i++) {
186-
float autoSquareLength = autoScaleFactor * float(diamondIds[i].val[3]);
187-
vector< vector< Point2f > > currentCorners;
188-
vector< Vec3d > currentRvec, currentTvec;
168+
for(size_t i = 0; i < N; i++) {
169+
float sqLenScale = autoScaleFactor * float(diamondIds[i].val[3]);
170+
vector<vector<Point2f> > currentCorners;
171+
vector<Vec3d> currentRvec, currentTvec;
189172
currentCorners.push_back(diamondCorners[i]);
190-
aruco::estimatePoseSingleMarkers(currentCorners, autoSquareLength, camMatrix,
191-
distCoeffs, currentRvec, currentTvec);
192-
rvecs.push_back(currentRvec[0]);
193-
tvecs.push_back(currentTvec[0]);
173+
// set coordinate system
174+
objPoints.ptr<Vec3f>(0)[0] = Vec3f(-sqLenScale/2.f, sqLenScale/2.f, 0);
175+
objPoints.ptr<Vec3f>(0)[1] = Vec3f(sqLenScale/2.f, sqLenScale/2.f, 0);
176+
objPoints.ptr<Vec3f>(0)[2] = Vec3f(sqLenScale/2.f, -sqLenScale/2.f, 0);
177+
objPoints.ptr<Vec3f>(0)[3] = Vec3f(-sqLenScale/2.f, -sqLenScale/2.f, 0);
178+
solvePnP(objPoints, diamondCorners.at(i), camMatrix, distCoeffs, rvecs.at(i), tvecs.at(i));
194179
}
195180
}
196181
}
@@ -214,20 +199,21 @@ int main(int argc, char *argv[]) {
214199
if(showRejected && rejectedMarkers.size() > 0)
215200
aruco::drawDetectedMarkers(imageCopy, rejectedMarkers, noArray(), Scalar(100, 0, 255));
216201

202+
//! [draw_diamonds]
217203
if(diamondIds.size() > 0) {
218204
aruco::drawDetectedDiamonds(imageCopy, diamondCorners, diamondIds);
205+
//! [draw_diamonds]
219206

207+
//! [draw_diamond_pose_estimation]
220208
if(estimatePose) {
221-
for(unsigned int i = 0; i < diamondIds.size(); i++)
222-
cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i],
223-
squareLength * 1.1f);
209+
for(size_t i = 0u; i < diamondIds.size(); i++)
210+
cv::drawFrameAxes(imageCopy, camMatrix, distCoeffs, rvecs[i], tvecs[i], squareLength*1.1f);
224211
}
212+
//! [draw_diamond_pose_estimation]
225213
}
226-
227214
imshow("out", imageCopy);
228215
char key = (char)waitKey(waitTime);
229216
if(key == 27) break;
230217
}
231-
232218
return 0;
233219
}

modules/aruco/tutorials/charuco_detection/charuco_detection.markdown

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ The parameters of detectBoard are:
138138
- `markerCorners` - input/output vector of detected marker corners.
139139
- `markerIds` - input/output vector of identifiers of the detected markers
140140

141-
If markerCorners and markerIds are empty, then `cv::aruco::CharucoDetector::detectBoard()`
142-
call `cv::aruco::ArucoDetector::detectMarkers()` and return `markerCorners` and `markerIds`.
141+
If markerCorners and markerIds are empty, the function will detect aruco markers and ids.
143142

144143
If calibration parameters are provided, the ChArUco corners are interpolated by, first, estimating a rough pose from the ArUco markers
145144
and, then, reprojecting the ChArUco corners back to the image.
@@ -207,7 +206,9 @@ The aruco module provides a function to perform ChArUco pose estimation easily.
207206
of the `cv::aruco::CharucoBoard` is placed in the board plane with the Z axis pointing in, and centered in the bottom left corner of the board.
208207

209208
@note After OpenCV 4.6.0, there was an incompatible change in the coordinate systems of the boards,
210-
now the coordinate systems are placed in the boards plane with the Z axis pointing in (previously the axis pointed out).
209+
now the coordinate systems are placed in the boards plane with the Z axis pointing in the plane (previously the axis pointed out the plane).
210+
`objPoints` in CW order correspond to the Z-axis pointing in the plane.
211+
`objPoints` in CCW order correspond to the Z-axis pointing out the plane.
211212
See PR https://github.com/opencv/opencv_contrib/pull/3174
212213

213214

0 commit comments

Comments
 (0)