dictionary.cpp
Go to the documentation of this file.
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 #include "precomp.hpp"
41 #include <opencv2/core.hpp>
42 #include <opencv2/imgproc.hpp>
45 #include "opencv2/core/hal/hal.hpp"
46 
47 namespace cv {
48 namespace aruco {
49 
50 using namespace std;
51 
52 
55 Dictionary::Dictionary(const Ptr<Dictionary> &_dictionary) {
56  markerSize = _dictionary->markerSize;
57  maxCorrectionBits = _dictionary->maxCorrectionBits;
58  bytesList = _dictionary->bytesList.clone();
59 }
60 
61 
64 Dictionary::Dictionary(const Mat &_bytesList, int _markerSize, int _maxcorr) {
65  markerSize = _markerSize;
66  maxCorrectionBits = _maxcorr;
67  bytesList = _bytesList;
68 }
69 
70 
73 Ptr<Dictionary> Dictionary::create(int nMarkers, int markerSize, int randomSeed) {
74  const Ptr<Dictionary> baseDictionary = makePtr<Dictionary>();
75  return create(nMarkers, markerSize, baseDictionary, randomSeed);
76 }
77 
78 
81 Ptr<Dictionary> Dictionary::create(int nMarkers, int markerSize,
82  const Ptr<Dictionary> &baseDictionary, int randomSeed) {
83 
84  return generateCustomDictionary(nMarkers, markerSize, baseDictionary, randomSeed);
85 }
86 
87 
90 Ptr<Dictionary> Dictionary::get(int dict) {
91  return getPredefinedDictionary(dict);
92 }
93 
94 
97 bool Dictionary::identify(const Mat &onlyBits, int &idx, int &rotation,
98  double maxCorrectionRate) const {
99 
100  CV_Assert(onlyBits.rows == markerSize && onlyBits.cols == markerSize);
101 
102  int maxCorrectionRecalculed = int(double(maxCorrectionBits) * maxCorrectionRate);
103 
104  // get as a byte list
105  Mat candidateBytes = getByteListFromBits(onlyBits);
106 
107  idx = -1; // by default, not found
108 
109  // search closest marker in dict
110  for(int m = 0; m < bytesList.rows; m++) {
111  int currentMinDistance = markerSize * markerSize + 1;
112  int currentRotation = -1;
113  for(unsigned int r = 0; r < 4; r++) {
114  int currentHamming = cv::hal::normHamming(
115  bytesList.ptr(m)+r*candidateBytes.cols,
116  candidateBytes.ptr(),
117  candidateBytes.cols);
118 
119  if(currentHamming < currentMinDistance) {
120  currentMinDistance = currentHamming;
121  currentRotation = r;
122  }
123  }
124 
125  // if maxCorrection is fullfilled, return this one
126  if(currentMinDistance <= maxCorrectionRecalculed) {
127  idx = m;
128  rotation = currentRotation;
129  break;
130  }
131  }
132 
133  return idx != -1;
134 }
135 
136 
139 int Dictionary::getDistanceToId(InputArray bits, int id, bool allRotations) const {
140 
141  CV_Assert(id >= 0 && id < bytesList.rows);
142 
143  unsigned int nRotations = 4;
144  if(!allRotations) nRotations = 1;
145 
146  Mat candidateBytes = getByteListFromBits(bits.getMat());
147  int currentMinDistance = int(bits.total() * bits.total());
148  for(unsigned int r = 0; r < nRotations; r++) {
149  int currentHamming = cv::hal::normHamming(
150  bytesList.ptr(id) + r*candidateBytes.cols,
151  candidateBytes.ptr(),
152  candidateBytes.cols);
153 
154  if(currentHamming < currentMinDistance) {
155  currentMinDistance = currentHamming;
156  }
157  }
158  return currentMinDistance;
159 }
160 
161 
162 
166 void Dictionary::drawMarker(int id, int sidePixels, OutputArray _img, int borderBits) const {
167 
168  CV_Assert(sidePixels >= (markerSize + 2*borderBits));
169  CV_Assert(id < bytesList.rows);
170  CV_Assert(borderBits > 0);
171 
172  _img.create(sidePixels, sidePixels, CV_8UC1);
173 
174  // create small marker with 1 pixel per bin
175  Mat tinyMarker(markerSize + 2 * borderBits, markerSize + 2 * borderBits, CV_8UC1,
176  Scalar::all(0));
177  Mat innerRegion = tinyMarker.rowRange(borderBits, tinyMarker.rows - borderBits)
178  .colRange(borderBits, tinyMarker.cols - borderBits);
179  // put inner bits
180  Mat bits = 255 * getBitsFromByteList(bytesList.rowRange(id, id + 1), markerSize);
181  CV_Assert(innerRegion.total() == bits.total());
182  bits.copyTo(innerRegion);
183 
184  // resize tiny marker to output size
185  cv::resize(tinyMarker, _img.getMat(), _img.getMat().size(), 0, 0, INTER_NEAREST);
186 }
187 
188 
189 
190 
194 Mat Dictionary::getByteListFromBits(const Mat &bits) {
195  // integer ceil
196  int nbytes = (bits.cols * bits.rows + 8 - 1) / 8;
197 
198  Mat candidateByteList(1, nbytes, CV_8UC4, Scalar::all(0));
199  unsigned char currentBit = 0;
200  int currentByte = 0;
201 
202  // the 4 rotations
203  uchar* rot0 = candidateByteList.ptr();
204  uchar* rot1 = candidateByteList.ptr() + 1*nbytes;
205  uchar* rot2 = candidateByteList.ptr() + 2*nbytes;
206  uchar* rot3 = candidateByteList.ptr() + 3*nbytes;
207 
208  for(int row = 0; row < bits.rows; row++) {
209  for(int col = 0; col < bits.cols; col++) {
210  // circular shift
211  rot0[currentByte] <<= 1;
212  rot1[currentByte] <<= 1;
213  rot2[currentByte] <<= 1;
214  rot3[currentByte] <<= 1;
215  // set bit
216  rot0[currentByte] |= bits.at<uchar>(row, col);
217  rot1[currentByte] |= bits.at<uchar>(col, bits.cols - 1 - row);
218  rot2[currentByte] |= bits.at<uchar>(bits.rows - 1 - row, bits.cols - 1 - col);
219  rot3[currentByte] |= bits.at<uchar>(bits.rows - 1 - col, row);
220  currentBit++;
221  if(currentBit == 8) {
222  // next byte
223  currentBit = 0;
224  currentByte++;
225  }
226  }
227  }
228  return candidateByteList;
229 }
230 
231 
232 
236 Mat Dictionary::getBitsFromByteList(const Mat &byteList, int markerSize) {
237  CV_Assert(byteList.total() > 0 &&
238  byteList.total() >= (unsigned int)markerSize * markerSize / 8 &&
239  byteList.total() <= (unsigned int)markerSize * markerSize / 8 + 1);
240  Mat bits(markerSize, markerSize, CV_8UC1, Scalar::all(0));
241 
242  unsigned char base2List[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
243  int currentByteIdx = 0;
244  // we only need the bytes in normal rotation
245  unsigned char currentByte = byteList.ptr()[0];
246  int currentBit = 0;
247  for(int row = 0; row < bits.rows; row++) {
248  for(int col = 0; col < bits.cols; col++) {
249  if(currentByte >= base2List[currentBit]) {
250  bits.at< unsigned char >(row, col) = 1;
251  currentByte -= base2List[currentBit];
252  }
253  currentBit++;
254  if(currentBit == 8) {
255  currentByteIdx++;
256  currentByte = byteList.ptr()[currentByteIdx];
257  // if not enough bits for one more byte, we are in the end
258  // update bit position accordingly
259  if(8 * (currentByteIdx + 1) > (int)bits.total())
260  currentBit = 8 * (currentByteIdx + 1) - (int)bits.total();
261  else
262  currentBit = 0; // ok, bits enough for next byte
263  }
264  }
265  }
266  return bits;
267 }
268 
269 
270 
271 
272 // DictionaryData constructors calls
273 const Dictionary DICT_ARUCO_DATA = Dictionary(Mat(1024, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_ARUCO_BYTES), 5, 0);
274 
275 const Dictionary DICT_4X4_50_DATA = Dictionary(Mat(50, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 1);
276 const Dictionary DICT_4X4_100_DATA = Dictionary(Mat(100, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 1);
277 const Dictionary DICT_4X4_250_DATA = Dictionary(Mat(250, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 1);
278 const Dictionary DICT_4X4_1000_DATA = Dictionary(Mat(1000, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_4X4_1000_BYTES), 4, 0);
279 
280 const Dictionary DICT_5X5_50_DATA = Dictionary(Mat(50, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 3);
281 const Dictionary DICT_5X5_100_DATA = Dictionary(Mat(100, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 3);
282 const Dictionary DICT_5X5_250_DATA = Dictionary(Mat(250, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 2);
283 const Dictionary DICT_5X5_1000_DATA = Dictionary(Mat(1000, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_5X5_1000_BYTES), 5, 2);
284 
285 const Dictionary DICT_6X6_50_DATA = Dictionary(Mat(50, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 6);
286 const Dictionary DICT_6X6_100_DATA = Dictionary(Mat(100, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 5);
287 const Dictionary DICT_6X6_250_DATA = Dictionary(Mat(250, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 5);
288 const Dictionary DICT_6X6_1000_DATA = Dictionary(Mat(1000, (6*6 + 7)/8 ,CV_8UC4, (uchar*)DICT_6X6_1000_BYTES), 6, 4);
289 
290 const Dictionary DICT_7X7_50_DATA = Dictionary(Mat(50, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 9);
291 const Dictionary DICT_7X7_100_DATA = Dictionary(Mat(100, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 8);
292 const Dictionary DICT_7X7_250_DATA = Dictionary(Mat(250, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 8);
293 const Dictionary DICT_7X7_1000_DATA = Dictionary(Mat(1000, (7*7 + 7)/8 ,CV_8UC4, (uchar*)DICT_7X7_1000_BYTES), 7, 6);
294 
295 const Dictionary DICT_APRILTAG_16h5_DATA = Dictionary(Mat(30, (4*4 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_16h5_BYTES), 4, 0);
296 const Dictionary DICT_APRILTAG_25h9_DATA = Dictionary(Mat(35, (5*5 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_25h9_BYTES), 5, 0);
297 const Dictionary DICT_APRILTAG_36h10_DATA = Dictionary(Mat(2320, (6*6 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_36h10_BYTES), 6, 0);
298 const Dictionary DICT_APRILTAG_36h11_DATA = Dictionary(Mat(587, (6*6 + 7)/8, CV_8UC4, (uchar*)DICT_APRILTAG_36h11_BYTES), 6, 0);
299 
300 
302  switch(name) {
303 
304  case DICT_ARUCO_ORIGINAL:
305  return makePtr<Dictionary>(DICT_ARUCO_DATA);
306 
307  case DICT_4X4_50:
308  return makePtr<Dictionary>(DICT_4X4_50_DATA);
309  case DICT_4X4_100:
310  return makePtr<Dictionary>(DICT_4X4_100_DATA);
311  case DICT_4X4_250:
312  return makePtr<Dictionary>(DICT_4X4_250_DATA);
313  case DICT_4X4_1000:
314  return makePtr<Dictionary>(DICT_4X4_1000_DATA);
315 
316  case DICT_5X5_50:
317  return makePtr<Dictionary>(DICT_5X5_50_DATA);
318  case DICT_5X5_100:
319  return makePtr<Dictionary>(DICT_5X5_100_DATA);
320  case DICT_5X5_250:
321  return makePtr<Dictionary>(DICT_5X5_250_DATA);
322  case DICT_5X5_1000:
323  return makePtr<Dictionary>(DICT_5X5_1000_DATA);
324 
325  case DICT_6X6_50:
326  return makePtr<Dictionary>(DICT_6X6_50_DATA);
327  case DICT_6X6_100:
328  return makePtr<Dictionary>(DICT_6X6_100_DATA);
329  case DICT_6X6_250:
330  return makePtr<Dictionary>(DICT_6X6_250_DATA);
331  case DICT_6X6_1000:
332  return makePtr<Dictionary>(DICT_6X6_1000_DATA);
333 
334  case DICT_7X7_50:
335  return makePtr<Dictionary>(DICT_7X7_50_DATA);
336  case DICT_7X7_100:
337  return makePtr<Dictionary>(DICT_7X7_100_DATA);
338  case DICT_7X7_250:
339  return makePtr<Dictionary>(DICT_7X7_250_DATA);
340  case DICT_7X7_1000:
341  return makePtr<Dictionary>(DICT_7X7_1000_DATA);
342 
343  case DICT_APRILTAG_16h5:
344  return makePtr<Dictionary>(DICT_APRILTAG_16h5_DATA);
345  case DICT_APRILTAG_25h9:
346  return makePtr<Dictionary>(DICT_APRILTAG_25h9_DATA);
347  case DICT_APRILTAG_36h10:
348  return makePtr<Dictionary>(DICT_APRILTAG_36h10_DATA);
349  case DICT_APRILTAG_36h11:
350  return makePtr<Dictionary>(DICT_APRILTAG_36h11_DATA);
351 
352  }
353  return makePtr<Dictionary>(DICT_4X4_50_DATA);
354 }
355 
356 
357 Ptr<Dictionary> getPredefinedDictionary(int dict) {
359 }
360 
361 
365 static Mat _generateRandomMarker(int markerSize, RNG &rng) {
366  Mat marker(markerSize, markerSize, CV_8UC1, Scalar::all(0));
367  for(int i = 0; i < markerSize; i++) {
368  for(int j = 0; j < markerSize; j++) {
369  unsigned char bit = (unsigned char) (rng.uniform(0,2));
370  marker.at< unsigned char >(i, j) = bit;
371  }
372  }
373  return marker;
374 }
375 
383 static int _getSelfDistance(const Mat &marker) {
384  Mat bytes = Dictionary::getByteListFromBits(marker);
385  int minHamming = (int)marker.total() + 1;
386  for(int r = 1; r < 4; r++) {
387  int currentHamming = cv::hal::normHamming(bytes.ptr(), bytes.ptr() + bytes.cols*r, bytes.cols);
388  if(currentHamming < minHamming) minHamming = currentHamming;
389  }
390  return minHamming;
391 }
392 
395 Ptr<Dictionary> generateCustomDictionary(int nMarkers, int markerSize,
396  const Ptr<Dictionary> &baseDictionary, int randomSeed) {
397  RNG rng((uint64)(randomSeed));
398 
399  Ptr<Dictionary> out = makePtr<Dictionary>();
400  out->markerSize = markerSize;
401 
402  // theoretical maximum intermarker distance
403  // See S. Garrido-Jurado, R. Muñoz-Salinas, F. J. Madrid-Cuevas, and M. J. Marín-Jiménez. 2014.
404  // "Automatic generation and detection of highly reliable fiducial markers under occlusion".
405  // Pattern Recogn. 47, 6 (June 2014), 2280-2292. DOI=10.1016/j.patcog.2014.01.005
406  int C = (int)std::floor(float(markerSize * markerSize) / 4.f);
407  int tau = 2 * (int)std::floor(float(C) * 4.f / 3.f);
408 
409  // if baseDictionary is provided, calculate its intermarker distance
410  if(baseDictionary->bytesList.rows > 0) {
411  CV_Assert(baseDictionary->markerSize == markerSize);
412  out->bytesList = baseDictionary->bytesList.clone();
413 
414  int minDistance = markerSize * markerSize + 1;
415  for(int i = 0; i < out->bytesList.rows; i++) {
416  Mat markerBytes = out->bytesList.rowRange(i, i + 1);
417  Mat markerBits = Dictionary::getBitsFromByteList(markerBytes, markerSize);
418  minDistance = min(minDistance, _getSelfDistance(markerBits));
419  for(int j = i + 1; j < out->bytesList.rows; j++) {
420  minDistance = min(minDistance, out->getDistanceToId(markerBits, j));
421  }
422  }
423  tau = minDistance;
424  }
425 
426  // current best option
427  int bestTau = 0;
428  Mat bestMarker;
429 
430  // after these number of unproductive iterations, the best option is accepted
431  const int maxUnproductiveIterations = 5000;
432  int unproductiveIterations = 0;
433 
434  while(out->bytesList.rows < nMarkers) {
435  Mat currentMarker = _generateRandomMarker(markerSize, rng);
436 
437  int selfDistance = _getSelfDistance(currentMarker);
438  int minDistance = selfDistance;
439 
440  // if self distance is better or equal than current best option, calculate distance
441  // to previous accepted markers
442  if(selfDistance >= bestTau) {
443  for(int i = 0; i < out->bytesList.rows; i++) {
444  int currentDistance = out->getDistanceToId(currentMarker, i);
445  minDistance = min(currentDistance, minDistance);
446  if(minDistance <= bestTau) {
447  break;
448  }
449  }
450  }
451 
452  // if distance is high enough, accept the marker
453  if(minDistance >= tau) {
454  unproductiveIterations = 0;
455  bestTau = 0;
456  Mat bytes = Dictionary::getByteListFromBits(currentMarker);
457  out->bytesList.push_back(bytes);
458  } else {
459  unproductiveIterations++;
460 
461  // if distance is not enough, but is better than the current best option
462  if(minDistance > bestTau) {
463  bestTau = minDistance;
464  bestMarker = currentMarker;
465  }
466 
467  // if number of unproductive iterarions has been reached, accept the current best option
468  if(unproductiveIterations == maxUnproductiveIterations) {
469  unproductiveIterations = 0;
470  tau = bestTau;
471  bestTau = 0;
472  Mat bytes = Dictionary::getByteListFromBits(bestMarker);
473  out->bytesList.push_back(bytes);
474  }
475  }
476  }
477 
478  // update the maximum number of correction bits for the generated dictionary
479  out->maxCorrectionBits = (tau - 1) / 2;
480 
481  return out;
482 }
483 
484 
487 Ptr<Dictionary> generateCustomDictionary(int nMarkers, int markerSize, int randomSeed) {
488  Ptr<Dictionary> baseDictionary = makePtr<Dictionary>();
489  return generateCustomDictionary(nMarkers, markerSize, baseDictionary, randomSeed);
490 }
491 
492 
493 }
494 }
const Dictionary DICT_4X4_50_DATA
Definition: dictionary.cpp:275
const Dictionary DICT_4X4_250_DATA
Definition: dictionary.cpp:277
6x6 bits, minimum hamming distance between any two codes = 11, 587 codes
Definition: dictionary.hpp:162
const Dictionary DICT_7X7_100_DATA
Definition: dictionary.cpp:291
const Dictionary DICT_6X6_250_DATA
Definition: dictionary.cpp:287
5x5 bits, minimum hamming distance between any two codes = 9, 35 codes
Definition: dictionary.hpp:160
const Dictionary DICT_5X5_250_DATA
Definition: dictionary.cpp:282
const Dictionary DICT_4X4_100_DATA
Definition: dictionary.cpp:276
const Dictionary DICT_5X5_50_DATA
Definition: dictionary.cpp:280
4x4 bits, minimum hamming distance between any two codes = 5, 30 codes
Definition: dictionary.hpp:159
CV_WRAP void drawMarker(int id, int sidePixels, OutputArray _img, int borderBits=1) const
Draw a canonical marker image.
Definition: dictionary.cpp:166
static CV_WRAP Mat getByteListFromBits(const Mat &bits)
Transform matrix of bits to list of bytes in the 4 rotations.
Definition: dictionary.cpp:194
int getDistanceToId(InputArray bits, int id, bool allRotations=true) const
Returns the distance of the input bits to the specific id. If allRotations is true, the four posible bits rotation are considered.
Definition: dictionary.cpp:139
Definition: charuco.hpp:47
static CV_WRAP Mat getBitsFromByteList(const Mat &byteList, int markerSize)
Transform list of bytes to matrix of bits.
Definition: dictionary.cpp:236
CV_EXPORTS Ptr< Dictionary > getPredefinedDictionary(PREDEFINED_DICTIONARY_NAME name)
Returns one of the predefined dictionaries defined in PREDEFINED_DICTIONARY_NAME. ...
Definition: dictionary.cpp:301
const Dictionary DICT_6X6_100_DATA
Definition: dictionary.cpp:286
const Dictionary DICT_5X5_100_DATA
Definition: dictionary.cpp:281
PREDEFINED_DICTIONARY_NAME
Predefined markers dictionaries/sets Each dictionary indicates the number of bits and the number of m...
Definition: dictionary.hpp:141
const Dictionary DICT_APRILTAG_36h11_DATA
Definition: dictionary.cpp:298
static int _getSelfDistance(const Mat &marker)
Calculate selfDistance of the codification of a marker Mat. Self distance is the Hamming distance of ...
Definition: dictionary.cpp:383
const Dictionary DICT_7X7_50_DATA
Definition: dictionary.cpp:290
Ptr< Dictionary > generateCustomDictionary(int nMarkers, int markerSize, const Ptr< Dictionary > &baseDictionary, int randomSeed)
Definition: dictionary.cpp:395
const Dictionary DICT_5X5_1000_DATA
Definition: dictionary.cpp:283
bool identify(const Mat &onlyBits, int &idx, int &rotation, double maxCorrectionRate) const
Given a matrix of bits. Returns whether if marker is identified or not. It returns by reference the c...
Definition: dictionary.cpp:97
const Dictionary DICT_6X6_50_DATA
Definition: dictionary.cpp:285
const Dictionary DICT_6X6_1000_DATA
Definition: dictionary.cpp:288
double min(double a, double b)
int int randomSeed
Definition: dictionary.hpp:184
static Mat _generateRandomMarker(int markerSize, RNG &rng)
Generates a random marker Mat of size markerSize x markerSize.
Definition: dictionary.cpp:365
Dictionary(const Mat &_bytesList=Mat(), int _markerSize=0, int _maxcorr=0)
Definition: dictionary.cpp:64
const Dictionary DICT_4X4_1000_DATA
Definition: dictionary.cpp:278
const Dictionary DICT_APRILTAG_16h5_DATA
Definition: dictionary.cpp:295
6x6 bits, minimum hamming distance between any two codes = 10, 2320 codes
Definition: dictionary.hpp:161
const Dictionary DICT_7X7_250_DATA
Definition: dictionary.cpp:292
int markerSize
Definition: dictionary.hpp:183
const Dictionary DICT_ARUCO_DATA
Definition: dictionary.cpp:273
static CV_WRAP Ptr< Dictionary > get(int dict)
Definition: dictionary.cpp:90
int const Ptr< Dictionary > & baseDictionary
Definition: dictionary.hpp:202
const Dictionary DICT_7X7_1000_DATA
Definition: dictionary.cpp:293
Dictionary/Set of markers. It contains the inner codification.
Definition: dictionary.hpp:61
const Dictionary DICT_APRILTAG_36h10_DATA
Definition: dictionary.cpp:297
const Dictionary DICT_APRILTAG_25h9_DATA
Definition: dictionary.cpp:296


aruco_pose
Author(s): Oleg Kalachev
autogenerated on Mon Feb 28 2022 22:08:24