78 #define MAX_CONTOUR_APPROX 7    83     CImage& thresh_img, 
const int dilations, IplConvKernel* kernel_cross,
    84     IplConvKernel* kernel_rect, IplConvKernel* kernel_diag1,
    85     IplConvKernel* kernel_diag2, IplConvKernel* kernel_horz,
    86     IplConvKernel* kernel_vert)
    97             cvDilate(ipl, ipl, kernel_cross, 1);
   101             cvErode(ipl, ipl, kernel_rect, 1);
   104             cvDilate(ipl, ipl, kernel_vert, 1);
   107             cvDilate(ipl, ipl, kernel_vert, 1);
   110             cvDilate(ipl, ipl, kernel_vert, 1);
   113             cvDilate(ipl, ipl, kernel_vert, 1);
   116             cvDilate(ipl, ipl, kernel_vert, 1);
   120             cvDilate(ipl, ipl, kernel_cross, 1);
   123             cvErode(ipl, ipl, kernel_rect, 1);
   126             cvDilate(ipl, ipl, kernel_horz, 1);
   129             cvDilate(ipl, ipl, kernel_horz, 1);
   132             cvDilate(ipl, ipl, kernel_horz, 1);
   135             cvDilate(ipl, ipl, kernel_horz, 1);
   138             cvDilate(ipl, ipl, kernel_horz, 1);
   142             cvDilate(ipl, ipl, kernel_diag2, 1);
   145             cvDilate(ipl, ipl, kernel_diag1, 1);
   148             cvDilate(ipl, ipl, kernel_diag2, 1);
   151             cvDilate(ipl, ipl, kernel_diag1, 1);
   154             cvDilate(ipl, ipl, kernel_diag2, 1);
   157             cvDilate(ipl, ipl, kernel_diag1, 1);
   161             cvDilate(ipl, ipl, kernel_diag2, 1);
   164             cvDilate(ipl, ipl, kernel_diag2, 1);
   167             cvDilate(ipl, ipl, kernel_diag2, 1);
   170             cvDilate(ipl, ipl, kernel_diag2, 1);
   174             cvDilate(ipl, ipl, kernel_diag1, 1);
   177             cvDilate(ipl, ipl, kernel_diag1, 1);
   180             cvDilate(ipl, ipl, kernel_diag1, 1);
   183             cvDilate(ipl, ipl, kernel_diag1, 1);
   187             cvDilate(ipl, ipl, kernel_cross, 1);
   190             cvErode(ipl, ipl, kernel_rect, 1);
   193             cvDilate(ipl, ipl, kernel_cross, 1);
   196             cvDilate(ipl, ipl, kernel_diag2, 1);
   200             cvDilate(ipl, ipl, kernel_diag1, 1);
   203             cvDilate(ipl, ipl, kernel_rect, 1);
   206             cvErode(ipl, ipl, kernel_cross, 1);
   209             cvDilate(ipl, ipl, kernel_rect, 1);
   212             cvDilate(ipl, ipl, kernel_cross, 1);
   226     const CImage& img_, CvSize pattern_size,
   227     std::vector<CvPoint2D32f>& out_corners)
   233     size_t max_count = 0;
   234     int max_dilation_run_ID = -1;
   239     vector<CvCBQuad::Ptr> quads;  
   240     vector<CvCBQuad::Ptr> quad_group;  
   241     vector<CvCBCorner::Ptr> corners;  
   242     vector<CvCBQuad::Ptr>
   249     int quad_count, group_idx;
   251     if (pattern_size.width < 2 || pattern_size.height < 2)
   253         std::cerr << 
"Pattern should have at least 2x2 size" << endl;
   256     if (pattern_size.width > 127 || pattern_size.height > 127)
   258         std::cerr << 
"Pattern should not have a size larger than 127 x 127"   274     IplConvKernel* kernel_cross =
   275         cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_CROSS, 
nullptr);
   276     IplConvKernel* kernel_rect =
   277         cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT, 
nullptr);
   279     static int kernel_diag1_vals[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
   280     IplConvKernel* kernel_diag1 = cvCreateStructuringElementEx(
   281         3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_diag1_vals);
   282     static int kernel_diag2_vals[9] = {0, 0, 1, 0, 1, 0, 1, 0, 0};
   283     IplConvKernel* kernel_diag2 = cvCreateStructuringElementEx(
   284         3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_diag2_vals);
   285     static int kernel_horz_vals[9] = {0, 0, 0, 1, 1, 1, 0, 0, 0};
   286     IplConvKernel* kernel_horz = cvCreateStructuringElementEx(
   287         3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_horz_vals);
   288     static int kernel_vert_vals[9] = {0, 1, 0, 0, 1, 0, 0, 1, 0};
   289     IplConvKernel* kernel_vert = cvCreateStructuringElementEx(
   290         3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_vert_vals);
   298     cv::adaptiveThreshold(
   301         CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, block_size, 0);
   303     thresh_img_save = thresh_img.makeDeepCopy();
   314     bool last_dilation = 
false;
   316     for (
int dilations = 0; !last_dilation; dilations++)
   320         thresh_img = thresh_img_save.makeDeepCopy();
   324             thresh_img, dilations, kernel_cross, kernel_rect, kernel_diag1,
   325             kernel_diag2, kernel_horz, kernel_vert);
   332             thresh_img.asCvMatRef(), cv::Point(0, 0),
   333             cv::Point(thresh_img.getWidth() - 1, thresh_img.getHeight() - 1),
   334             CV_RGB(255, 255, 255), 3, 8);
   339             quads, corners, thresh_img, flags, dilations, 
true);
   340         if (quad_count <= 0) 
continue;
   355         for (group_idx = 0;; group_idx++)
   359             if (quad_group.empty()) 
break;
   362             size_t count = quad_group.size();
   368             if (count  > max_count)
   375                 max_dilation_run_ID = dilations;
   398                 output_quad_group = quad_group;  
   410     found = 
myQuads2Points(output_quad_group, pattern_size, out_corners);
   412     if (found != -1 && found != 1)
   424         last_dilation = 
false;
   425         for (
int dilations = 0; !last_dilation; dilations++)
   432             thresh_img = thresh_img_save.makeDeepCopy();
   436                 thresh_img, dilations, kernel_cross, kernel_rect, kernel_diag1,
   437                 kernel_diag2, kernel_horz, kernel_vert);
   440                 thresh_img.asCvMatRef(), cv::Point(0, 0),
   442                     thresh_img.getWidth() - 1, thresh_img.getHeight() - 1),
   443                 CV_RGB(255, 255, 255), 3, 8);
   446                 quads, corners, thresh_img, flags, dilations, 
false);
   447             if (quad_count <= 0) 
