Commit 882d7e6d authored by Alexander Alekhin's avatar Alexander Alekhin

Merge pull request #1637 from catree:add_apriltag_dictionaries

parents c5404095 81d7d980
@article{Aruco2014,
title = "Automatic generation and detection of highly reliable fiducial markers under occlusion ",
journal = "Pattern Recognition ",
volume = "47",
number = "6",
pages = "2280 - 2292",
year = "2014",
issn = "0031-3203",
doi = "http://dx.doi.org/10.1016/j.patcog.2014.01.005",
url = "http://www.sciencedirect.com/science/article/pii/S0031320314000235",
author = "S. Garrido-Jurado and R. Mu\~noz-Salinas and F.J. Madrid-Cuevas and M.J. Mar\'in-Jim\'enez"
}
@inproceedings{wang2016iros,
AUTHOR = {John Wang and Edwin Olson},
TITLE = {{AprilTag} 2: Efficient and robust fiducial detection},
BOOKTITLE = {Proceedings of the {IEEE/RSJ} International Conference on Intelligent
Robots and Systems {(IROS)}},
YEAR = {2016},
MONTH = {October},
}
...@@ -49,14 +49,16 @@ the use of this software, even if advised of the possibility of such damage. ...@@ -49,14 +49,16 @@ the use of this software, even if advised of the possibility of such damage.
* These markers are useful for easy, fast and robust camera pose estimation.ç * These markers are useful for easy, fast and robust camera pose estimation.ç
* *
* The main functionalities are: * The main functionalities are:
* - Detection of markers in a image * - Detection of markers in an image
* - Pose estimation from a single marker or from a board/set of markers * - Pose estimation from a single marker or from a board/set of markers
* - Detection of ChArUco board for high subpixel accuracy * - Detection of ChArUco board for high subpixel accuracy
* - Camera calibration from both, ArUco boards and ChArUco boards. * - Camera calibration from both, ArUco boards and ChArUco boards.
* - Detection of ChArUco diamond markers * - Detection of ChArUco diamond markers
* The samples directory includes easy examples of how to use the module. * The samples directory includes easy examples of how to use the module.
* *
* The implementation is based on the ArUco Library by R. Muñoz-Salinas and S. Garrido-Jurado. * The implementation is based on the ArUco Library by R. Muñoz-Salinas and S. Garrido-Jurado @cite Aruco2014.
*
* Markers can also be detected based on the AprilTag 2 @cite wang2016iros fiducial detection method.
* *
* @sa S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, and M. J. Marín-Jiménez. 2014. * @sa S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, and M. J. Marín-Jiménez. 2014.
* "Automatic generation and detection of highly reliable fiducial markers under occlusion". * "Automatic generation and detection of highly reliable fiducial markers under occlusion".
...@@ -77,10 +79,10 @@ namespace aruco { ...@@ -77,10 +79,10 @@ namespace aruco {
//! @{ //! @{
enum CornerRefineMethod{ enum CornerRefineMethod{
CORNER_REFINE_NONE, // default corners CORNER_REFINE_NONE, ///< Tag and corners detection based on the ArUco approach
CORNER_REFINE_SUBPIX, // refine the corners using subpix CORNER_REFINE_SUBPIX, ///< ArUco approach and refine the corners locations using corner subpixel accuracy
CORNER_REFINE_CONTOUR, // refine the corners using the contour-points CORNER_REFINE_CONTOUR, ///< ArUco approach and refine the corners locations using the contour-points line fitting
CORNER_REFINE_APRILTAG, // detect corners using the AprilTag2 approach CORNER_REFINE_APRILTAG, ///< Tag and corners detection based on the AprilTag 2 approach @cite wang2016iros
}; };
/** /**
......
...@@ -155,7 +155,11 @@ enum CV_EXPORTS_W_SIMPLE PREDEFINED_DICTIONARY_NAME { ...@@ -155,7 +155,11 @@ enum CV_EXPORTS_W_SIMPLE PREDEFINED_DICTIONARY_NAME {
DICT_7X7_100, DICT_7X7_100,
DICT_7X7_250, DICT_7X7_250,
DICT_7X7_1000, DICT_7X7_1000,
DICT_ARUCO_ORIGINAL DICT_ARUCO_ORIGINAL,
DICT_APRILTAG_16h5, ///< 4x4 bits, minimum hamming distance between any two codes = 5, 30 codes
DICT_APRILTAG_25h9, ///< 5x5 bits, minimum hamming distance between any two codes = 9, 35 codes
DICT_APRILTAG_36h10, ///< 6x6 bits, minimum hamming distance between any two codes = 10, 2320 codes
DICT_APRILTAG_36h11 ///< 6x6 bits, minimum hamming distance between any two codes = 11, 587 codes
}; };
......
...@@ -50,13 +50,16 @@ const char* keys = ...@@ -50,13 +50,16 @@ const char* keys =
"{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2," "{d | | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
"DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, " "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "
"DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12," "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
"DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}" "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16,"
"DICT_APRILTAG_16h5=17, DICT_APRILTAG_25h9=18, DICT_APRILTAG_36h10=19, DICT_APRILTAG_36h11=20}"
"{v | | Input from video file, if ommited, input comes from camera }" "{v | | Input from video file, if ommited, input comes from camera }"
"{ci | 0 | Camera id if input doesnt come from video (-v) }" "{ci | 0 | Camera id if input doesnt come from video (-v) }"
"{c | | Camera intrinsic parameters. Needed for camera pose }" "{c | | Camera intrinsic parameters. Needed for camera pose }"
"{l | 0.1 | Marker side lenght (in meters). Needed for correct scale in camera pose }" "{l | 0.1 | Marker side lenght (in meters). Needed for correct scale in camera pose }"
"{dp | | File of marker detector parameters }" "{dp | | File of marker detector parameters }"
"{r | | show rejected candidates too }"; "{r | | show rejected candidates too }"
"{refine | | Corner refinement: CORNER_REFINE_NONE=0, CORNER_REFINE_SUBPIX=1,"
"CORNER_REFINE_CONTOUR=2, CORNER_REFINE_APRILTAG=3}";
} }
/** /**
...@@ -127,7 +130,12 @@ int main(int argc, char *argv[]) { ...@@ -127,7 +130,12 @@ int main(int argc, char *argv[]) {
return 0; return 0;
} }
} }
detectorParams->cornerRefinementMethod = aruco::CORNER_REFINE_SUBPIX; // do corner refinement in markers
if (parser.has("refine")) {
//override cornerRefinementMethod read from config file
detectorParams->cornerRefinementMethod = parser.get<int>("refine");
}
std::cout << "Corner refinement method (0: None, 1: Subpixel, 2:contour, 3: AprilTag 2): " << detectorParams->cornerRefinementMethod << std::endl;
int camId = parser.get<int>("ci"); int camId = parser.get<int>("ci");
......
...@@ -41,6 +41,7 @@ the use of this software, even if advised of the possibility of such damage. ...@@ -41,6 +41,7 @@ the use of this software, even if advised of the possibility of such damage.
#include <opencv2/core.hpp> #include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp> #include <opencv2/imgproc.hpp>
#include "predefined_dictionaries.hpp" #include "predefined_dictionaries.hpp"
#include "predefined_dictionaries_apriltag.hpp"
#include "opencv2/core/hal/hal.hpp" #include "opencv2/core/hal/hal.hpp"
namespace cv { namespace cv {
...@@ -291,6 +292,11 @@ const Dictionary DICT_7X7_100_DATA = Dictionary(Mat(100, (7*7 + 7)/8 ,CV_8UC4, ( ...@@ -291,6 +292,11 @@ const Dictionary DICT_7X7_100_DATA = Dictionary(Mat(100, (7*7 + 7)/8 ,CV_8UC4, (
const Dictionary DICT_7X7_250_DATA = Dictionary(Mat(250, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 8); const Dictionary DICT_7X7_250_DATA = Dictionary(Mat(250, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 8);
const Dictionary DICT_7X7_1000_DATA = Dictionary(Mat(1000, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 6); const Dictionary DICT_7X7_1000_DATA = Dictionary(Mat(1000, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 6);
const Dictionary DICT_APRILTAG_16h5_DATA = Dictionary(Mat(30, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_16h5_BYTES), 4, 0);
const Dictionary DICT_APRILTAG_25h9_DATA = Dictionary(Mat(35, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_25h9_BYTES), 5, 0);
const Dictionary DICT_APRILTAG_36h10_DATA = Dictionary(Mat(2320, (6*6 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_36h10_BYTES), 6, 0);
const Dictionary DICT_APRILTAG_36h11_DATA = Dictionary(Mat(587, (6*6 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_36h11_BYTES), 6, 0);
Ptr<Dictionary> getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) { Ptr<Dictionary> getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) {
switch(name) { switch(name) {
...@@ -334,6 +340,15 @@ Ptr<Dictionary> getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) { ...@@ -334,6 +340,15 @@ Ptr<Dictionary> getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name) {
case DICT_7X7_1000: case DICT_7X7_1000:
return makePtr<Dictionary>(DICT_7X7_1000_DATA); return makePtr<Dictionary>(DICT_7X7_1000_DATA);
case DICT_APRILTAG_16h5:
return makePtr<Dictionary>(DICT_APRILTAG_16h5_DATA);
case DICT_APRILTAG_25h9:
return makePtr<Dictionary>(DICT_APRILTAG_25h9_DATA);
case DICT_APRILTAG_36h10:
return makePtr<Dictionary>(DICT_APRILTAG_36h10_DATA);
case DICT_APRILTAG_36h11:
return makePtr<Dictionary>(DICT_APRILTAG_36h11_DATA);
} }
return makePtr<Dictionary>(DICT_4X4_50_DATA); return makePtr<Dictionary>(DICT_4X4_50_DATA);
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment