dictionary_based.cpp
Go to the documentation of this file.
1 #include "dictionary_based.h"
2 #include <bitset>
3 #include <opencv2/imgproc/imgproc.hpp>
4 
5 
6 namespace aruco{
7 
8 void DictionaryBased::setParams(const Dictionary &dic,float max_correction_rate){
9  _dic=dic;
10  max_correction_rate=max(0.f,min(1.0f,max_correction_rate));
11  _maxCorrectionAllowed=float(_dic.tau())*max_correction_rate;
12 
13 }
14 
15 std::string DictionaryBased::getName()const{
17 }
18 
19 void DictionaryBased::toMat(uint64_t code,int nbits_sq,cv::Mat &out) {
20  out.create(nbits_sq,nbits_sq,CV_8UC1);
21  bitset<64> bs(code);
22  int curbit=0;
23  for(int r=0;r<nbits_sq;r++){
24  uchar *pr=out.ptr<uchar>(r);
25  for(int c=0;c<nbits_sq;c++)
26  pr[c] = bs[curbit];
27 
28  }
29 }
30 
31 
32 int hamm_distance(uint64_t a,uint64_t b){
33  uint64_t v=a&b;
34  uint64_t mask=0x1;
35  int d=0;
36  for(int i=0;i<63;i++){
37  d+= mask&v;
38  v=v<<1;
39  }
40  return d;
41 }
42 
43 bool DictionaryBased::detect(const cv::Mat &in, int & marker_id,int &nRotations) {
44  assert(in.rows == in.cols);
45  cv::Mat grey;
46  if (in.type() == CV_8UC1) grey = in;
47  else cv::cvtColor(in, grey, CV_BGR2GRAY);
48  // threshold image
49  cv::threshold(grey, grey, 125, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
50 
51  vector<uint64_t> ids;
52  //get the ids in the four rotations (if possible)
53  if ( !getInnerCode( grey,_dic.nbits(),ids)) return false;
54 
55  //find the best one
56  for(int i=0;i<4;i++){
57  if ( _dic.is(ids[i])){//is in the set?
58  nRotations=i;//how many rotations are and its id
59  marker_id=_dic[ids[i]];
60  return true;//bye bye
61  }
62  }
63 
64  //you get here, no valid id :(
65  //lets try error correction
66 
67  if(_maxCorrectionAllowed>0){//find distance to map elements
68  for(auto ci:_dic.getMapCode()){
69  for(int i=0;i<4;i++){
70  if (hamm_distance(ci.first,ids[i])<_maxCorrectionAllowed){
71  marker_id=ci.second;
72  nRotations=i;
73  return true;
74  }
75  }
76  }
77  }
78  else return false;
79 
80  }
81 
82  bool DictionaryBased::getInnerCode(const cv::Mat &thres_img,int total_nbits,vector<uint64_t> &ids){
83  int bits_a=sqrt(total_nbits);
84  int bits_a2=bits_a+2;
85  // Markers are divided in (bits_a+2)x(bits_a+2) regions, of which the inner bits_axbits_a belongs to marker info
86  // the external border shoould be entirely black
87 
88  int swidth = thres_img.rows / bits_a2;
89  for (int y = 0; y < bits_a2; y++) {
90  int inc = bits_a2-1;
91  if (y == 0 || y == bits_a2-1)
92  inc = 1; // for first and last row, check the whole border
93  for (int x = 0; x < bits_a2; x += inc) {
94  cv::Mat square = thres_img(cv::Rect(x*swidth, y*swidth, swidth, swidth));
95  if (cv::countNonZero(square) > (swidth * swidth) / 2)
96  return false; // can not be a marker because the border element is not black!
97  }
98  }
99 
100  // now,
101  // get information(for each inner square, determine if it is black or white)
102 
103  // now,
104  cv::Mat _bits = cv::Mat::zeros(bits_a, bits_a, CV_8UC1);
105  // get information(for each inner square, determine if it is black or white)
106 
107  for (int y = 0; y < bits_a; y++) {
108 
109  for (int x = 0; x < bits_a; x++) {
110  int Xstart = (x + 1) * (swidth);
111  int Ystart = (y + 1) * (swidth);
112  cv::Mat square = thres_img(cv::Rect(Xstart, Ystart, swidth, swidth));
113  int nZ = cv::countNonZero(square);
114  if (nZ > (swidth * swidth) / 2)
115  _bits.at< uchar >(y, x) = 1;
116  }
117  }
118  //now, get the 64bits ids
119 
120  int nr=0;
121  do{
122  ids.push_back(touulong(_bits));
123  _bits=rotate(_bits);
124  nr++;
125  }while(nr<4);
126  return true;
127  }
128 
129  //convert matrix of (0,1)s in a 64 bit value
130  uint64_t DictionaryBased::touulong(const cv::Mat &code){
131 
132  std::bitset<64> bits;
133  int bidx=0;
134  for (int y = code.rows-1; y >=0 ; y--)
135  for (int x = code.cols-1; x >=0; x--)
136  bits[bidx++]=code.at<uchar>(y,x);
137  return bits.to_ullong();
138 
139  }
140  cv::Mat DictionaryBased::rotate(const cv::Mat &in) {
141  cv::Mat out;
142  in.copyTo(out);
143  for (int i = 0; i < in.rows; i++) {
144  for (int j = 0; j < in.cols; j++) {
145  out.at< uchar >(i, j) = in.at< uchar >(in.cols - j - 1, i);
146  }
147  }
148  return out;
149  }
150 
151 
152 }
d
DICT_TYPES getType() const
Definition: dictionary.h:36
f
void setParams(const Dictionary &dic, float max_correction_rate)
uint64_t touulong(const cv::Mat &code)
cv::Mat rotate(const cv::Mat &in)
const CwiseUnaryOp< internal::scalar_square_op< Scalar >, const Derived > square() const
void toMat(uint64_t code, int nbits_sq, cv::Mat &out)
bool getInnerCode(const cv::Mat &thres_img, int total_nbits, vector< uint64_t > &ids)
const std::map< uint64_t, uint16_t > & getMapCode() const
Definition: dictionary.h:45
TFSIMD_FORCE_INLINE const tfScalar & x() const
uint32_t tau() const
Definition: dictionary.h:43
std::string getName() const
bool is(uint64_t code) const
Definition: dictionary.h:34
int min(int a, int b)
static std::string getTypeString(DICT_TYPES t)
Definition: dictionary.cpp:235
const CwiseUnaryOp< internal::scalar_sqrt_op< Scalar >, const Derived > sqrt() const
int hamm_distance(uint64_t a, uint64_t b)
bool detect(const cv::Mat &in, int &marker_id, int &nRotations)
uint32_t nbits() const
Definition: dictionary.h:41


tuw_aruco
Author(s): Lukas Pfeifhofer
autogenerated on Mon Jun 10 2019 15:40:48