continue;
   462             while (feedBack == -1)
   465                     quads, dilations, output_quad_group, max_dilation_run_ID);
   471                     max_count = max_count + 1;
   477                         output_quad_group, pattern_size, out_corners);
   480                     if (found == -1 || found == 1)
   496     cvReleaseStructuringElement(&kernel_cross);
   497     cvReleaseStructuringElement(&kernel_rect);
   498     cvReleaseStructuringElement(&kernel_diag1);
   499     cvReleaseStructuringElement(&kernel_diag2);
   500     cvReleaseStructuringElement(&kernel_horz);
   501     cvReleaseStructuringElement(&kernel_vert);
   512         std::cerr << 
"While linking the corners a problem was encountered. No "   513                      "corner sequence is returned. "   527     double x0, 
double y0, 
double x1, 
double y1, 
double x2, 
double y2)
   529     return std::abs(0.5 * (x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)));
   532 double median(
const std::vector<double>& vec)
   534     std::vector<double> v = vec;  
   535     const size_t n = v.size() / 2;
   536     nth_element(v.begin(), v.begin() + n, v.end());
   546     std::vector<CvCBQuad::Ptr>& quad_group, 
const CvSize& pattern_size)
   548     cv::MemStorage temp_storage;  
   550     CvPoint2D32f center = cvPoint2D32f(0, 0);
   553     const size_t expected_quads_count =
   554         ((pattern_size.width + 1) * (pattern_size.height + 1) + 1) / 2;
   559     const size_t nQuads = quad_group.size();
   560     if (nQuads <= expected_quads_count) 
return;  
   563     vector<CvPoint2D32f> centers(nQuads);
   564     temp_storage = cv::MemStorage(cvCreateMemStorage(0));
   569     std::vector<double> quad_areas(nQuads);
   570     double min_area = DBL_MAX, max_area = -DBL_MAX, mean_area = 0.0;
   572     for (
size_t i = 0; i < nQuads; i++)
   574         CvPoint2D32f ci = cvPoint2D32f(0, 0);
   577         for (
size_t j = 0; j < 4; j++)
   579             CvPoint2D32f pt = q->corners[j]->pt;
   590                 q->corners[0]->pt.x, q->corners[0]->pt.y, q->corners[1]->pt.x,
   591                 q->corners[1]->pt.y, q->corners[2]->pt.x, q->corners[2]->pt.y) +
   593                 q->corners[0]->pt.x, q->corners[0]->pt.y, q->corners[2]->pt.x,
   594                 q->corners[2]->pt.y, q->corners[3]->pt.x, q->corners[3]->pt.y);
   599         if (a < min_area) min_area = a;
   600         if (a > max_area) max_area = a;
   611     const double median_area = 
median(quad_areas);
   614     for (
size_t i = 0; i < nQuads; i++)
   616         quad_group[i]->area_ratio = quad_group[i]->area / median_area;
   631     while (quad_group.size() > expected_quads_count)
   633         double min_box_area = DBL_MAX;
   634         int min_box_area_index = -1;
   637         int most_outlier_idx = -1;
   638         double most_outlier_ratio = 1.0;
   639         for (
size_t skip = 0; skip < quad_group.size(); skip++)
   641             double ar = quad_group[skip]->area_ratio;
   642             if (ar > 1.0) ar = 1.0 / ar;
   644             if (ar < most_outlier_ratio)
   646                 most_outlier_ratio = ar;
   647                 most_outlier_idx = skip;
   651         if (most_outlier_idx >= 0)
   653             min_box_area_index = most_outlier_idx;
   656         if (min_box_area_index == -1)  
   659             for (
size_t skip = 0; skip < quad_group.size(); skip++)
   662                 CvPoint2D32f temp = centers[skip];
   663                 centers[skip] = center;
   665                     cvMat(1, quad_group.size(), CV_32FC2, ¢ers[0]);
   667                     cvConvexHull2(&pointMat, temp_storage, CV_CLOCKWISE, 1);
   668                 centers[skip] = temp;
   669                 double hull_area = fabs(cvContourArea(hull, CV_WHOLE_SEQ));
   672                 if (hull_area < min_box_area)
   674                     min_box_area = hull_area;
   675                     min_box_area_index = skip;
   677                 cvClearMemStorage(temp_storage);
   684         for (
size_t i = 0; i < quad_group.size(); i++)
   688             for (
size_t j = 0; j < 4; j++)
   690                 if (q->neighbors[j] == q0)
   692                     q->neighbors[j].reset();  
   694                     for (
size_t k = 0; k < 4; k++)
   695                         if (q0->neighbors[k] == q)
   697                             q0->neighbors[k].reset();  
   707         quad_group.erase(quad_group.begin() + min_box_area_index);
   708         centers.erase(centers.begin() + min_box_area_index);
   716     std::vector<CvCBQuad::Ptr>& quad, std::vector<CvCBQuad::Ptr>& out_group,
   717     const int group_idx, [[maybe_unused]] 
const int dilation)
   722     const size_t quad_count = quad.size();
   725     for (
size_t i = 0; i < quad_count; i++)
   727         if (quad[i]->count < 0 || quad[i]->group_idx >= 0) 
continue;
   733         std::stack<CvCBQuad::Ptr> seqStack;
   737         q->group_idx = group_idx;
   738         out_group.push_back(q);  
   740         while (!seqStack.empty())
   745             for (
size_t k = 0; k < 4; k++)
   751                 if (neighbor && neighbor->count > 0 && neighbor->group_idx < 0)
   753                     neighbor->group_idx = group_idx;
   754                     seqStack.push(neighbor);  
   769     std::vector<CvCBQuad::Ptr>& quad_group, 
const CvSize& pattern_size,
   772     const size_t count = quad_group.size();
   775     if (firstRun == 
true)
   781         for (
size_t i = 0; i < count; i++)
   784             if (q->
count > max_number)
   786                 max_number = q->
count;
   789                 if (max_number == 4) 
break;
   796         CvCBQuad* q = quad_group[max_id].get();
   810     bool flag_changed = 
true;
   811     while (flag_changed == 
true)
   814         flag_changed = 
