subpixelcorner.cpp
Go to the documentation of this file.
1 #include "subpixelcorner.h"
2 #include <opencv2/imgproc/imgproc.hpp>
3 using namespace cv;
4 
5 namespace aruco {
6 
7 SubPixelCorner::SubPixelCorner() {
8  _winSize = 15;
9  _apertureSize = 3;
10  _term.maxCount = 10;
11  _term.epsilon = 0.1;
12  _term.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
13  enable = true;
14 }
15 
16 void SubPixelCorner::checkTerm() {
17  switch (_term.type) {
18  case CV_TERMCRIT_ITER:
19  _term.epsilon = 0.f;
20  _term.maxCount;
21  break;
22  case CV_TERMCRIT_EPS:
23  _term.maxCount = _term.COUNT;
24  break;
25  case CV_TERMCRIT_ITER | CV_TERMCRIT_EPS:
26  break;
27  default:
28  _term.maxCount = _term.COUNT;
29  _term.epsilon = 0.1;
30  _term.type = CV_TERMCRIT_ITER | CV_TERMCRIT_EPS;
31  break;
32  }
33 
34  eps = std::max(_term.epsilon, 0.0);
35  eps = eps * eps;
36 
37  _max_iters = std::max(_term.maxCount, 1);
38  int max1 = TermCriteria::MAX_ITER;
39  _max_iters = std::min(_max_iters, max1);
40 }
41 
42 double SubPixelCorner::pointDist(cv::Point2f estimate_corner, cv::Point2f curr_corner) {
43  double dist = ((curr_corner.x - estimate_corner.x) * (curr_corner.x - estimate_corner.x)) +
44  ((curr_corner.y - estimate_corner.y) * (curr_corner.y - estimate_corner.y));
45  return dist;
46 }
47 
48 
49 void SubPixelCorner::generateMask() {
50 
51  double coeff = 1. / (_winSize * _winSize);
52  float *maskX = (float *)calloc(1, (_winSize * sizeof(float)));
53  float *maskY = (float *)calloc(1, (_winSize * sizeof(float)));
54  mask.create(_winSize, _winSize, CV_32FC(1));
55  /* calculate mask */
56  int k = 0;
57  for (int i = -_winSize / 2, k = 0; i <= _winSize / 2; i++, k++) {
58  maskX[k] = (float)exp(-i * i * coeff);
59  }
60 
61  maskY = maskX;
62 
63  for (int i = 0; i < _winSize; i++) {
64  float *mask_ptr = mask.ptr< float >(i);
65  for (int j = 0; j < _winSize; j++) {
66  mask_ptr[j] = maskX[j] * maskY[i];
67  }
68  }
69 }
70 
71 void SubPixelCorner::RefineCorner(cv::Mat image, std::vector< cv::Point2f > &corners) {
72 
73  if (enable == false)
74  return;
75  checkTerm();
76 
77  generateMask();
78  // loop over all the corner points
79  for (int k = 0; k < corners.size(); k++) {
80  cv::Point2f curr_corner;
81  // initial estimate
82  cv::Point2f estimate_corner = corners[k];
83 
84  // cerr << 'SSS" << corners[k].x <<":" << corners[k].y << endl;
85 
86  if (estimate_corner.x < 0 || estimate_corner.y < 0 || estimate_corner.y > image.rows || estimate_corner.y > image.cols)
87  continue;
88  int iter = 0;
89  double dist = TermCriteria::EPS;
90  // loop till termination criteria is met
91  do {
92  iter = iter + 1;
93  curr_corner = estimate_corner;
94 
95  /*
96  Point cx;
97  cx.x=floor(curr_corner.x);
98  cx.y=floor(curr_corner.y);
99  double dx=curr_corner.x-cx.x;
100  double dy=curr_corner.y-cx.y;
101  float vIx[2];
102  float vIy[2];
103 
104  vIx[0] = dx;
105  vIx[1] = 1 - dx;
106  vIy[0] = dy;
107  vIy[1] = 1 - dy;
108 
109  int x1=std::max((int)(cx.x-_winSize-_apertureSize/2),0);
110  int y1=std::max((int)(cx.y-_winSize-_apertureSize/2),0);
111 
112  xmin = x1<0?0:x1;
113  xmax = x1+_winSize<image.cols?x1+_winSize:image.cols-1;
114  ymin = y1<0?0:y1;
115  ymax = y1+_winSize<image.rows?y1+_winSize:image.rows-1;
116 
117  Rect roi=Rect(xmin,ymin,xmax-xmin,ymax-ymin);
118  */
119 
120  Mat local;
121  cv::getRectSubPix(image, Size(_winSize + 2 * (_apertureSize / 2), _winSize + 2 * (_apertureSize / 2)), curr_corner, local);
122 
123 
124 
125  cv::Mat Dx, Dy;
126  // extracing image ROI about the corner point
127  // Mat local=image(roi);
128  // computing the gradients over the neighborhood about corner point
129  cv::Sobel(local, Dx, CV_32FC(1), 1, 0, _apertureSize, 1, 0);
130  cv::Sobel(local, Dy, CV_32FC(1), 0, 1, _apertureSize, 1, 0);
131 
132  // parameters requried for estimations
133  double A = 0, B = 0, C = 0, D = 0, E = 0, F = 0;
134  int lx = 0, ly = 0;
135  for (int i = _apertureSize / 2; i <= _winSize; i++) {
136 
137  float *dx_ptr = Dx.ptr< float >(i);
138  float *dy_ptr = Dy.ptr< float >(i);
139  ly = i - _winSize / 2 - _apertureSize / 2;
140 
141  float *mask_ptr = mask.ptr< float >(ly + _winSize / 2);
142 
143  for (int j = _apertureSize / 2; j <= _winSize; j++) {
144 
145  lx = j - _winSize / 2 - _apertureSize / 2;
146  // cerr << lx+_winSize/2 << ":" ;
147  double val = mask_ptr[lx + _winSize / 2];
148  double dxx = dx_ptr[j] * dx_ptr[j] * val;
149  double dyy = dy_ptr[j] * dy_ptr[j] * val;
150  double dxy = dx_ptr[j] * dy_ptr[j] * val;
151 
152  A = A + dxx;
153  B = B + dxy;
154  E = E + dyy;
155  C = C + dxx * lx + dxy * ly;
156  F = F + dxy * lx + dyy * ly;
157  }
158  }
159 
160  // computing denominator
161  double det = (A * E - B * B);
162  if (fabs(det) > DBL_EPSILON * DBL_EPSILON) {
163  det = 1.0 / det;
164  // translating back to original corner and adding new estimates
165  estimate_corner.x = curr_corner.x + ((C * E) - (B * F)) * det;
166  estimate_corner.y = curr_corner.y + ((A * F) - (C * D)) * det;
167  } else {
168  estimate_corner.x = curr_corner.x;
169  estimate_corner.y = curr_corner.y;
170  }
171 
172  dist = pointDist(estimate_corner, curr_corner);
173 
174 
175  } while (iter < _max_iters && dist > eps);
176 
177  // double dist=pointDist(corners[k],estimate_corner);
178  if (fabs(corners[k].x - estimate_corner.x) > _winSize || fabs(corners[k].y - estimate_corner.y) > _winSize) {
179  estimate_corner.x = corners[k].x;
180  estimate_corner.y = corners[k].y;
181  }
182  corners[k].x = estimate_corner.x;
183  corners[k].y = estimate_corner.y;
184  // cerr << "EEE" << corners[k].x <<":" << corners[k].y << endl;
185  }
186 }
187 }


asr_aruco_marker_recognition
Author(s): Allgeyer Tobias, Meißner Pascal, Qattan Mohamad
autogenerated on Mon Jun 10 2019 12:40:22