| 1 | // This file is part of OpenCV project. |
| 2 | // It is subject to the license terms in the LICENSE file found in the top-level directory |
| 3 | // of this distribution and at http://opencv.org/license.html |
| 4 | #ifndef OPENCV_OBJDETECT_DICTIONARY_HPP |
| 5 | #define OPENCV_OBJDETECT_DICTIONARY_HPP |
| 6 | |
| 7 | #include <opencv2/core.hpp> |
| 8 | |
| 9 | namespace cv { |
| 10 | namespace aruco { |
| 11 | |
| 12 | //! @addtogroup objdetect_aruco |
| 13 | //! @{ |
| 14 | |
| 15 | |
| 16 | /** @brief Dictionary is a set of unique ArUco markers of the same size |
| 17 | * |
| 18 | * `bytesList` storing as 2-dimensions Mat with 4-th channels (CV_8UC4 type was used) and contains the marker codewords where: |
| 19 | * - bytesList.rows is the dictionary size |
| 20 | * - each marker is encoded using `nbytes = ceil(markerSize*markerSize/8.)` bytes |
| 21 | * - each row contains all 4 rotations of the marker, so its length is `4*nbytes` |
| 22 | * - the byte order in the bytesList[i] row: |
| 23 | * `//bytes without rotation/bytes with rotation 1/bytes with rotation 2/bytes with rotation 3//` |
| 24 | * So `bytesList.ptr(i)[k*nbytes + j]` is the j-th byte of i-th marker, in its k-th rotation. |
| 25 | * @note Python bindings generate matrix with shape of bytesList `dictionary_size x nbytes x 4`, |
| 26 | * but it should be indexed like C++ version. Python example for j-th byte of i-th marker, in its k-th rotation: |
| 27 | * `aruco_dict.bytesList[id].ravel()[k*nbytes + j]` |
| 28 | */ |
| 29 | class CV_EXPORTS_W_SIMPLE Dictionary { |
| 30 | |
| 31 | public: |
| 32 | CV_PROP_RW Mat bytesList; ///< marker code information. See class description for more details |
| 33 | CV_PROP_RW int markerSize; ///< number of bits per dimension |
| 34 | CV_PROP_RW int maxCorrectionBits; ///< maximum number of bits that can be corrected |
| 35 | |
| 36 | CV_WRAP Dictionary(); |
| 37 | |
| 38 | /** @brief Basic ArUco dictionary constructor |
| 39 | * |
| 40 | * @param bytesList bits for all ArUco markers in dictionary see memory layout in the class description |
| 41 | * @param _markerSize ArUco marker size in units |
| 42 | * @param maxcorr maximum number of bits that can be corrected |
| 43 | */ |
| 44 | CV_WRAP Dictionary(const Mat &bytesList, int _markerSize, int maxcorr = 0); |
| 45 | |
| 46 | /** @brief Read a new dictionary from FileNode. |
| 47 | * |
| 48 | * Dictionary example in YAML format:\n |
| 49 | * nmarkers: 35\n |
| 50 | * markersize: 6\n |
| 51 | * maxCorrectionBits: 5\n |
| 52 | * marker_0: "101011111011111001001001101100000000"\n |
| 53 | * ...\n |
| 54 | * marker_34: "011111010000111011111110110101100101" |
| 55 | */ |
| 56 | CV_WRAP bool readDictionary(const cv::FileNode& fn); |
| 57 | |
| 58 | /** @brief Write a dictionary to FileStorage, format is the same as in readDictionary(). |
| 59 | */ |
| 60 | CV_WRAP void writeDictionary(FileStorage& fs, const String& name = String()); |
| 61 | |
| 62 | /** @brief Given a matrix of bits. Returns whether if marker is identified or not. |
| 63 | * |
| 64 | * Returns reference to the marker id in the dictionary (if any) and its rotation. |
| 65 | */ |
| 66 | CV_WRAP bool identify(const Mat &onlyBits, CV_OUT int &idx, CV_OUT int &rotation, double maxCorrectionRate) const; |
| 67 | |
| 68 | /** @brief Returns Hamming distance of the input bits to the specific id. |
| 69 | * |
| 70 | * If `allRotations` flag is set, the four posible marker rotations are considered |
| 71 | */ |
| 72 | CV_WRAP int getDistanceToId(InputArray bits, int id, bool allRotations = true) const; |
| 73 | |
| 74 | |
| 75 | /** @brief Generate a canonical marker image |
| 76 | */ |
| 77 | CV_WRAP void generateImageMarker(int id, int sidePixels, OutputArray _img, int borderBits = 1) const; |
| 78 | |
| 79 | |
| 80 | /** @brief Transform matrix of bits to list of bytes with 4 marker rotations |
| 81 | */ |
| 82 | CV_WRAP static Mat getByteListFromBits(const Mat &bits); |
| 83 | |
| 84 | |
| 85 | /** @brief Transform list of bytes to matrix of bits |
| 86 | */ |
| 87 | CV_WRAP static Mat getBitsFromByteList(const Mat &byteList, int markerSize); |
| 88 | }; |
| 89 | |
| 90 | |
| 91 | |
| 92 | |
| 93 | /** @brief Predefined markers dictionaries/sets |
| 94 | * |
| 95 | * Each dictionary indicates the number of bits and the number of markers contained |
| 96 | * - DICT_ARUCO_ORIGINAL: standard ArUco Library Markers. 1024 markers, 5x5 bits, 0 minimum |
| 97 | distance |
| 98 | */ |
| 99 | enum PredefinedDictionaryType { |
| 100 | DICT_4X4_50 = 0, ///< 4x4 bits, minimum hamming distance between any two codes = 4, 50 codes |
| 101 | DICT_4X4_100, ///< 4x4 bits, minimum hamming distance between any two codes = 3, 100 codes |
| 102 | DICT_4X4_250, ///< 4x4 bits, minimum hamming distance between any two codes = 3, 250 codes |
| 103 | DICT_4X4_1000, ///< 4x4 bits, minimum hamming distance between any two codes = 2, 1000 codes |
| 104 | DICT_5X5_50, ///< 5x5 bits, minimum hamming distance between any two codes = 8, 50 codes |
| 105 | DICT_5X5_100, ///< 5x5 bits, minimum hamming distance between any two codes = 7, 100 codes |
| 106 | DICT_5X5_250, ///< 5x5 bits, minimum hamming distance between any two codes = 6, 250 codes |
| 107 | DICT_5X5_1000, ///< 5x5 bits, minimum hamming distance between any two codes = 5, 1000 codes |
| 108 | DICT_6X6_50, ///< 6x6 bits, minimum hamming distance between any two codes = 13, 50 codes |
| 109 | DICT_6X6_100, ///< 6x6 bits, minimum hamming distance between any two codes = 12, 100 codes |
| 110 | DICT_6X6_250, ///< 6x6 bits, minimum hamming distance between any two codes = 11, 250 codes |
| 111 | DICT_6X6_1000, ///< 6x6 bits, minimum hamming distance between any two codes = 9, 1000 codes |
| 112 | DICT_7X7_50, ///< 7x7 bits, minimum hamming distance between any two codes = 19, 50 codes |
| 113 | DICT_7X7_100, ///< 7x7 bits, minimum hamming distance between any two codes = 18, 100 codes |
| 114 | DICT_7X7_250, ///< 7x7 bits, minimum hamming distance between any two codes = 17, 250 codes |
| 115 | DICT_7X7_1000, ///< 7x7 bits, minimum hamming distance between any two codes = 14, 1000 codes |
| 116 | DICT_ARUCO_ORIGINAL, ///< 6x6 bits, minimum hamming distance between any two codes = 3, 1024 codes |
| 117 | DICT_APRILTAG_16h5, ///< 4x4 bits, minimum hamming distance between any two codes = 5, 30 codes |
| 118 | DICT_APRILTAG_25h9, ///< 5x5 bits, minimum hamming distance between any two codes = 9, 35 codes |
| 119 | DICT_APRILTAG_36h10, ///< 6x6 bits, minimum hamming distance between any two codes = 10, 2320 codes |
| 120 | DICT_APRILTAG_36h11, ///< 6x6 bits, minimum hamming distance between any two codes = 11, 587 codes |
| 121 | DICT_ARUCO_MIP_36h12 ///< 6x6 bits, minimum hamming distance between any two codes = 12, 250 codes |
| 122 | }; |
| 123 | |
| 124 | |
| 125 | /** @brief Returns one of the predefined dictionaries defined in PredefinedDictionaryType |
| 126 | */ |
| 127 | CV_EXPORTS Dictionary getPredefinedDictionary(PredefinedDictionaryType name); |
| 128 | |
| 129 | |
| 130 | /** @brief Returns one of the predefined dictionaries referenced by DICT_*. |
| 131 | */ |
| 132 | CV_EXPORTS_W Dictionary getPredefinedDictionary(int dict); |
| 133 | |
| 134 | /** @brief Extend base dictionary by new nMarkers |
| 135 | * |
| 136 | * @param nMarkers number of markers in the dictionary |
| 137 | * @param markerSize number of bits per dimension of each markers |
| 138 | * @param baseDictionary Include the markers in this dictionary at the beginning (optional) |
| 139 | * @param randomSeed a user supplied seed for theRNG() |
| 140 | * |
| 141 | * This function creates a new dictionary composed by nMarkers markers and each markers composed |
| 142 | * by markerSize x markerSize bits. If baseDictionary is provided, its markers are directly |
| 143 | * included and the rest are generated based on them. If the size of baseDictionary is higher |
| 144 | * than nMarkers, only the first nMarkers in baseDictionary are taken and no new marker is added. |
| 145 | */ |
| 146 | CV_EXPORTS_W Dictionary extendDictionary(int nMarkers, int markerSize, const Dictionary &baseDictionary = Dictionary(), |
| 147 | int randomSeed=0); |
| 148 | |
| 149 | |
| 150 | |
| 151 | //! @} |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | #endif |
| 156 | |