false;
   818         for (
int i = 
int(count - 1); i >= 0; i--)
   821             if ((quad_group[i])->labeled == 
false)
   825                 for (
size_t j = 0; j < 4; j++)
   829                     if ((quad_group[i])->neighbors[j])
   832                             quad_group[i]->neighbors[j];
   835                         if (quadNeighborJ->labeled == 
true)
   841                             int connectedNeighborCornerId = -1;
   842                             for (
int k = 0; k < 4; k++)
   844                                 if (quadNeighborJ->neighbors[k] ==
   847                                     connectedNeighborCornerId = k;
   860                                     ->corners[connectedNeighborCornerId];
   862                                 quadNeighborJ->corners
   863                                     [(connectedNeighborCornerId + 1) % 4];
   865                                 quadNeighborJ->corners
   866                                     [(connectedNeighborCornerId + 2) % 4];
   868                                 quadNeighborJ->corners
   869                                     [(connectedNeighborCornerId + 3) % 4];
   871                             (quad_group[i])->corners[j]->row = conCorner->row;
   872                             (quad_group[i])->corners[j]->column =
   874                             (quad_group[i])->corners[(j + 1) % 4]->row =
   875                                 conCorner->row - conCornerCW2->row +
   877                             (quad_group[i])->corners[(j + 1) % 4]->column =
   878                                 conCorner->column - conCornerCW2->column +
   879                                 conCornerCW3->column;
   880                             (quad_group[i])->corners[(j + 2) % 4]->row =
   881                                 conCorner->row + conCorner->row -
   883                             (quad_group[i])->corners[(j + 2) % 4]->column =
   884                                 conCorner->column + conCorner->column -
   885                                 conCornerCW2->column;
   886                             (quad_group[i])->corners[(j + 3) % 4]->row =
   887                                 conCorner->row - conCornerCW2->row +
   889                             (quad_group[i])->corners[(j + 3) % 4]->column =
   890                                 conCorner->column - conCornerCW2->column +
   891                                 conCornerCW1->column;
   894                             (quad_group[i])->labeled = 
true;
   916     int min_column = 127;
   917     int max_column = -127;
   919     for (
size_t i = 0; i < count; i++)
   923         for (
size_t j = 0; j < 4; j++)
   925             if ((q->corners[j])->row > max_row) max_row = (q->corners[j])->row;
   927             if ((q->corners[j])->row < min_row) min_row = (q->corners[j])->row;
   929             if ((q->corners[j])->column > max_column)
   930                 max_column = (q->corners[j])->column;
   932             if ((q->corners[j])->column < min_column)
   933                 min_column = (q->corners[j])->column;
   940     for (
int i = min_row; i <= max_row; i++)
   942         for (
int j = min_column; j <= max_column; j++)
   952             for (
size_t k = 0; k < count; k++)
   954                 for (
size_t l = 0; l < 4; l++)
   956                     if (((quad_group[k])->corners[l]->row == i) &&
   957                         ((quad_group[k])->corners[l]->column == j))
   962                             (quad_group[k])->corners[l]->needsNeighbor = 
false;
   965                                 ->needsNeighbor = 
false;
   971                             (quad_group[k])->corners[l]->needsNeighbor = 
true;
   988     for (
int i = min_row; i <= max_row; i++)
   990         for (
int j = min_column; j <= max_column; j++)
  1003             for (
size_t k = 0; k < count; k++)
  1005                 for (
size_t l = 0; l < 4; l++)
  1007                     if (((quad_group[k])->corners[l]->row == i) &&
  1008                         ((quad_group[k])->corners[l]->column == j))
  1017                         else if (number == 2)
  1023                                 (quad_group[k])->corners[l]->pt.x -
  1024                                 (quad_group[quadID])->corners[cornerID]->pt.x;
  1026                                 (quad_group[k])->corners[l]->pt.y -
  1027                                 (quad_group[quadID])->corners[cornerID]->pt.y;
  1029                             if (delta_x != 0 || delta_y != 0)
  1032                                 (quad_group[k])->corners[l]->pt.x =
  1033                                     (quad_group[k])->corners[l]->pt.x -
  1035                                 (quad_group[quadID])->corners[cornerID]->pt.x =
  1036                                     (quad_group[quadID])
  1040                                 (quad_group[k])->corners[l]->pt.y =
  1041                                     (quad_group[k])->corners[l]->pt.y -
  1043                                 (quad_group[quadID])->corners[cornerID]->pt.y =
  1044                                     (quad_group[quadID])
  1050                         else if (number > 2)
  1058                         number = number + 1;
  1074     int largerDimPattern = max(pattern_size.height, pattern_size.width);
  1075     int smallerDimPattern = min(pattern_size.height, pattern_size.width);
  1076     bool flagSmallerDim1 = 
false;
  1077     bool flagSmallerDim2 = 
false;
  1079     if ((largerDimPattern + 1) == max_column - min_column)
  1081         flagSmallerDim1 = 
true;
  1086         for (
size_t k = 0; k < count; k++)
  1088             for (
size_t l = 0; l < 4; l++)
  1090                 if ((quad_group[k])->corners[l]->column == min_column ||
  1091                     (quad_group[k])->corners[l]->column == max_column)
  1094                     (quad_group[k])->corners[l]->needsNeighbor = 
false;
  1100     if ((largerDimPattern + 1) == max_row - min_row)
  1102         flagSmallerDim2 = 
true;
  1107         for (
size_t k = 0; k < count; k++)
  1109             for (
size_t l = 0; l < 4; l++)
  1111                 if ((quad_group[k])->corners[l]->row == min_row ||
  1112                     (quad_group[k])->corners[l]->row == max_row)
  1115                     (quad_group[k])->corners[l]->needsNeighbor = 
false;
  1133     if ((flagSmallerDim1 == 
false && flagSmallerDim2 == 
true))
  1138         if ((smallerDimPattern + 1) == max_column - min_column)
  1140             for (
size_t k = 0; k < count; k++)
  1142                 for (
int l = 0; l < 4; l++)
  1144                     if ((quad_group[k])->corners[l]->column == min_column ||
  1145                         (quad_group[k])->corners[l]->column == max_column)
  1148                         (quad_group[k])->corners[l]->needsNeighbor = 
false;
  1155     if ((flagSmallerDim1 == 
true && flagSmallerDim2 == 
false))
  1160         if ((smallerDimPattern + 1) == max_row - min_row)
  1162             for (
size_t k = 0; k < count; k++)
  1164                 for (
size_t l = 0; l < 4; l++)
  1166                     if ((quad_group[k])->corners[l]->row == min_row ||
  1167                         (quad_group[k])->corners[l]->row == max_row)
  1170                         (quad_group[k])->corners[l]->needsNeighbor = 
false;
  1177     if ((flagSmallerDim1 == 
false && flagSmallerDim2 == 
false) &&
  1178         smallerDimPattern + 1 < max_column - min_column)
  1183         if ((smallerDimPattern + 1) == max_row - min_row)
  1185             for (
size_t k = 0; k < count; k++)
  1187                 for (
size_t l = 0; l < 4; l++)
  1189                     if ((quad_group[k])->corners[l]->row == min_row ||
  1190                         (quad_group[k])->corners[l]->row == max_row)
  1193                         (quad_group[k])->corners[l]->needsNeighbor = 
false;
  1200     if ((flagSmallerDim1 == 
false && flagSmallerDim2 == 
false) &&
  1201         smallerDimPattern + 1 < max_row - min_row)
  1206         if ((smallerDimPattern + 1) == max_column - min_column)
  1208             for (
size_t k = 0; k < count; k++)
  1210                 for (
size_t l = 0; l < 4; l++)
  1212                     if ((quad_group[k])->corners[l]->column == min_column ||
  1213                         (quad_group[k])->corners[l]->column == max_column)
  1216                         (quad_group[k])->corners[l]->needsNeighbor = 
false;
  1236     const float thresh_dilation = (float)(2 * dilation + 3) *
  1237                                   (2 * dilation + 3) *
  1242     const size_t quad_count = quads.size();
  1245     for (
size_t idx = 0; idx < quad_count; idx++)
  1251         for (
size_t i = 0; i < 4; i++)
  1254             float min_dist = FLT_MAX;
  1255             int closest_corner_idx = -1;
  1258             if (cur_quad->neighbors[i]) 
continue;
  1260             pt = cur_quad->corners[i]->pt;
  1263             for (
size_t k = 0; k < quad_count; k++)
  1265                 if (k == idx) 
continue;
  1267                 for (
size_t j = 0; j < 4; j++)
  1270                     if (quads[k]->neighbors[j]) 
continue;
  1272                     dx = pt.x - quads[k]->corners[j]->pt.x;
  1273                     dy = pt.y - quads[k]->corners[j]->pt.y;
  1274                     dist = dx * dx + dy * dy;
  1279                     if (dist < min_dist &&
  1280                         dist <= (cur_quad->edge_len + thresh_dilation) &&
  1281                         dist <= (quads[k]->edge_len + thresh_dilation))
  1286                         float x1 = (cur_quad->corners[i]->pt.x +
  1287                                     cur_quad->corners[(i + 1) % 4]->pt.x) /
  1289                         float y1 = (cur_quad->corners[i]->pt.y +
  1290                                     cur_quad->corners[(i + 1) % 4]->pt.y) /
  1292                         float x2 = (cur_quad->corners[(i + 2) % 4]->pt.x +
  1293                                     cur_quad->corners[(i + 3) % 4]->pt.x) /
  1295                         float y2 = (cur_quad->corners[(i + 2) % 4]->pt.y +
  1296                                     cur_quad->corners[(i + 3) % 4]->pt.y) /
  1299                         float x3 = (cur_quad->corners[i]->pt.x +
  1300                                     cur_quad->corners[(i + 3) % 4]->pt.x) /
  1302                         float y3 = (cur_quad->corners[i]->pt.y +
  1303                                     cur_quad->corners[(i + 3) % 4]->pt.y) /
  1305                         float x4 = (cur_quad->corners[(i + 1) % 4]->pt.x +
  1306                                     cur_quad->corners[(i + 2) % 4]->pt.x) /
  1308                         float y4 = (cur_quad->corners[(i + 1) % 4]->pt.y +
  1309                                     cur_quad->corners[(i + 2) % 4]->pt.y) /
  1320                         float c11 = cur_quad->corners[i]->pt.x - x2;
  1321                         float d11 = cur_quad->corners[i]->pt.y - y2;
  1323                         float c12 = quads[k]->corners[j]->pt.x - x2;
  1324                         float d12 = quads[k]->corners[j]->pt.y - y2;
  1325                         float sign11 = 
a1 * d11 - c11 * 
b1;
  1326                         float sign12 = 
a1 * d12 - c12 * 
b1;
  1331                         float c21 = cur_quad->corners[i]->pt.x - x4;
  1332                         float d21 = cur_quad->corners[i]->pt.y - y4;
  1334                         float c22 = quads[k]->corners[j]->pt.x - x4;
  1335                         float d22 = quads[k]->corners[j]->pt.y - y4;
  1336                         float sign21 = 
a2 * d21 - c21 * 
b2;
  1337                         float sign22 = 
a2 * d22 - c22 * 
b2;
  1347                         float c13 = quads[k]->corners[(j + 2) % 4]->pt.x - x2;
  1348                         float d13 = quads[k]->corners[(j + 2) % 4]->pt.y - y2;
  1349                         float c23 = quads[k]->corners[(j + 2) % 4]->pt.x - x4;
  1350                         float d23 = quads[k]->corners[(j + 2) % 4]->pt.y - y4;
  1351                         float sign13 = 
a1 * d13 - c13 * 
b1;
  1352                         float sign23 = 
a2 * d23 - c23 * 
b2;
  1357                         float u1 = (quads[k]->corners[j]->pt.x +
  1358                                     quads[k]->corners[(j + 1) % 4]->pt.x) /
  1360                         float v1 = (quads[k]->corners[j]->pt.y +
  1361                                     quads[k]->corners[(j + 1) % 4]->pt.y) /
  1363                         float u2 = (quads[k]->corners[(j + 2) % 4]->pt.x +
  1364                                     quads[k]->corners[(j + 3) % 4]->pt.x) /
  1366                         float v2 = (quads[k]->corners[(j + 2) % 4]->pt.y +
  1367                                     quads[k]->corners[(j + 3) % 4]->pt.y) /
  1370                         float u3 = (quads[k]->corners[j]->pt.x +
  1371                                     quads[k]->corners[(j + 3) % 4]->pt.x) /
  1373                         float v3 = (quads[k]->corners[j]->pt.y +
  1374                                     quads[k]->corners[(j + 3) % 4]->pt.y) /
  1376                         float u4 = (quads[k]->corners[(j + 1) % 4]->pt.x +
  1377                                     quads[k]->corners[(j + 2) % 4]->pt.x) /
  1379                         float v4 = (quads[k]->corners[(j + 1) % 4]->pt.y +
  1380                                     quads[k]->corners[(j + 2) % 4]->pt.y) /
  1392                         float c31 = cur_quad->corners[i]->pt.x - u2;
  1393                         float d31 = cur_quad->corners[i]->pt.y - v2;
  1395                         float c32 = quads[k]->corners[j]->pt.x - u2;
  1396                         float d32 = quads[k]->corners[j]->pt.y - v2;
  1397                         float sign31 = 
a3 * d31 - c31 * 
b3;
  1398                         float sign32 = 
a3 * d32 - c32 * 
b3;
  1403                         float c41 = cur_quad->corners[i]->pt.x - u4;
  1404                         float d41 = cur_quad->corners[i]->pt.y - v4;
  1406                         float c42 = quads[k]->corners[j]->pt.x - u4;
  1407                         float d42 = quads[k]->corners[j]->pt.y - v4;
  1408                         float sign41 = a4 * d41 - c41 * b4;
  1409                         float sign42 = a4 * d42 - c42 * b4;
  1419                         float c33 = cur_quad->corners[(i + 2) % 4]->pt.x - u2;
  1420                         float d33 = cur_quad->corners[(i + 2) % 4]->pt.y - v2;
  1421                         float c43 = cur_quad->corners[(i + 2) % 4]->pt.x - u4;
  1422                         float d43 = cur_quad->corners[(i + 2) % 4]->pt.y - v4;
  1423                         float sign33 = 
a3 * d33 - c33 * 
b3;
  1424                         float sign43 = a4 * d43 - c43 * b4;
  1427                         if (((sign11 < 0 && sign12 < 0) ||
  1428                              (sign11 > 0 && sign12 > 0)) &&
  1429                             ((sign21 < 0 && sign22 < 0) ||
  1430                              (sign21 > 0 && sign22 > 0)) &&
  1431                             ((sign31 < 0 && sign32 < 0) ||
  1432                              (sign31 > 0 && sign32 > 0)) &&
  1433                             ((sign41 < 0 && sign42 < 0) ||
  1434                              (sign41 > 0 && sign42 > 0)) &&
  1435                             ((sign11 < 0 && sign13 < 0) ||
  1436                              (sign11 > 0 && sign13 > 0)) &&
  1437                             ((sign21 < 0 && sign23 < 0) ||
  1438                              (sign21 > 0 && sign23 > 0)) &&
  1439                             ((sign31 < 0 && sign33 < 0) ||
  1440                              (sign31 > 0 && sign33 > 0)) &&
  1441                             ((sign41 < 0 && sign43 < 0) ||
  1442                              (sign41 > 0 && sign43 > 0)))
  1445                             closest_corner_idx = j;
  1446                             closest_quad = quads[k];
  1454             if (closest_corner_idx >= 0 && min_dist < FLT_MAX)
  1457                     closest_quad->corners[closest_corner_idx];
  1462                 for (
size_t j = 0; !skip && j < 4; j++)
  1463                     skip = closest_quad->neighbors[j] == cur_quad;
  1468                 closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f;
  1469                 closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f;
  1472                 cur_quad->neighbors[i] = closest_quad;
  1473                 cur_quad->corners[i] = closest_corner;
  1475                 closest_quad->count++;
  1476                 closest_quad->neighbors[closest_corner_idx] = cur_quad;
  1477                 closest_quad->corners[closest_corner_idx] = closest_corner;
  1491     std::vector<CvCBQuad::Ptr>& new_quads, 
int new_dilation,
  1492     std::vector<CvCBQuad::Ptr>& old_quads, 
int old_dilation)
  1502     const float thresh_dilation =
  1503         (float)(2 * new_dilation + 3) * (2 * old_dilation + 3) * 2;
  1507     for (
size_t idx = 0; idx < old_quads.size(); idx++)
  1512         for (
int i = 0; i < 4; i++)
  1515             float min_dist = FLT_MAX;
  1516             int closest_corner_idx = -1;
  1521             if (cur_quad->corners[i]->needsNeighbor == 
false) 
continue;
  1523             pt = cur_quad->corners[i]->pt;
  1526             for (
size_t k = 0; k < new_quads.size(); k++)
  1529                 if (new_quads[k]->labeled == 
true) 
continue;
  1531                 for (
int j = 0; j < 4; j++)
  1535                     dx = pt.x - new_quads[k]->corners[j]->pt.x;
  1536                     dy = pt.y - new_quads[k]->corners[j]->pt.y;
  1537                     dist = dx * dx + dy * dy;
  1539                     if ((dist < min_dist) &&
  1540                         dist <= (cur_quad->edge_len + thresh_dilation) &&
  1541                         dist <= (new_quads[k]->edge_len + thresh_dilation))
  1546                         float x1 = (cur_quad->corners[i]->pt.x +
  1547                                     cur_quad->corners[(i + 1) % 4]->pt.x) /
  1549                         float y1 = (cur_quad->corners[i]->pt.y +
  1550                                     cur_quad->corners[(i + 1) % 4]->pt.y) /
  1552                         float x2 = (cur_quad->corners[(i + 2) % 4]->pt.x +
  1553                                     cur_quad->corners[(i + 3) % 4]->pt.x) /
  1555                         float y2 = (cur_quad->corners[(i + 2) % 4]->pt.y +
  1556                                     cur_quad->corners[(i + 3) % 4]->pt.y) /
  1559                         float x3 = (cur_quad->corners[i]->pt.x +
  1560                                     cur_quad->corners[(i + 3) % 4]->pt.x) /
  1562                         float y3 = (cur_quad->corners[i]->pt.y +
  1563                                     cur_quad->corners[(i + 3) % 4]->pt.y) /
  1565                         float x4 = (cur_quad->corners[(i + 1) % 4]->pt.x +
  1566                                     cur_quad->corners[(i + 2) % 4]->pt.x) /
  1568                         float y4 = (cur_quad->corners[(i + 1) % 4]->pt.y +
  1569                                     cur_quad->corners[(i + 2) % 4]->pt.y) /
  1580                         float c11 = cur_quad->corners[i]->pt.x - x2;
  1581                         float d11 = cur_quad->corners[i]->pt.y - y2;
  1583                         float c12 = new_quads[k]->corners[j]->pt.x - x2;
  1584                         float d12 = new_quads[k]->corners[j]->pt.y - y2;
  1585                         float sign11 = 
