Aruco生成标记与板的代码详解——

一、什么是ArUco标记?

  What is the ARUCO Tag?

    ArUco标记最初由S.Garrido-Jurado等人在2014年发表的论文Automatic generation and detection of highly reliable fiducial markers under occlusion中提出。ArUco的全称是Augmented Reality University of Cordoba,下面给出ArUco标记的生成示例。

  The ARUCO tag was originally marked by S. Garrido-jurado et al. proposed in a paper published in 2014 on Automatic Generation and detection of highly reliable fiducial markers under occlude. The full name of ArUco is Augmented Reality University of Cordoba. Here are some examples of ArUco tags.

  ArUco标记作为基准标记放置在要成像的对象或场景上。它是一个背景为黑色的正方形,正方形内部的白色图案用来表示标记的唯一性,并且存储一些信息。黑色边界的目的是为了提高ArUco标记检测的准确性和性能。ArUco标记的尺寸可以任意的更改,为了成功检测可根据对象大小和场景选择合适的尺寸。在实际使用中,如果标记的尺寸太小,可能无法检测到它,这时可以选择更换较大尺寸的标记,或者将相机离标记更近一些。

  在本文中,通过aruco库函数生成其可使用的标记与板,用于后续项目。此外,在机器人应用中,可以将这些标记沿着仓库机器人的路径放置。当安装在机器人上的摄像头检测到这些标记时,由于每个标记都有唯一的ID,并且且标记在仓库中的放置位置已知,因此就可以知道机器人在仓库中的精确位置。

  生成标记的源码:

  1 //引入头文件
  2 #include <opencv2/highgui.hpp>
  3 #include <opencv2/aruco.hpp>
  4 
  5 //定义命名空间
  6 using namespace cv;
  7 
  8 //赋予命名空间中about与keys的信息
  9 namespace {
 10 const char* about = "Create an ArUco marker image";
 11 const char* keys  =
 12         "{@outfile |<none> | Output image }"
 13         "{d        |       | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
 14         "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "
 15         "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
 16         "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"
 17         "{id       |       | Marker id in the dictionary }"
 18         "{ms       | 200   | Marker size in pixels }"
 19         "{bb       | 1     | Number of bits in marker borders }"
 20         "{si       | false | show generated image }";
 21 }
 22 
 23 
 24 int main(int argc, char *argv[]) {
 25     /*
 26     * 函数功能:构造函数
 27     * 参数:
 28     *   [in]     argc        main函数中的第一参数,即运行程序中获得指令的个数
 29     *   [in]     argv        main函数中的第二个参数,即运行程序中指令的内容
 30     *   [in]     key_map     当启动程序是没有输入任何指令,则使用key_map中默认的指指令。
 31     * 备注:
 32     *   key_map中的格式:
 33     *       "{    s|  123asd       |string parameter}
 34     *        {    d|  100          |digit parameter }
 35     *        {   @c|  false        |without camera  }
 36     *        {    1|  some text    |help            }
 37     *        {    2|  333          |another help    }"
 38     *参数or指令名称|指令or参数内容 |指令说明
 39     *
 40     *
 41     *  运行程序输入指令的方式如下:(例如程序名称为extest.exe)
 42     *  extest.exe -s=123asdd -d=1000 -@c=10
 43     *  注意:指令名称前面需要加一个“-”,或“--”。当输入指令后面没有参数,默认为true
 44     *       另外,前面加@的指令可以不输入指令名称,直接设置指令内容即可。
 45     *       没有输入的指令,则使用key_map中的默认值
 46     */
 47     CommandLineParser parser(argc, argv, keys);
 48 
 49 /*
 50     设置关于消息。
 51     当调用printMessage时,关于参数消息将显示在参数表之前。
 52 */
 53     parser.about(about);
 54     //指令数小于4时,打印关于信息
 55     if(argc < 4) {
 56         parser.printMessage();
 57         return 0;
 58     }
 59 
 60     //获取输入参数,通过CommandLineParser类中get函数获取
 61     //生成aruco码的型号
 62     int dictionaryId = parser.get<int>("d");
 63     //aruco码的id号
 64     int markerId = parser.get<int>("id");
 65     //标记边界中的位数
 66     int borderBits = parser.get<int>("bb");
 67     //像素大小
 68     int markerSize = parser.get<int>("ms");
 69     //是否展示生成图片
 70     bool showImage = parser.get<bool>("si");
 71     //获得@outfile的名称
 72     String out = parser.get<String>(0);
 73 
 74     //判断是否有错误,有则打印
 75     if(!parser.check()) {
 76         parser.printErrors();
 77         return 0;
 78     }
 79 
 80     //定义变量类型为Ptr<aruco::Dictionary>的指针,返回在PREDEFINED_DICTIONARY_NAME中定义的预定义词典之一
 81     Ptr<aruco::Dictionary> dictionary =
 82         aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
 83     
 84     //定义一个图片变量
 85     Mat markerImg;
 86 /*
 87     void cv::aruco::drawMarker(const Ptr<Dictionary> & dictionary, 
 88                                 int              id, 
 89                                 int              sidePixels, 
 90                                 OutputArra       img,
 91                                 int              borderBits = 1 
 92     )
 93     Parameters:
 94     dictionary  指示标记类型的标记字典
 95     id          将返回的标记的标识符。 它必须是指定字典中的有效ID
 96     sidePixels  图片尺寸(以像素为单位)
 97     img         输出带有标记的图像
 98     borderBits  标记边界的宽度
 99 */
100     aruco::drawMarker(dictionary, markerId, markerSize, markerImg, borderBits);
101 
102     if(showImage) {
103         imshow("marker", markerImg);
104         waitKey(0);
105     }
106 
107     imwrite(out, markerImg);
108 
109     return 0;
110 }

  生成板的源码:

  1 #include <opencv2/highgui.hpp>
  2 #include <opencv2/aruco.hpp>
  3 
  4 using namespace cv;
  5 
  6 namespace {
  7 const char* about = "Create an ArUco grid board image";
  8 const char* keys  =
  9         "{@outfile |<none> | Output image }"
 10         "{w        |       | Number of markers in X direction }"
 11         "{h        |       | Number of markers in Y direction }"
 12         "{l        |       | Marker side length (in pixels) }"
 13         "{s        |       | Separation between two consecutive markers in the grid (in pixels)}"
 14         "{d        |       | dictionary: DICT_4X4_50=0, DICT_4X4_100=1, DICT_4X4_250=2,"
 15         "DICT_4X4_1000=3, DICT_5X5_50=4, DICT_5X5_100=5, DICT_5X5_250=6, DICT_5X5_1000=7, "
 16         "DICT_6X6_50=8, DICT_6X6_100=9, DICT_6X6_250=10, DICT_6X6_1000=11, DICT_7X7_50=12,"
 17         "DICT_7X7_100=13, DICT_7X7_250=14, DICT_7X7_1000=15, DICT_ARUCO_ORIGINAL = 16}"
 18         "{m        |       | Margins size (in pixels). Default is marker separation (-s) }"
 19         "{bb       | 1     | Number of bits in marker borders }"
 20         "{si       | false | show generated image }";
 21 }
 22 
 23 int main(int argc, char *argv[]) {
 24 /*
 25     * 函数功能:构造函数
 26     * 参数:
 27     *   [in]     argc        main函数中的第一参数,即运行程序中获得指令的个数
 28     *   [in]     argv        main函数中的第二个参数,即运行程序中指令的内容
 29     *   [in]     key_map     当启动程序是没有输入任何指令,则使用key_map中默认的指指令。
 30     * 备注:
 31     *   key_map中的格式:
 32     *       "{    s|  123asd       |string parameter}
 33     *        {    d|  100          |digit parameter }
 34     *        {   @c|  false        |without camera  }
 35     *        {    1|  some text    |help            }
 36     *        {    2|  333          |another help    }"
 37     *参数or指令名称|指令or参数内容 |指令说明
 38     *
 39     *
 40     *  运行程序输入指令的方式如下:(例如程序名称为extest.exe)
 41     *  extest.exe -s=123asdd -d=1000 -@c=10
 42     *  注意:指令名称前面需要加一个“-”,或“--”。当输入指令后面没有参数,默认为true
 43     *       另外,前面加@的指令可以不输入指令名称,直接设置指令内容即可。
 44     *       没有输入的指令,则使用key_map中的默认值
 45 */    
 46     CommandLineParser parser(argc, argv, keys);
 47 
 48 /*
 49     设置关于消息。
 50     当调用printMessage时,关于参数消息将显示在参数表之前。
 51 */
 52     parser.about(about);
 53     //指令数小于7时,打印关于信息
 54     if(argc < 7) {
 55         parser.printMessage();
 56         return 0;
 57     }
 58 
 59     //X方向上的标记数
 60     int markersX = parser.get<int>("w");
 61     //Y方向上的标记数
 62     int markersY = parser.get<int>("h");
 63     //标记边长(以像素为单位)
 64     int markerLength = parser.get<int>("l");
 65     //网格中两个连续标记之间的分隔(以像素为单位)
 66     int markerSeparation = parser.get<int>("s");
 67     //预定义的字典
 68     int dictionaryId = parser.get<int>("d");
 69     //边距大小(以像素为单位)默认为标记分隔符(-s)    
 70     int margins = markerSeparation;
 71     if(parser.has("m")) {
 72         margins = parser.get<int>("m");
 73     }
 74     //标记边界中的位数
 75     int borderBits = parser.get<int>("bb");
 76     //显示生成的图像
 77     bool showImage = parser.get<bool>("si");
 78     //获得@outfile的名称
 79     String out = parser.get<String>(0);
 80     //判断是否有错误,有则打印
 81     if(!parser.check()) {
 82         parser.printErrors();
 83         return 0;
 84     }
 85     //确定页边距与标记的布局
 86     Size imageSize;
 87     imageSize.width = markersX * (markerLength + markerSeparation) - markerSeparation + 2 * margins;
 88     imageSize.height = markersY * (markerLength + markerSeparation) - markerSeparation + 2 * margins;
 90 
 91     //定义变量类型为Ptr<aruco::Dictionary>的指针,返回在PREDEFINED_DICTIONARY_NAME中定义的预定义词典之一
 92     Ptr<aruco::Dictionary> dictionary =
 93         aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
 94     
 95     //定义变量类型为Ptr<aruco::GridBoard>的指针,返回GridBoard对象
 96 /*
 97     static Ptr<GridBoard> cv::aruco::GridBoard::create(int markersX, 
 98                                                     int       markersY, 
 99                                                     float     markerLength, 
100                                                     float     markerSeparation, 
101                                                     const     Ptr<Dictionary> & dictionary, 
102                                                     int       firstMarker = 0)
103     Parameters:
104     markersX          X方向上的标记数
105     markersY          Y方向上的标记数
106     markerLength      标记边长(通常以米为单位)
107     markerSeparation  两个标记之间的分隔(与markerLength相同的单位)
108     dictionary        指示标记类型的标记字典
109     firstMarker       词典中要在板上使用的第一个标记的ID
110 */
111     Ptr<aruco::GridBoard> board = aruco::GridBoard::create(markersX, markersY, float(markerLength),
112                                                       float(markerSeparation), dictionary);
113 
114     // show created board
115 /*
116     void cv::aruco::GridBoard::draw(Size outSize, 
117                                     OutputArray    img, 
118                                     int            marginSize = 0, 
119                                     int            borderBits = 1)
120     Parameters
121     outSize        输出图像的大小(以像素为单位)
122     img            用面板输出图像。该图像的大小为outSize,并且板将在中间,并保持木板的比例
123     marginSize     输出图像中板的最小边距(以像素为单位)
124     borderBits     标记边框的宽度
125 */    
126     Mat boardImage;
127     board->draw(imageSize, boardImage, margins, borderBits);
128 
129     if(showImage) {
130         imshow("board", boardImage);
131         waitKey(0);
132     }
133 
134     imwrite(out, boardImage);
135 
136     return 0;
137 }

文中源码来源与github中fdcl-gwu/aruco-markers,链接为https://github.com/fdcl-gwu/aruco-markers#generating-markers,如有侵权,联系删除

posted @ 2020-12-15 15:57  涅风  阅读(2608)  评论(0编辑  收藏  举报