38 unsigned int HighlyReliableMarkers::_n, HighlyReliableMarkers::_ncellsBorder, HighlyReliableMarkers::_correctionDistance;
    39 int HighlyReliableMarkers::_swidth;
    44 MarkerCode::MarkerCode(
unsigned int n) {
    46     for (
unsigned int i = 0; i < 4; i++) {
    47         _bits[i].resize(n * n);
    48         for (
unsigned int j = 0; j < _bits[i].size(); j++)
    59     for (
unsigned int i = 0; i < 4; i++) {
    60         _bits[i] = MC.
_bits[i];
    70 void MarkerCode::set(
unsigned int pos, 
bool val, 
bool updateIds) {
    72     if (
get(pos) != val) {
    73         for (
unsigned int i = 0; i < 4; i++) {         
    74             unsigned int y = pos / n(), 
x = pos % n(); 
    88             unsigned int rotPos = y * n() + 
x; 
    89             _bits[i][rotPos] = val;            
    93                     _ids[i] += (
unsigned int)
pow(
float(2), float(rotPos)); 
    95                     _ids[i] -= (
unsigned int)
pow(
float(2), float(rotPos)); 
   104 unsigned int MarkerCode::selfDistance(
unsigned int &minRot)
 const {
   105     unsigned int res = _bits[0].size();    
   106     for (
unsigned int i = 1; i < 4; i++) { 
   107         unsigned int hammdist = hammingDistance(_bits[0], _bits[i]);
   108         if (hammdist < res) {
   119 unsigned int MarkerCode::distance(
const MarkerCode &m, 
unsigned int &minRot)
 const {
   120     unsigned int res = _bits[0].size(); 
   121     for (
unsigned int i = 0; i < 4; i++) {
   122         unsigned int hammdist = hammingDistance(_bits[0], m.
getRotation(i));
   123         if (hammdist < res) {
   135     for (
unsigned int i = 0; i < s.length(); i++) {
   145 std::string MarkerCode::toString()
 const {
   148     for (
unsigned int i = 0; i < size(); i++) {
   160 cv::Mat MarkerCode::getImg(
unsigned int pixSize)
 const {
   161     const unsigned int borderSize = 1;
   162     unsigned int nrows = n() + 2 * borderSize;
   163     if (pixSize % nrows != 0)
   164         pixSize = pixSize + nrows - pixSize % nrows;
   165     unsigned int cellSize = pixSize / nrows;
   166     cv::Mat img(pixSize, pixSize, CV_8U, cv::Scalar::all(0)); 
   168     for (
unsigned int i = 0; i < n(); i++) {
   169         for (
unsigned int j = 0; j < n(); j++) {
   170             if (_bits[0][i * n() + j] != 0) { 
   172                 for (
unsigned int k = 0; k < cellSize; k++) {
   173                     for (
unsigned int l = 0; l < cellSize; l++) {
   174                         img.at< uchar >((i + borderSize) * cellSize + k, (j + borderSize) * cellSize + l) = 255;
   186 unsigned int MarkerCode::hammingDistance(
const std::vector< bool > &m1, 
const std::vector< bool > &m2)
 const {
   187     unsigned int res = 0;
   188     for (
unsigned int i = 0; i < m1.size(); i++)
   199 bool Dictionary::fromFile(std::string filename) {
   200     cv::FileStorage fs(filename, cv::FileStorage::READ);
   201     int nmarkers, markersize;
   204     fs[
"nmarkers"] >> nmarkers;                     
   205     fs[
"markersize"] >> markersize;                 
   209     for (
int i = 0; i < nmarkers; i++) {
   211         fs[
"marker_" + toStr(i)] >> s;
   222 bool Dictionary::toFile(std::string filename) {
   223     cv::FileStorage fs(filename, cv::FileStorage::WRITE);
   225     fs << 
"nmarkers" << (int)size();                               
   226     fs << 
"markersize" << (int)((*
this)[0].n());                   
   227     fs << 
"tau0" << (int)(this->tau0); 
   229     for (
unsigned int i = 0; i < size(); i++) {
   230         std::string 
s = ((*this)[i]).toString();
   231         fs << 
"marker_" + toStr(i) << s;
   239 unsigned int Dictionary::distance(
const MarkerCode &m, 
unsigned int &minMarker, 
unsigned int &minRot) {
   240     unsigned int res = m.
size();
   241     for (
unsigned int i = 0; i < size(); i++) {
   242         unsigned int minRotAux;
   243         unsigned int distance = (*this)[i].distance(m, minRotAux);
   244         if (distance < res) {
   256 unsigned int Dictionary::minimunDistance() {
   259     unsigned int minDist = (*this)[0].size();
   261     for (
unsigned int i = 0; i < size(); i++) {
   263         minDist = std::min(minDist, (*
this)[i].selfDistance());
   266         for (
unsigned int j = i + 1; j < size(); j++) {
   267             minDist = std::min(minDist, (*
this)[i].
distance((*
this)[j]));
   278 bool HighlyReliableMarkers::loadDictionary(
Dictionary D, 
float correctionDistanceRate) {
   283     _ncellsBorder = (_D[0].n() + 2);
   284     _correctionDistance = correctionDistanceRate * ((D.
tau0-1)/2);
   285     cerr << 
"aruco :: _correctionDistance = " << _correctionDistance << endl;
   286     _binaryTree.loadDictionary(&D);
   290 bool HighlyReliableMarkers::loadDictionary(std::string filename, 
float correctionDistance) {
   293     return loadDictionary(D, correctionDistance);
   299 int HighlyReliableMarkers::detect(
const cv::Mat &in, 
int &nRotations) {
   301     assert(in.rows == in.cols);
   303     if (in.type() == CV_8UC1)
   306         cv::cvtColor(in, grey, CV_BGR2GRAY);
   308     cv::threshold(grey, grey, 125, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
   309     _swidth = grey.rows / _ncellsBorder;
   319     for (
unsigned int i = 0; i < 4; i++) {
   320         if (_binaryTree.findId(candidate.
getId(i), orgPos)) {
   339     unsigned int minMarker, minRot;
   340     if (_D.distance(candidate, minMarker, minRot) <= _correctionDistance) {
   352 bool HighlyReliableMarkers::checkBorders(cv::Mat grey) {
   353     for (
int y = 0; y < _ncellsBorder; y++) {
   354         int inc = _ncellsBorder - 1;
   355         if (y == 0 || y == _ncellsBorder - 1)
   357         for (
int x = 0; 
x < _ncellsBorder; 
x += inc) {
   358             int Xstart = (
x) * (_swidth);
   359             int Ystart = (y) * (_swidth);
   360             cv::Mat 
square = grey(cv::Rect(Xstart, Ystart, _swidth, _swidth));
   361             int nZ = cv::countNonZero(square);
   362             if (nZ > (_swidth * _swidth) / 2) {
   372 MarkerCode HighlyReliableMarkers::getMarkerCode(
const cv::Mat &grey) {
   374     for (
int y = 0; y < _n; y++) {
   375         for (
int x = 0; 
x < _n; 
x++) {
   376             int Xstart = (
x + 1) * (_swidth);
   377             int Ystart = (y + 1) * (_swidth);
   378             cv::Mat 
square = grey(cv::Rect(Xstart, Ystart, _swidth, _swidth));
   379             int nZ = countNonZero(square);
   380             if (nZ > (_swidth * _swidth) / 2)
   381                 candidate.
set(y * _n + 
x, 1);
   391 void HighlyReliableMarkers::BalancedBinaryTree::loadDictionary(
Dictionary *D) {
   394     for (
unsigned int i = 0; i < D->size(); i++) {
   395         _orderD.push_back(std::pair< unsigned int, unsigned int >((*D)[i].getId(), i));
   397     std::sort(_orderD.begin(), _orderD.end());
   400     unsigned int levels = 0;
   401     while (
pow(
float(2), 
float(levels)) <= _orderD.size())
   406     std::vector< bool > visited;
   407     visited.resize(_orderD.size(), 
false);
   410     unsigned int rootIdx = _orderD.
size() / 2;
   411     visited[rootIdx] = 
true; 
   417     std::vector< std::pair< unsigned int, unsigned int > > intervals;
   419     intervals.push_back(std::pair< unsigned int, unsigned int >(0, rootIdx));
   420     intervals.push_back(std::pair< unsigned int, unsigned int >(rootIdx, _orderD.size()));
   424     _binaryTree.resize(_orderD.size());
   427     if (!visited[(0 + rootIdx) / 2])
   428         _binaryTree[rootIdx].first = (0 + rootIdx) / 2;
   430         _binaryTree[rootIdx].first = -1;
   431     if (!visited[(rootIdx + _orderD.size()) / 2])
   432         _binaryTree[rootIdx].second = (rootIdx + _orderD.size()) / 2;
   434         _binaryTree[rootIdx].second = -1;
   437     for (
unsigned int i = 1; i < levels; i++) {
   438         unsigned int nintervals = intervals.size(); 
   439         for (
unsigned int j = 0; j < nintervals; j++) {
   441             unsigned int lowerBound, higherBound;
   442             lowerBound = intervals.back().first;
   443             higherBound = intervals.back().second;
   444             intervals.pop_back();
   447             unsigned int center = (higherBound + lowerBound) / 2;
   450             if (!visited[center])
   451                 visited[center] = 
true;
   456             unsigned int lowerChild = (lowerBound + center) / 2;
   457             unsigned int higherChild = (center + higherBound) / 2;
   460             if (!visited[lowerChild]) {
   461                 intervals.insert(intervals.begin(), std::pair< unsigned int, unsigned int >(lowerBound, center)); 
   462                 _binaryTree[center].first = lowerChild;                                                           
   464                 _binaryTree[center].first = -1; 
   467             if (!visited[higherChild]) {
   468                 intervals.insert(intervals.begin(), std::pair< unsigned int, unsigned int >(center, higherBound));
   469                 _binaryTree[center].second = higherChild;
   471                 _binaryTree[center].second = -1;
   486 bool HighlyReliableMarkers::BalancedBinaryTree::findId(
unsigned int id, 
unsigned int &orgPos) {
   489         unsigned int posId = _orderD[pos].first; 
   491             orgPos = _orderD[pos].second;
   493         } 
else if (posId < 
id)
   494             pos = _binaryTree[pos].second; 
   496             pos = _binaryTree[pos].first; 
 unsigned int getId(unsigned int rot=0) const 
const std::vector< bool > & getRotation(unsigned int rot) const 
void fromString(std::string s)
const CwiseUnaryOp< internal::scalar_pow_op< Scalar >, const Derived > pow(const Scalar &exponent) const 
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const 
const CwiseUnaryOp< internal::scalar_square_op< Scalar >, const Derived > square() const 
unsigned int size() const 
TFSIMD_FORCE_INLINE const tfScalar & x() const 
void set(unsigned int pos, bool val, bool updateIds=true)
bool fromFile(std::string filename)
std::vector< bool > _bits[4]
bitset< 64 > fromString(std::string str)