a1 * d11 - c11 * 
b1;
  1586                         float sign12 = 
a1 * d12 - c12 * 
b1;
  1591                         float c21 = cur_quad->corners[i]->pt.x - x4;
  1592                         float d21 = cur_quad->corners[i]->pt.y - y4;
  1594                         float c22 = new_quads[k]->corners[j]->pt.x - x4;
  1595                         float d22 = new_quads[k]->corners[j]->pt.y - y4;
  1596                         float sign21 = 
a2 * d21 - c21 * 
b2;
  1597                         float sign22 = 
a2 * d22 - c22 * 
b2;
  1608                             new_quads[k]->corners[(j + 2) % 4]->pt.x - x2;
  1610                             new_quads[k]->corners[(j + 2) % 4]->pt.y - y2;
  1612                             new_quads[k]->corners[(j + 2) % 4]->pt.x - x4;
  1614                             new_quads[k]->corners[(j + 2) % 4]->pt.y - y4;
  1615                         float sign13 = 
a1 * d13 - c13 * 
b1;
  1616                         float sign23 = 
a2 * d23 - c23 * 
b2;
  1621                         float u1 = (new_quads[k]->corners[j]->pt.x +
  1622                                     new_quads[k]->corners[(j + 1) % 4]->pt.x) /
  1624                         float v1 = (new_quads[k]->corners[j]->pt.y +
  1625                                     new_quads[k]->corners[(j + 1) % 4]->pt.y) /
  1627                         float u2 = (new_quads[k]->corners[(j + 2) % 4]->pt.x +
  1628                                     new_quads[k]->corners[(j + 3) % 4]->pt.x) /
  1630                         float v2 = (new_quads[k]->corners[(j + 2) % 4]->pt.y +
  1631                                     new_quads[k]->corners[(j + 3) % 4]->pt.y) /
  1634                         float u3 = (new_quads[k]->corners[j]->pt.x +
  1635                                     new_quads[k]->corners[(j + 3) % 4]->pt.x) /
  1637                         float v3 = (new_quads[k]->corners[j]->pt.y +
  1638                                     new_quads[k]->corners[(j + 3) % 4]->pt.y) /
  1640                         float u4 = (new_quads[k]->corners[(j + 1) % 4]->pt.x +
  1641                                     new_quads[k]->corners[(j + 2) % 4]->pt.x) /
  1643                         float v4 = (new_quads[k]->corners[(j + 1) % 4]->pt.y +
  1644                                     new_quads[k]->corners[(j + 2) % 4]->pt.y) /
  1655                         float c31 = cur_quad->corners[i]->pt.x - u2;
  1656                         float d31 = cur_quad->corners[i]->pt.y - v2;
  1658                         float c32 = new_quads[k]->corners[j]->pt.x - u2;
  1659                         float d32 = new_quads[k]->corners[j]->pt.y - v2;
  1660                         float sign31 = 
a3 * d31 - c31 * 
b3;
  1661                         float sign32 = 
a3 * d32 - c32 * 
b3;
  1666                         float c41 = cur_quad->corners[i]->pt.x - u4;
  1667                         float d41 = cur_quad->corners[i]->pt.y - v4;
  1669                         float c42 = new_quads[k]->corners[j]->pt.x - u4;
  1670                         float d42 = new_quads[k]->corners[j]->pt.y - v4;
  1671                         float sign41 = a4 * d41 - c41 * b4;
  1672                         float sign42 = a4 * d42 - c42 * b4;
  1682                         float c33 = cur_quad->corners[(i + 2) % 4]->pt.x - u2;
  1683                         float d33 = cur_quad->corners[(i + 2) % 4]->pt.y - v2;
  1684                         float c43 = cur_quad->corners[(i + 2) % 4]->pt.x - u4;
  1685                         float d43 = cur_quad->corners[(i + 2) % 4]->pt.y - v4;
  1686                         float sign33 = 
a3 * d33 - c33 * 
b3;
  1687                         float sign43 = a4 * d43 - c43 * b4;
  1695                         float x5 = cur_quad->corners[i]->pt.x;
  1696                         float y5 = cur_quad->corners[i]->pt.y;
  1697                         float x6 = cur_quad->corners[(i + 1) % 4]->pt.x;
  1698                         float y6 = cur_quad->corners[(i + 1) % 4]->pt.y;
  1702                         float x8 = cur_quad->corners[(i + 3) % 4]->pt.x;
  1703                         float y8 = cur_quad->corners[(i + 3) % 4]->pt.y;
  1714                         float c51 = cur_quad->corners[(i + 2) % 4]->pt.x - x5;
  1715                         float d51 = cur_quad->corners[(i + 2) % 4]->pt.y - y5;
  1717                         float c52 = new_quads[k]->corners[j]->pt.x - x5;
  1718                         float d52 = new_quads[k]->corners[j]->pt.y - y5;
  1719                         float sign51 = a5 * d51 - c51 * b5;
  1720                         float sign52 = a5 * d52 - c52 * b5;
  1725                         float c61 = cur_quad->corners[(i + 2) % 4]->pt.x - x7;
  1726                         float d61 = cur_quad->corners[(i + 2) % 4]->pt.y - y7;
  1728                         float c62 = new_quads[k]->corners[j]->pt.x - x7;
  1729                         float d62 = new_quads[k]->corners[j]->pt.y - y7;
  1730                         float sign61 = a6 * d61 - c61 * b6;
  1731                         float sign62 = a6 * d62 - c62 * b6;
  1736                         float u5 = new_quads[k]->corners[j]->pt.x;
  1737                         float v5 = new_quads[k]->corners[j]->pt.y;
  1738                         float u6 = new_quads[k]->corners[(j + 1) % 4]->pt.x;
  1739                         float v6 = new_quads[k]->corners[(j + 1) % 4]->pt.y;
  1743                         float u8 = new_quads[k]->corners[(j + 3) % 4]->pt.x;
  1744                         float v8 = new_quads[k]->corners[(j + 3) % 4]->pt.y;
  1755                         float c71 = cur_quad->corners[i]->pt.x - u5;
  1756                         float d71 = cur_quad->corners[i]->pt.y - v5;
  1759                             new_quads[k]->corners[(j + 2) % 4]->pt.x - u5;
  1761                             new_quads[k]->corners[(j + 2) % 4]->pt.y - v5;
  1762                         float sign71 = a7 * d71 - c71 * b7;
  1763                         float sign72 = a7 * d72 - c72 * b7;
  1768                         float c81 = cur_quad->corners[i]->pt.x - u7;
  1769                         float d81 = cur_quad->corners[i]->pt.y - v7;
  1772                             new_quads[k]->corners[(j + 2) % 4]->pt.x - u7;
  1774                             new_quads[k]->corners[(j + 2) % 4]->pt.y - v7;
  1775                         float sign81 = a8 * d81 - c81 * b8;
  1776                         float sign82 = a8 * d82 - c82 * b8;
  1779                         if (((sign11 < 0 && sign12 < 0) ||
  1780                              (sign11 > 0 && sign12 > 0)) &&
  1781                             ((sign21 < 0 && sign22 < 0) ||
  1782                              (sign21 > 0 && sign22 > 0)) &&
  1783                             ((sign31 < 0 && sign32 < 0) ||
  1784                              (sign31 > 0 && sign32 > 0)) &&
  1785                             ((sign41 < 0 && sign42 < 0) ||
  1786                              (sign41 > 0 && sign42 > 0)) &&
  1787                             ((sign11 < 0 && sign13 < 0) ||
  1788                              (sign11 > 0 && sign13 > 0)) &&
  1789                             ((sign21 < 0 && sign23 < 0) ||
  1790                              (sign21 > 0 && sign23 > 0)) &&
  1791                             ((sign31 < 0 && sign33 < 0) ||
  1792                              (sign31 > 0 && sign33 > 0)) &&
  1793                             ((sign41 < 0 && sign43 < 0) ||
  1794                              (sign41 > 0 && sign43 > 0)) &&
  1795                             ((sign51 < 0 && sign52 > 0) ||
  1796                              (sign51 > 0 && sign52 < 0)) &&
  1797                             ((sign61 < 0 && sign62 > 0) ||
  1798                              (sign61 > 0 && sign62 < 0)) &&
  1799                             ((sign71 < 0 && sign72 > 0) ||
  1800                              (sign71 > 0 && sign72 < 0)) &&
  1801                             ((sign81 < 0 && sign82 > 0) ||
  1802                              (sign81 > 0 && sign82 < 0)))
  1804                             closest_corner_idx = j;
  1805                             closest_quad = new_quads[k];
  1813             if (closest_corner_idx >= 0 && min_dist < FLT_MAX)
  1816                     closest_quad->corners[closest_corner_idx];
  1817                 closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f;
  1818                 closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f;
  1823                 cur_quad->corners[i]->pt.x = closest_corner->pt.x;
  1824                 cur_quad->corners[i]->pt.y = closest_corner->pt.y;
  1825                 cur_quad->neighbors[i] = closest_quad;
  1826                 closest_quad->corners[closest_corner_idx]->pt.x =
  1827                     closest_corner->pt.x;
  1828                 closest_quad->corners[closest_corner_idx]->pt.y =
  1829                     closest_corner->pt.y;
  1833                 closest_quad->labeled = 
true;
  1839                 newQuad->edge_len = closest_quad->edge_len;
  1840                 newQuad->group_idx =
  1841                     cur_quad->group_idx;  
  1842                 newQuad->labeled = 
false;  
  1846                 newQuad->neighbors[closest_corner_idx] = cur_quad;
  1847                 newQuad->neighbors[(closest_corner_idx + 1) % 4]
  1849                 newQuad->neighbors[(closest_corner_idx + 2) % 4]
  1851                 newQuad->neighbors[(closest_corner_idx + 3) % 4]
  1854                 for (
int j = 0; j < 4; j++)
  1857                     newQuad->corners[j]->pt.x = closest_quad->corners[j]->pt.x;
  1858                     newQuad->corners[j]->pt.y = closest_quad->corners[j]->pt.y;
  1861                 old_quads.push_back(newQuad);
  1862                 cur_quad->neighbors[i] = newQuad;
  1878     vector<CvCBQuad::Ptr>& out_quads, vector<CvCBCorner::Ptr>& out_corners,
  1879     const CImage& image, 
int flags, [[maybe_unused]] 
int dilation,
  1887     cv::MemStorage temp_storage = cv::MemStorage(cvCreateMemStorage(0));
  1889     CvSeq* src_contour = 
nullptr;
  1892     CvContourScanner scanner;
  1896     const int min_size =
  1899     root = cvCreateSeq(0, 
sizeof(CvSeq), 
sizeof(CvSeq*), temp_storage);
  1903     IplImage im_ipl = cvIplImage(im_mat);
  1904     scanner = cvStartFindContours(
  1905         &im_ipl, temp_storage, 
sizeof(
CvContourEx), CV_RETR_CCOMP,
  1906         CV_CHAIN_APPROX_SIMPLE);
  1909     while ((src_contour = cvFindNextContour(scanner)) != 
nullptr)
  1911         CvSeq* dst_contour = 
nullptr;
  1912         CvRect rect = ((CvContour*)src_contour)->rect;
  1925         if (CV_IS_SEQ_HOLE(src_contour) && rect.width * rect.height >= min_size)
  1927             int min_approx_level = 2, max_approx_level;
  1928             if (firstRun == 
true)
  1929                 max_approx_level = 3;
  1933             for (approx_level = min_approx_level;
  1934                  approx_level <= max_approx_level; approx_level++)
  1936                 dst_contour = cvApproxPoly(
  1937                     src_contour, 
sizeof(CvContour), temp_storage,
  1938                     CV_POLY_APPROX_DP, (
float)approx_level);
  1942                 dst_contour = cvApproxPoly(
  1943                     dst_contour, 
sizeof(CvContour), temp_storage,
  1944                     CV_POLY_APPROX_DP, (
float)approx_level);
  1946                 if (dst_contour->total == 4) 
break;
  1950             if (dst_contour->total == 4 && cvCheckContourConvexity(dst_contour))
  1957                 for (
int i = 0; i < 4; i++)
  1958                     pt[i] = *(CvPoint*)cvGetSeqElem(dst_contour, i);
  1982                     auto* parent = (
CvContourEx*)(src_contour->v_prev);
  1984                     if (!board || board->
counter < parent->counter)
  1986                     dst_contour->v_prev = (CvSeq*)parent;
  1987                     cvSeqPush(root, &dst_contour);
  1994     cvEndFindContours(&scanner);
  1998     for (
int q = 0; q < root->total; q++)
  2001     out_corners.clear();
  2002     for (
int q = 0; q < 4 * root->total; q++)
  2006     for (
int idx = 0; idx < root->total; idx++)
  2009         src_contour = *(CvSeq**)cvGetSeqElem(root, idx);
  2010         if ((flags & cv::CALIB_CB_FILTER_QUADS) &&
  2011             src_contour->v_prev != (CvSeq*)board)
  2017         assert(src_contour->total == 4);
  2018         for (
int i = 0; i < 4; i++)
  2021                 cvPointTo32f(*(CvPoint*)cvGetSeqElem(src_contour, i));
  2023                 [quad_count * 4 + i];  
  2028             q->corners[i] = corner;
  2030         q->edge_len = FLT_MAX;
  2031         for (
int i = 0; i < 4; i++)
  2033             float dx = q->corners[i]->pt.x - q->corners[(i + 1) & 3]->pt.x;
  2034             float dy = q->corners[i]->pt.y - q->corners[(i + 1) & 3]->pt.y;
  2035             float d = dx * dx + dy * dy;
  2036             if (q->edge_len > d) q->edge_len = d;
  2041     if (cvGetErrStatus() < 0)
  2045         out_corners.clear();
  2056     const std::vector<CvCBQuad::Ptr>& output_quads, 
const CvSize& pattern_size,
  2057     std::vector<CvPoint2D32f>& out_corners)
  2060     out_corners.clear();
  2062     bool flagRow = 
false;
  2063     bool flagColumn = 
false;
  2064     int maxPattern_sizeRow = -1;
  2065     int maxPattern_sizeColumn = -1;
  2071     int min_column = 127;
  2072     int max_column = -127;
  2074     for (
size_t i = 0; i < output_quads.size(); i++)
  2078         for (
int j = 0; j < 4; j++)
  2080             if ((q->corners[j])->row > max_row) max_row = (q->corners[j])->row;
  2081             if ((q->corners[j])->row < min_row) min_row = (q->corners[j])->row;
  2082             if ((q->corners[j])->column > max_column)
  2083                 max_column = (q->corners[j])->column;
  2084             if ((q->corners[j])->column < min_column)
  2085                 min_column = (q->corners[j])->column;
  2093     for (
size_t i = 0; i < output_quads.size(); i++)
  2097         for (
int j = 0; j < 4; j++)
  2099             if ((q->corners[j])->column == max_column &&
  2100                 (q->corners[j])->row != min_row &&
  2101                 (q->corners[j])->row != max_row)
  2103                 if ((q->corners[j]->needsNeighbor) == 
false)
  2110             if ((q->corners[j])->row == max_row &&
  2111                 (q->corners[j])->column != min_column &&
  2112                 (q->corners[j])->column != max_column)
  2114                 if ((q->corners[j]->needsNeighbor) == 
false)
  2124     if (flagColumn == 
true)
  2126         if (max_column - min_column == pattern_size.width + 1)
  2128             maxPattern_sizeColumn = pattern_size.width;
  2129             maxPattern_sizeRow = pattern_size.height;
  2133             maxPattern_sizeColumn = pattern_size.height;
  2134             maxPattern_sizeRow = pattern_size.width;
  2137     else if (flagRow == 
true)
  2139         if (max_row - min_row == pattern_size.width + 1)
  2141             maxPattern_sizeRow = pattern_size.width;
  2142             maxPattern_sizeColumn = pattern_size.height;
  2146             maxPattern_sizeRow = pattern_size.height;
  2147             maxPattern_sizeColumn = pattern_size.width;
  2155         maxPattern_sizeColumn = max(pattern_size.width, pattern_size.height);
  2156         maxPattern_sizeRow = max(pattern_size.width, pattern_size.height);
  2160     if (maxPattern_sizeRow * maxPattern_sizeColumn !=
  2161         pattern_size.width * pattern_size.height)
  2165     bool do_swap_col_row = maxPattern_sizeRow != pattern_size.height;
  2167     if (do_swap_col_row)
  2169         std::swap(min_row, min_column);
  2170         std::swap(maxPattern_sizeRow, maxPattern_sizeColumn);
  2175     for (
int i = min_row + 1; i < maxPattern_sizeRow + min_row + 1; i++)
  2177         for (
int j = min_column + 1; j < maxPattern_sizeColumn + min_column + 1;
  2183             for (
size_t k = 0; k < output_quads.size(); k++)
  2185                 for (
int l = 0; l < 4; l++)
  2187                     int r = output_quads[k]->corners[l]->row;
  2188                     int c = output_quads[k]->corners[l]->column;
  2189                     if (do_swap_col_row) std::swap(r, c);
  2191                     if (r == i && c == j)
  2200                             out_corners.push_back(
  2201                                 output_quads[k]->corners[l]->pt);
  2211                         if (iter > 2) 
return -1;
  2220             if (iter == 1 || iter == 2)
  2231     return (out_corners.size() ==
  2232             size_t(pattern_size.width) * size_t(pattern_size.height))
  2241     std::map<CvCBQuad*, size_t> pointer2index;
  2242     for (
size_t i = 0; i < quads.size(); i++) pointer2index[quads[i].
get()] = i;
  2244     vector<std::array<size_t, 4>> neig_indices(quads.size());
  2245     for (
size_t i = 0; i < quads.size(); i++)
  2246         for (
size_t j = 0; j < 4; j++)
  2247             neig_indices[i][j] = pointer2index[quads[i]->neighbors[j].
get()];
  2249     std::vector<CvCBQuad::Ptr> new_quads = quads;
  2250     std::for_each(new_quads.begin(), new_quads.end(), [](
CvCBQuad::Ptr& ptr) {
  2253     for (
size_t i = 0; i < new_quads.size(); i++)
  2254         for (
size_t j = 0; j < 4; j++)
  2255             new_quads[i]->neighbors[j] = new_quads[neig_indices[i][j]];
  2262 #endif  // MRPT_HAS_OPENCV void mrFindQuadNeighbors2(std::vector< CvCBQuad::Ptr > &quads, int dilation)
 
std::shared_ptr< CvCBCorner > Ptr
 
Shallow copy: the copied object is a reference to the original one. 
 
void mrLabelQuadGroup(std::vector< CvCBQuad::Ptr > &quad_group, const CvSize &pattern_size, bool firstRun)
 
void icvCleanFoundConnectedQuads(std::vector< CvCBQuad::Ptr > &quad_group, const CvSize &pattern_size)
 
size_t getHeight() const override
Returns the height of the image in pixels. 
 
void asCvMat(cv::Mat &out_img, copy_type_t copy_type) const
Makes a shallow or deep copy of this image into the provided cv::Mat. 
 
int mrAugmentBestRun(std::vector< CvCBQuad::Ptr > &new_quads, int new_dilation, std::vector< CvCBQuad::Ptr > &old_quads, int old_dilation)
 
This base provides a set of functions for maths stuff. 
 
size_t getWidth() const override
Returns the width of the image in pixels. 
 
double median(const std::vector< double > &vec)
 
bool do_special_dilation(CImage &thresh_img, const int dilations, IplConvKernel *kernel_cross, IplConvKernel *kernel_rect, IplConvKernel *kernel_diag1, IplConvKernel *kernel_diag2, IplConvKernel *kernel_horz, IplConvKernel *kernel_vert)
 
double triangleArea(double x0, double y0, double x1, double y1, double x2, double y2)
 
int myQuads2Points(const std::vector< CvCBQuad::Ptr > &output_quads, const CvSize &pattern_size, std::vector< CvPoint2D32f > &out_corners)
 
#define MAX_CONTOUR_APPROX
 
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries. 
 
struct _IplImage IplImage
 
std::shared_ptr< CvCBQuad > Ptr
 
CvCBCorner::Ptr corners[4]
 
void quadListMakeUnique(std::vector< CvCBQuad::Ptr > &quads)
 
void icvFindConnectedQuads(std::vector< CvCBQuad::Ptr > &quad, std::vector< CvCBQuad::Ptr > &out_group, const int group_idx, [[maybe_unused]] const int dilation)
 
int cvFindChessboardCorners3(const CImage &img_, CvSize pattern_size, std::vector< CvPoint2D32f > &out_corners)
 
A class for storing images as grayscale or RGB bitmaps. 
 
int icvGenerateQuads(vector< CvCBQuad::Ptr > &out_quads, vector< CvCBCorner::Ptr > &out_corners, const CImage &image, int flags, [[maybe_unused]] int dilation, bool firstRun)