66 #define MAX_CONTOUR_APPROX 7 71 IplConvKernel *kernel_cross,
72 IplConvKernel *kernel_rect,
73 IplConvKernel *kernel_diag1,
74 IplConvKernel *kernel_diag2,
75 IplConvKernel *kernel_horz,
76 IplConvKernel *kernel_vert
86 cvDilate( thresh_img.
getAs<IplImage>(), thresh_img.
getAs<IplImage>(), kernel_cross, 1);
88 cvDilate( thresh_img.
getAs<IplImage>(), thresh_img.
getAs<IplImage>(), kernel_rect, 1);
90 cvDilate( thresh_img.
getAs<IplImage>(), thresh_img.
getAs<IplImage>(), kernel_cross, 1);
92 cvDilate( thresh_img.
getAs<IplImage>(), thresh_img.
getAs<IplImage>(), kernel_rect, 1);
94 cvDilate( thresh_img.
getAs<IplImage>(), thresh_img.
getAs<IplImage>(), kernel_cross, 1);
96 cvDilate( thresh_img.
getAs<IplImage>(), thresh_img.
getAs<IplImage>(), kernel_rect, 1);
100 IplImage *ipl = thresh_img.
getAs<IplImage>();
106 case 37: cvDilate(ipl,ipl, kernel_cross , 1); isLast =
true;
108 case 36: cvErode (ipl,ipl, kernel_rect , 1);
110 case 35: cvDilate(ipl,ipl, kernel_vert , 1);
112 case 34: cvDilate(ipl,ipl, kernel_vert , 1);
114 case 33: cvDilate(ipl,ipl, kernel_vert , 1);
116 case 32: cvDilate(ipl,ipl, kernel_vert , 1);
118 case 31: cvDilate(ipl,ipl, kernel_vert , 1);
break;
120 case 30: cvDilate(ipl,ipl, kernel_cross , 1);
122 case 29: cvErode (ipl,ipl, kernel_rect , 1);
124 case 28: cvDilate(ipl,ipl, kernel_horz , 1);
126 case 27: cvDilate(ipl,ipl, kernel_horz , 1);
128 case 26: cvDilate(ipl,ipl, kernel_horz , 1);
130 case 25: cvDilate(ipl,ipl, kernel_horz , 1);
132 case 24: cvDilate(ipl,ipl, kernel_horz , 1);
break;
134 case 23: cvDilate(ipl,ipl, kernel_diag2 , 1);
136 case 22: cvDilate(ipl,ipl, kernel_diag1 , 1);
138 case 21: cvDilate(ipl,ipl, kernel_diag2 , 1);
140 case 20: cvDilate(ipl,ipl, kernel_diag1 , 1);
142 case 19: cvDilate(ipl,ipl, kernel_diag2 , 1);
144 case 18: cvDilate(ipl,ipl, kernel_diag1 , 1);
break;
146 case 17: cvDilate(ipl,ipl, kernel_diag2 , 1);
148 case 16: cvDilate(ipl,ipl, kernel_diag2 , 1);
150 case 15: cvDilate(ipl,ipl, kernel_diag2 , 1);
152 case 14: cvDilate(ipl,ipl, kernel_diag2 , 1);
break;
154 case 13: cvDilate(ipl,ipl, kernel_diag1 , 1);
156 case 12: cvDilate(ipl,ipl, kernel_diag1 , 1);
158 case 11: cvDilate(ipl,ipl, kernel_diag1 , 1);
160 case 10: cvDilate(ipl,ipl, kernel_diag1 , 1);
break;
162 case 9: cvDilate(ipl,ipl, kernel_cross , 1);
164 case 8: cvErode (ipl,ipl, kernel_rect , 1);
166 case 7: cvDilate(ipl,ipl, kernel_cross , 1);
168 case 6: cvDilate(ipl,ipl, kernel_diag2 , 1); isLast =
true;
170 case 5: cvDilate(ipl,ipl, kernel_diag1 , 1);
172 case 4: cvDilate(ipl,ipl, kernel_rect , 1);
174 case 3: cvErode (ipl,ipl, kernel_cross , 1);
176 case 2: cvDilate(ipl,ipl, kernel_rect , 1);
178 case 1: cvDilate(ipl,ipl, kernel_cross , 1);
199 size_t max_count = 0;
200 int max_dilation_run_ID = -1;
205 vector<CvCBQuadPtr> quads;
206 vector<CvCBQuadPtr> quad_group;
207 vector<CvCBCornerPtr> corners;
208 vector<CvCBQuadPtr> output_quad_group;
214 int quad_count, group_idx;
216 if( pattern_size.width < 2 || pattern_size.height < 2 )
218 std::cerr <<
"Pattern should have at least 2x2 size" << endl;
221 if( pattern_size.width > 127 || pattern_size.height > 127 )
223 std::cerr <<
"Pattern should not have a size larger than 127 x 127" << endl;
234 IplConvKernel *kernel_cross = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL);
235 IplConvKernel *kernel_rect = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_RECT,NULL);
237 static int kernel_diag1_vals[9] = {
241 IplConvKernel *kernel_diag1 = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_diag1_vals);
242 static int kernel_diag2_vals[9] = {
246 IplConvKernel *kernel_diag2 = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_diag2_vals);
247 static int kernel_horz_vals[9] = {
251 IplConvKernel *kernel_horz = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_horz_vals);
252 static int kernel_vert_vals[9] = {
256 IplConvKernel *kernel_vert = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_vert_vals);
262 block_size = cvRound(
MIN(
img.getWidth(),
img.getHeight())*0.2)|1;
264 cvAdaptiveThreshold(
img.getAs<IplImage>(), thresh_img.getAs<IplImage>(), 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, block_size, 0 );
266 cvCopy( thresh_img.getAs<IplImage>(), thresh_img_save.getAs<IplImage>());
271 img.saveToFile(
"./DBG_OrigImg.png");
284 bool last_dilation =
false;
286 for(
int dilations = 0; !last_dilation; dilations++ )
289 cvCopy( thresh_img_save.getAs<IplImage>(), thresh_img.getAs<IplImage>() );
292 last_dilation =
do_special_dilation(thresh_img, dilations,kernel_cross,kernel_rect,kernel_diag1,kernel_diag2, kernel_horz,kernel_vert);
295 thresh_img.saveToFile(
mrpt::format(
"./DBG_dilation=%i.png",(
int)dilations));
302 cvRectangle( thresh_img.getAs<IplImage>(), cvPoint(0,0),
303 cvPoint(thresh_img.getWidth()-1,thresh_img.getHeight()-1),
304 CV_RGB(255,255,255), 3, 8);
308 quad_count =
icvGenerateQuads( quads, corners, thresh_img, flags, dilations,
true );
309 if( quad_count <= 0 )
319 IplImage* imageCopy22 = cvCreateImage( cvGetSize(thresh_img.getAs<IplImage>()), 8, 3 );
322 IplImage* imageCopy2 = cvCreateImage( cvGetSize(thresh_img.getAs<IplImage>()), 8, 1 );
323 cvCopy( thresh_img.getAs<IplImage>(), imageCopy2);
324 cvCvtColor( imageCopy2, imageCopy22, CV_GRAY2BGR );
326 for(
int kkk = 0; kkk < quad_count; kkk++ )
330 pt[0].x = (int)print_quad->corners[0]->pt.x;
331 pt[0].y = (
int)print_quad->corners[0]->pt.y;
332 pt[1].x = (int)print_quad->corners[1]->pt.x;
333 pt[1].y = (
int)print_quad->corners[1]->pt.y;
334 pt[2].x = (int)print_quad->corners[2]->pt.x;
335 pt[2].y = (
int)print_quad->corners[2]->pt.y;
336 pt[3].x = (int)print_quad->corners[3]->pt.x;
337 pt[3].y = (
int)print_quad->corners[3]->pt.y;
338 cvLine( imageCopy22, pt[0], pt[1], CV_RGB(255,255,0), 1, 8 );
339 cvLine( imageCopy22, pt[1], pt[2], CV_RGB(255,255,0), 1, 8 );
340 cvLine( imageCopy22, pt[2], pt[3], CV_RGB(255,255,0), 1, 8 );
341 cvLine( imageCopy22, pt[3], pt[0], CV_RGB(255,255,0), 1, 8 );
345 cvSaveImage(
mrpt::format(
"./DBG_dilation=%i_quads.png",(
int)dilations).c_str(), imageCopy22);
348 IplImage* imageCopy3 = cvCreateImage( cvGetSize(thresh_img.getAs<IplImage>()), 8, 3 );
349 cvCopy( imageCopy22, imageCopy3);
352 int line_type = CV_AA;
353 CvScalar
color = {{0,0,255}};
354 for(
int kkk = 0; kkk < quad_count; kkk++ )
357 for(
int kkkk = 0; kkkk < 4; kkkk++ )
359 if( print_quad2->neighbors[kkkk] )
361 pt.x = (int)(print_quad2->corners[kkkk]->pt.x);
362 pt.y = (int)(print_quad2->corners[kkkk]->pt.y);
363 cvCircle( imageCopy3, pt, 3,
color, 1, line_type,
scale);
367 cvSaveImage(
mrpt::format(
"./DBG_allFoundNeighbors_%05i.png",cnt).c_str(), imageCopy3);
380 for( group_idx = 0; ; group_idx++ )
384 if( quad_group.empty() )
388 size_t count = quad_group.size();
394 if(
count > max_count)
400 max_dilation_run_ID = dilations;
416 IplImage* imageCopy11 = cvCreateImage( cvGetSize(thresh_img.getAs<IplImage>()), 8, 3 );
417 cvCopy( imageCopy22, imageCopy11);
422 int min_column = -15;
424 for(
int i = min_row; i <= max_row; i++)
426 for(
int j = min_column; j <= max_column; j++)
428 for(
size_t k = 0; k <
count; k++)
430 for(
size_t l = 0; l < 4; l++)
432 if( ((quad_group[k])->corners[l]->
row == i) && ((quad_group[k])->corners[l]->
column == j) )
438 cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.2, 0.2, 0, 1);
440 ptt.x = (int) quad_group[k]->corners[l]->pt.x;
441 ptt.y = (
int) quad_group[k]->corners[l]->pt.y;
444 if ((quad_group[k])->corners[l]->needsNeighbor ==
false)
446 cvPutText(imageCopy11, str, ptt, &font, CV_RGB(0,255,0));
450 cvPutText(imageCopy11, str, ptt, &font, CV_RGB(255,0,0));
459 cvSaveImage(
format(
"./DBG_CornersIncreasingOrder_%05i.png",cnt++).c_str(), imageCopy11);
471 output_quad_group = quad_group;
480 found =
myQuads2Points( output_quad_group, pattern_size,out_corners);
483 if (found != -1 && found != 1)
493 bool last_dilation =
false;
494 for(
int dilations = 0; !last_dilation; dilations++ )
500 cvCopy( thresh_img_save.getAs<IplImage>(), thresh_img.getAs<IplImage>());
503 last_dilation =
do_special_dilation(thresh_img, dilations,kernel_cross,kernel_rect,kernel_diag1,kernel_diag2, kernel_horz,kernel_vert);
505 cvRectangle( thresh_img.getAs<IplImage>(), cvPoint(0,0),
506 cvPoint(thresh_img.getWidth()-1,thresh_img.getHeight()-1),
507 CV_RGB(255,255,255), 3, 8);
512 IplImage* imageCopy23 = cvCreateImage( cvGetSize(thresh_img.getAs<IplImage>()), 8, 3 );
513 cvCvtColor( thresh_img.getAs<IplImage>(), imageCopy23, CV_GRAY2BGR );
516 for(
size_t kkk = 0; kkk < max_count; kkk++ )
518 const CvCBQuadPtr & print_quad2 = output_quad_group[kkk];
519 for(
size_t kkkk = 0; kkkk < 4; kkkk++ )
521 pt[kkkk].x = (int) print_quad2->corners[kkkk]->pt.x;
522 pt[kkkk].y = (
int) print_quad2->corners[kkkk]->pt.y;
525 cvFillConvexPoly ( imageCopy23, pt, 4, CV_RGB(255*0.1,255*0.25,255*0.6));
529 sprintf(str,
"Dilation Run No.: %i",dilations);
531 cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 2);
535 cvSaveImage(
"./DBG_part2Start.png", imageCopy23);
540 quad_count =
icvGenerateQuads( quads, corners, thresh_img, flags, dilations,
false );
541 if( quad_count <= 0 )
548 for(
int kkk = 0; kkk < quad_count; kkk++ )
553 pt[0].x = (int)print_quad->corners[0]->pt.x;
554 pt[0].y = (
int)print_quad->corners[0]->pt.y;
555 pt[1].x = (int)print_quad->corners[1]->pt.x;
556 pt[1].y = (
int)print_quad->corners[1]->pt.y;
557 pt[2].x = (int)print_quad->corners[2]->pt.x;
558 pt[2].y = (
int)print_quad->corners[2]->pt.y;
559 pt[3].x = (int)print_quad->corners[3]->pt.x;
560 pt[3].y = (
int)print_quad->corners[3]->pt.y;
561 cvLine( imageCopy23, pt[0], pt[1], CV_RGB(255,0,0), 1, 8 );
562 cvLine( imageCopy23, pt[1], pt[2], CV_RGB(255,0,0), 1, 8 );
563 cvLine( imageCopy23, pt[2], pt[3], CV_RGB(255,0,0), 1, 8 );
564 cvLine( imageCopy23, pt[3], pt[0], CV_RGB(255,0,0), 1, 8 );
581 for(
size_t kkk = 0; kkk < max_count; kkk++ )
583 const CvCBQuadPtr & print_quad = output_quad_group[kkk];
586 pt[0].x = (int)print_quad->corners[0]->pt.x;
587 pt[0].y = (
int)print_quad->corners[0]->pt.y;
588 pt[1].x = (int)print_quad->corners[1]->pt.x;
589 pt[1].y = (
int)print_quad->corners[1]->pt.y;
590 pt[2].x = (int)print_quad->corners[2]->pt.x;
591 pt[2].y = (
int)print_quad->corners[2]->pt.y;
592 pt[3].x = (int)print_quad->corners[3]->pt.x;
593 pt[3].y = (
int)print_quad->corners[3]->pt.y;
611 cvSaveImage(
"./DBG_part2StartAndNewQuads.png", imageCopy23);
626 while ( feedBack == -1)
629 output_quad_group, max_dilation_run_ID );
637 for(
size_t kkk = max_count; kkk < max_count+1; kkk++ )
640 remember_quad = print_quad;
642 pt[0].x = (int)print_quad->corners[0]->pt.x;
643 pt[0].y = (
int)print_quad->corners[0]->pt.y;
644 pt[1].x = (int)print_quad->corners[1]->pt.x;
645 pt[1].y = (
int)print_quad->corners[1]->pt.y;
646 pt[2].x = (int)print_quad->corners[2]->pt.x;
647 pt[2].y = (
int)print_quad->corners[2]->pt.y;
648 pt[3].x = (int)print_quad->corners[3]->pt.x;
649 pt[3].y = (
int)print_quad->corners[3]->pt.y;
650 cvLine( imageCopy23, pt[0], pt[1], CV_RGB(255,0,0), 2, 8 );
651 cvLine( imageCopy23, pt[1], pt[2], CV_RGB(255,0,0), 2, 8 );
652 cvLine( imageCopy23, pt[2], pt[3], CV_RGB(255,0,0), 2, 8 );
653 cvLine( imageCopy23, pt[3], pt[0], CV_RGB(255,0,0), 2, 8 );
659 for(
size_t kkk = 0; kkk < max_count; kkk++ )
661 const CvCBQuadPtr &print_quad = output_quad_group[kkk];
663 for(
size_t kkkk = 0; kkkk < 4; kkkk++)
665 if(print_quad->neighbors[kkkk] == remember_quad)
668 pt[0].x = (int)print_quad->corners[0]->pt.x;
669 pt[0].y = (
int)print_quad->corners[0]->pt.y;
670 pt[1].x = (int)print_quad->corners[1]->pt.x;
671 pt[1].y = (
int)print_quad->corners[1]->pt.y;
672 pt[2].x = (int)print_quad->corners[2]->pt.x;
673 pt[2].y = (
int)print_quad->corners[2]->pt.y;
674 pt[3].x = (int)print_quad->corners[3]->pt.x;
675 pt[3].y = (
int)print_quad->corners[3]->pt.y;
676 cvLine( imageCopy23, pt[0], pt[1], CV_RGB(255,0,0), 2, 8 );
677 cvLine( imageCopy23, pt[1], pt[2], CV_RGB(255,0,0), 2, 8 );
678 cvLine( imageCopy23, pt[2], pt[3], CV_RGB(255,0,0), 2, 8 );
679 cvLine( imageCopy23, pt[3], pt[0], CV_RGB(255,0,0), 2, 8 );
684 cvSaveImage(
"./DBG_part2StartAndSelectedQuad.png", imageCopy23);
695 max_count = max_count + 1;
701 found =
myQuads2Points( output_quad_group, pattern_size,out_corners);
703 if (found == -1 || found == 1)
706 last_dilation =
true;
718 cvReleaseStructuringElement(&kernel_cross);
719 cvReleaseStructuringElement(&kernel_rect);
720 cvReleaseStructuringElement(&kernel_diag1);
721 cvReleaseStructuringElement(&kernel_diag2);
722 cvReleaseStructuringElement(&kernel_horz);
723 cvReleaseStructuringElement(&kernel_vert);
733 std::cerr <<
"While linking the corners a problem was encountered. No corner sequence is returned. " << endl;
749 double x2,
double y2 )
751 return std::abs( 0.5*(x0*(y1-y2)+x1*(y2-y0)+x2*(y0-y1)) );
754 double median(
const std::vector<double> &vec)
756 std::vector<double>
v = vec;
757 const size_t n =
v.size() / 2;
758 nth_element(
v.begin(),
v.begin()+
n,
v.end());
769 #if CV_MAJOR_VERSION==1 770 CvMemStorage* temp_storage = NULL;
772 cv::MemStorage temp_storage;
775 CvPoint2D32f center = cvPoint2D32f(0,0);
778 const size_t expected_quads_count = ((pattern_size.width + 1)*(pattern_size.height + 1) + 1)/2;
783 const size_t nQuads = quad_group.size();
784 if(nQuads <= expected_quads_count )
789 vector<CvPoint2D32f> centers( nQuads );
790 #if CV_MAJOR_VERSION==1 791 temp_storage = cvCreateMemStorage(0);
793 temp_storage = cv::MemStorage(cvCreateMemStorage(0));
798 std::vector<double> quad_areas(nQuads);
799 double min_area = DBL_MAX, max_area=-DBL_MAX, mean_area = 0.0;
801 for(
size_t i = 0; i < nQuads; i++ )
803 CvPoint2D32f ci = cvPoint2D32f(0,0);
806 for(
size_t j = 0; j < 4; j++ )
808 CvPoint2D32f pt =
q->corners[j]->pt;
819 q->corners[0]->pt.x,
q->corners[0]->pt.y,
820 q->corners[1]->pt.x,
q->corners[1]->pt.y,
821 q->corners[2]->pt.x,
q->corners[2]->pt.y )
824 q->corners[0]->pt.x,
q->corners[0]->pt.y,
825 q->corners[2]->pt.x,
q->corners[2]->pt.y,
826 q->corners[3]->pt.x,
q->corners[3]->pt.y );
831 if (
a<min_area) min_area=
a;
832 if (
a>max_area) max_area=
a;
843 const double median_area =
median(quad_areas);
846 for(
size_t i = 0; i < nQuads; i++ )
848 quad_group[i]->area_ratio = quad_group[i]->area / median_area;
863 while( quad_group.size() > expected_quads_count )
865 double min_box_area = DBL_MAX;
866 int min_box_area_index = -1;
869 int most_outlier_idx = -1;
870 double most_outlier_ratio = 1.0;
871 for(
size_t skip = 0; skip < quad_group.size(); skip++ )
873 double ar = quad_group[skip]->area_ratio;
874 if (ar>1.0) ar=1.0/ar;
876 if (ar<most_outlier_ratio)
878 most_outlier_ratio=ar;
879 most_outlier_idx = skip;
883 if (most_outlier_idx>=0)
885 min_box_area_index=most_outlier_idx;
888 if (min_box_area_index==-1)
891 for(
size_t skip = 0; skip < quad_group.size(); skip++ )
894 CvPoint2D32f temp = centers[skip];
895 centers[skip] = center;
896 CvMat pointMat = cvMat(1, quad_group.size(), CV_32FC2, ¢ers[0]);
897 CvSeq *hull = cvConvexHull2( &pointMat, temp_storage , CV_CLOCKWISE, 1 );
898 centers[skip] = temp;
899 double hull_area = fabs(cvContourArea(hull, CV_WHOLE_SEQ));
903 if( hull_area < min_box_area )
905 min_box_area = hull_area;
906 min_box_area_index = skip;
908 cvClearMemStorage( temp_storage );
916 for(
size_t i = 0; i < quad_group.size(); i++ )
920 for(
size_t j = 0; j < 4; j++ )
922 if(
q->neighbors[j] == q0 )
924 q->neighbors[j].reset();
926 for(
size_t k = 0; k < 4; k++ )
927 if( q0->neighbors[k] ==
q )
929 q0->neighbors[k].reset();
939 quad_group.erase( quad_group.begin() + min_box_area_index);
940 centers.erase(centers.begin() + min_box_area_index );
944 #if CV_MAJOR_VERSION==1 945 cvReleaseMemStorage(&temp_storage);
954 std::vector<CvCBQuadPtr> &quad,
955 std::vector<CvCBQuadPtr> &out_group,
963 const size_t quad_count = quad.size();
966 for(
size_t i = 0; i < quad_count; i++ )
968 if( quad[i]->
count < 0 || quad[i]->group_idx >= 0)
975 std::stack<CvCBQuadPtr> seqStack;
979 q->group_idx = group_idx;
980 out_group.push_back(
q );
982 while( !seqStack.empty() )
987 for(
size_t k = 0; k < 4; k++ )
993 if( neighbor && neighbor->count > 0 && neighbor->group_idx < 0 )
995 neighbor->group_idx = group_idx;
996 seqStack.push(neighbor);
997 out_group.push_back( neighbor );
1011 void mrLabelQuadGroup( std::vector<CvCBQuadPtr> &quad_group,
const CvSize &pattern_size,
bool firstRun )
1013 const size_t count = quad_group.size();
1016 if (firstRun ==
true)
1021 int max_number = -1;
1022 for(
size_t i = 0; i <
count; i++ )
1025 if(
q->count > max_number)
1027 max_number =
q->count;
1030 if (max_number == 4)
1042 q->corners[0]->row = 0;
1043 q->corners[0]->column = 0;
1044 q->corners[1]->row = 0;
1045 q->corners[1]->column = 1;
1046 q->corners[2]->row = 1;
1047 q->corners[2]->column = 1;
1048 q->corners[3]->row = 1;
1049 q->corners[3]->column = 0;
1053 bool flag_changed =
true;
1054 while( flag_changed ==
true )
1057 flag_changed =
false;
1062 for(
int i =
int(
count-1); i >= 0; i-- )
1065 if ( (quad_group[i])->labeled ==
false )
1069 for(
size_t j = 0; j < 4; j++ )
1073 if( (quad_group[i])->neighbors[j] )
1075 CvCBQuadPtr &quadNeighborJ = quad_group[i]->neighbors[j];
1079 if( quadNeighborJ->labeled ==
true)
1085 int connectedNeighborCornerId = -1;
1086 for(
int k = 0; k < 4; k++)
1088 if( quadNeighborJ->neighbors[k] == quad_group[i] )
1090 connectedNeighborCornerId = k;
1103 CvCBCornerPtr &conCorner = quadNeighborJ->corners[connectedNeighborCornerId];
1104 CvCBCornerPtr &conCornerCW1 = quadNeighborJ->corners[(connectedNeighborCornerId+1)%4];
1105 CvCBCornerPtr &conCornerCW2 = quadNeighborJ->corners[(connectedNeighborCornerId+2)%4];
1106 CvCBCornerPtr &conCornerCW3 = quadNeighborJ->corners[(connectedNeighborCornerId+3)%4];
1108 (quad_group[i])->corners[j]->
row = conCorner->row;
1109 (quad_group[i])->corners[j]->column = conCorner->column;
1110 (quad_group[i])->corners[(j+1)%4]->row = conCorner->row - conCornerCW2->row + conCornerCW3->row;
1111 (quad_group[i])->corners[(j+1)%4]->column = conCorner->column - conCornerCW2->column + conCornerCW3->column;
1112 (quad_group[i])->corners[(j+2)%4]->row = conCorner->row + conCorner->row - conCornerCW2->row;
1113 (quad_group[i])->corners[(j+2)%4]->column = conCorner->column + conCorner->column - conCornerCW2->column;
1114 (quad_group[i])->corners[(j+3)%4]->row = conCorner->row - conCornerCW2->row + conCornerCW1->row;
1115 (quad_group[i])->corners[(j+3)%4]->column = conCorner->column - conCornerCW2->column + conCornerCW1->column;
1119 (quad_group[i])->labeled =
true;
1123 flag_changed =
true;
1142 int min_column = 127;
1143 int max_column = -127;
1145 for(
size_t i = 0; i <
count; i++ )
1149 for(
size_t j = 0; j < 4; j++ )
1151 if( (
q->corners[j])->row > max_row)
1152 max_row = (
q->corners[j])->row;
1154 if( (
q->corners[j])->row < min_row)
1155 min_row = (
q->corners[j])->row;
1157 if( (
q->corners[j])->column > max_column)
1158 max_column = (
q->corners[j])->column;
1160 if( (
q->corners[j])->column < min_column)
1161 min_column = (
q->corners[j])->column;
1168 for(
int i = min_row; i <= max_row; i++)
1170 for(
int j = min_column; j <= max_column; j++)
1181 for(
size_t k = 0; k <
count; k++)
1183 for(
size_t l = 0; l < 4; l++)
1185 if( ((quad_group[k])->corners[l]->row == i) && ((quad_group[k])->corners[l]->column == j) )
1191 (quad_group[k])->corners[l]->needsNeighbor =
false;
1192 (quad_group[quadID])->corners[cornerID]->needsNeighbor =
false;
1198 (quad_group[k])->corners[l]->needsNeighbor =
true;
1217 for(
int i = min_row; i <= max_row; i++)
1219 for(
int j = min_column; j <= max_column; j++)
1233 for(
size_t k = 0; k <
count; k++)
1235 for(
size_t l = 0; l < 4; l++)
1237 if( ((quad_group[k])->corners[l]->row == i) && ((quad_group[k])->corners[l]->column == j) )
1247 else if (number == 2)
1252 float delta_x = (quad_group[k])->corners[l]->pt.x - (quad_group[quadID])->corners[cornerID]->pt.x;
1253 float delta_y = (quad_group[k])->corners[l]->pt.y - (quad_group[quadID])->corners[cornerID]->pt.y;
1255 if (delta_x != 0 || delta_y != 0)
1258 (quad_group[k])->corners[l]->pt.x = (quad_group[k])->corners[l]->pt.x - delta_x/2;
1259 (quad_group[quadID])->corners[cornerID]->pt.x = (quad_group[quadID])->corners[cornerID]->pt.x + delta_x/2;
1260 (quad_group[k])->corners[l]->pt.y = (quad_group[k])->corners[l]->pt.y - delta_y/2;
1261 (quad_group[quadID])->corners[cornerID]->pt.y = (quad_group[quadID])->corners[cornerID]->pt.y + delta_y/2;
1264 else if (number > 2)
1272 number = number + 1;
1286 int largerDimPattern = max(pattern_size.height,pattern_size.width);
1287 int smallerDimPattern =
min(pattern_size.height,pattern_size.width);
1288 bool flagSmallerDim1 =
false;
1289 bool flagSmallerDim2 =
false;
1291 if((largerDimPattern + 1) == max_column - min_column)
1293 flagSmallerDim1 =
true;
1297 for(
size_t k = 0; k <
count; k++ )
1299 for(
size_t l = 0; l < 4; l++ )
1301 if ( (quad_group[k])->corners[l]->
column == min_column || (quad_group[k])->corners[l]->
column == max_column)
1304 (quad_group[k])->corners[l]->needsNeighbor =
false;
1310 if((largerDimPattern + 1) == max_row - min_row)
1312 flagSmallerDim2 =
true;
1316 for(
size_t k = 0; k <
count; k++ )
1318 for(
size_t l = 0; l < 4; l++ )
1320 if ( (quad_group[k])->corners[l]->row == min_row || (quad_group[k])->corners[l]->
row == max_row)
1323 (quad_group[k])->corners[l]->needsNeighbor =
false;
1338 if( (flagSmallerDim1 ==
false && flagSmallerDim2 ==
true) )
1342 if((smallerDimPattern + 1) == max_column - min_column)
1344 for(
size_t k = 0; k <
count; k++ )
1346 for(
int l = 0; l < 4; l++ )
1348 if ( (quad_group[k])->corners[l]->column == min_column || (quad_group[k])->corners[l]->
column == max_column)
1351 (quad_group[k])->corners[l]->needsNeighbor =
false;
1358 if( (flagSmallerDim1 ==
true && flagSmallerDim2 ==
false) )
1362 if((smallerDimPattern + 1) == max_row - min_row)
1364 for(
size_t k = 0; k <
count; k++ )
1366 for(
size_t l = 0; l < 4; l++ )
1368 if ( (quad_group[k])->corners[l]->row == min_row || (quad_group[k])->corners[l]->
row == max_row)
1371 (quad_group[k])->corners[l]->needsNeighbor =
false;
1378 if( (flagSmallerDim1 ==
false && flagSmallerDim2 ==
false) && smallerDimPattern + 1 < max_column - min_column )
1382 if((smallerDimPattern + 1) == max_row - min_row)
1384 for(
size_t k = 0; k <
count; k++ )
1386 for(
size_t l = 0; l < 4; l++ )
1388 if ( (quad_group[k])->corners[l]->row == min_row || (quad_group[k])->corners[l]->
row == max_row)
1391 (quad_group[k])->corners[l]->needsNeighbor =
false;
1398 if( (flagSmallerDim1 ==
false && flagSmallerDim2 ==
false) && smallerDimPattern + 1 < max_row - min_row )
1402 if((smallerDimPattern + 1) == max_column - min_column)
1404 for(
size_t k = 0; k <
count; k++ )
1406 for(
size_t l = 0; l < 4; l++ )
1408 if ( (quad_group[k])->corners[l]->column == min_column || (quad_group[k])->corners[l]->
column == max_column)
1411 (quad_group[k])->corners[l]->needsNeighbor =
false;
1435 const float thresh_dilation = (float)(2*dilation+3)*(2*dilation+3)*2;
1439 const size_t quad_count = quads.size();
1442 for(
size_t idx = 0; idx < quad_count; idx++ )
1449 for(
size_t i = 0; i < 4; i++ )
1452 float min_dist = FLT_MAX;
1453 int closest_corner_idx = -1;
1456 if( cur_quad->neighbors[i] )
1459 pt = cur_quad->corners[i]->pt;
1463 for(
size_t k = 0; k < quad_count; k++ )
1468 for(
size_t j = 0; j < 4; j++ )
1471 if( quads[k]->neighbors[j] )
1474 dx = pt.x - quads[k]->corners[j]->pt.x;
1475 dy = pt.y - quads[k]->corners[j]->pt.y;
1476 dist = dx * dx + dy * dy;
1482 if( dist < min_dist &&
1483 dist <= (cur_quad->edge_len + thresh_dilation) &&
1484 dist <= (quads[k]->edge_len + thresh_dilation) )
1488 float x1 = (cur_quad->corners[i]->pt.x + cur_quad->corners[(i+1)%4]->pt.x)/2;
1489 float y1 = (cur_quad->corners[i]->pt.y + cur_quad->corners[(i+1)%4]->pt.y)/2;
1490 float x2 = (cur_quad->corners[(i+2)%4]->pt.x + cur_quad->corners[(i+3)%4]->pt.x)/2;
1491 float y2 = (cur_quad->corners[(i+2)%4]->pt.y + cur_quad->corners[(i+3)%4]->pt.y)/2;
1493 float x3 = (cur_quad->corners[i]->pt.x + cur_quad->corners[(i+3)%4]->pt.x)/2;
1494 float y3 = (cur_quad->corners[i]->pt.y + cur_quad->corners[(i+3)%4]->pt.y)/2;
1495 float x4 = (cur_quad->corners[(i+1)%4]->pt.x + cur_quad->corners[(i+2)%4]->pt.x)/2;
1496 float y4 = (cur_quad->corners[(i+1)%4]->pt.y + cur_quad->corners[(i+2)%4]->pt.y)/2;
1506 float c11 = cur_quad->corners[i]->pt.x - x2;
1507 float d11 = cur_quad->corners[i]->pt.y - y2;
1509 float c12 = quads[k]->corners[j]->pt.x - x2;
1510 float d12 = quads[k]->corners[j]->pt.y - y2;
1511 float sign11 =
a1*d11 - c11*
b1;
1512 float sign12 =
a1*d12 - c12*
b1;
1517 float c21 = cur_quad->corners[i]->pt.x - x4;
1518 float d21 = cur_quad->corners[i]->pt.y - y4;
1520 float c22 = quads[k]->corners[j]->pt.x - x4;
1521 float d22 = quads[k]->corners[j]->pt.y - y4;
1522 float sign21 =
a2*d21 - c21*
b2;
1523 float sign22 =
a2*d22 - c22*
b2;
1531 float c13 = quads[k]->corners[(j+2)%4]->pt.x - x2;
1532 float d13 = quads[k]->corners[(j+2)%4]->pt.y - y2;
1533 float c23 = quads[k]->corners[(j+2)%4]->pt.x - x4;
1534 float d23 = quads[k]->corners[(j+2)%4]->pt.y - y4;
1535 float sign13 =
a1*d13 - c13*
b1;
1536 float sign23 =
a2*d23 - c23*
b2;
1541 float u1 = (quads[k]->corners[j]->pt.x + quads[k]->corners[(j+1)%4]->pt.x)/2;
1542 float v1 = (quads[k]->corners[j]->pt.y + quads[k]->corners[(j+1)%4]->pt.y)/2;
1543 float u2 = (quads[k]->corners[(j+2)%4]->pt.x + quads[k]->corners[(j+3)%4]->pt.x)/2;
1544 float v2 = (quads[k]->corners[(j+2)%4]->pt.y + quads[k]->corners[(j+3)%4]->pt.y)/2;
1546 float u3 = (quads[k]->corners[j]->pt.x + quads[k]->corners[(j+3)%4]->pt.x)/2;
1547 float v3 = (quads[k]->corners[j]->pt.y + quads[k]->corners[(j+3)%4]->pt.y)/2;
1548 float u4 = (quads[k]->corners[(j+1)%4]->pt.x + quads[k]->corners[(j+2)%4]->pt.x)/2;
1549 float v4 = (quads[k]->corners[(j+1)%4]->pt.y + quads[k]->corners[(j+2)%4]->pt.y)/2;
1559 float c31 = cur_quad->corners[i]->pt.x -
u2;
1560 float d31 = cur_quad->corners[i]->pt.y -
v2;
1562 float c32 = quads[k]->corners[j]->pt.x -
u2;
1563 float d32 = quads[k]->corners[j]->pt.y -
v2;
1564 float sign31 =
a3*d31-c31*
b3;
1565 float sign32 =
a3*d32-c32*
b3;
1570 float c41 = cur_quad->corners[i]->pt.x - u4;
1571 float d41 = cur_quad->corners[i]->pt.y - v4;
1573 float c42 = quads[k]->corners[j]->pt.x - u4;
1574 float d42 = quads[k]->corners[j]->pt.y - v4;
1575 float sign41 = a4*d41-c41*b4;
1576 float sign42 = a4*d42-c42*b4;
1584 float c33 = cur_quad->corners[(i+2)%4]->pt.x -
u2;
1585 float d33 = cur_quad->corners[(i+2)%4]->pt.y -
v2;
1586 float c43 = cur_quad->corners[(i+2)%4]->pt.x - u4;
1587 float d43 = cur_quad->corners[(i+2)%4]->pt.y - v4;
1588 float sign33 =
a3*d33-c33*
b3;
1589 float sign43 = a4*d43-c43*b4;
1593 if ( ((sign11 < 0 && sign12 < 0) || (sign11 > 0 && sign12 > 0)) &&
1594 ((sign21 < 0 && sign22 < 0) || (sign21 > 0 && sign22 > 0)) &&
1595 ((sign31 < 0 && sign32 < 0) || (sign31 > 0 && sign32 > 0)) &&
1596 ((sign41 < 0 && sign42 < 0) || (sign41 > 0 && sign42 > 0)) &&
1597 ((sign11 < 0 && sign13 < 0) || (sign11 > 0 && sign13 > 0)) &&
1598 ((sign21 < 0 && sign23 < 0) || (sign21 > 0 && sign23 > 0)) &&
1599 ((sign31 < 0 && sign33 < 0) || (sign31 > 0 && sign33 > 0)) &&
1600 ((sign41 < 0 && sign43 < 0) || (sign41 > 0 && sign43 > 0)) )
1603 closest_corner_idx = j;
1604 closest_quad = quads[k];
1612 if( closest_corner_idx >= 0 && min_dist < FLT_MAX )
1614 CvCBCornerPtr &closest_corner = closest_quad->corners[closest_corner_idx];
1620 for(
size_t j = 0; !skip && j < 4; j++ )
1621 skip = closest_quad->neighbors[j] == cur_quad;
1627 closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f;
1628 closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f;
1631 cur_quad->neighbors[i] = closest_quad;
1632 cur_quad->corners[i] = closest_corner;
1634 closest_quad->count++;
1635 closest_quad->neighbors[closest_corner_idx] = cur_quad;
1636 closest_quad->corners[closest_corner_idx] = closest_corner;
1653 std::vector<CvCBQuadPtr> &new_quads,
int new_dilation,
1654 std::vector<CvCBQuadPtr> &old_quads,
int old_dilation )
1661 const float thresh_dilation = (float)(2*new_dilation+3)*(2*old_dilation+3)*2;
1667 for(
size_t idx = 0; idx < old_quads.size(); idx++ )
1673 for(
int i = 0; i < 4; i++ )
1676 float min_dist = FLT_MAX;
1677 int closest_corner_idx = -1;
1683 if( cur_quad->corners[i]->needsNeighbor ==
false )
1686 pt = cur_quad->corners[i]->pt;
1690 for(
size_t k = 0; k < new_quads.size(); k++ )
1693 if( new_quads[k]->labeled ==
true)
1696 for(
int j = 0; j < 4; j++ )
1701 dx = pt.x - new_quads[k]->corners[j]->pt.x;
1702 dy = pt.y - new_quads[k]->corners[j]->pt.y;
1703 dist = dx * dx + dy * dy;
1705 if( (dist < min_dist) &&
1706 dist <= (cur_quad->edge_len + thresh_dilation) &&
1707 dist <= (new_quads[k]->edge_len + thresh_dilation) )
1712 float x1 = (cur_quad->corners[i]->pt.x + cur_quad->corners[(i+1)%4]->pt.x)/2;
1713 float y1 = (cur_quad->corners[i]->pt.y + cur_quad->corners[(i+1)%4]->pt.y)/2;
1714 float x2 = (cur_quad->corners[(i+2)%4]->pt.x + cur_quad->corners[(i+3)%4]->pt.x)/2;
1715 float y2 = (cur_quad->corners[(i+2)%4]->pt.y + cur_quad->corners[(i+3)%4]->pt.y)/2;
1717 float x3 = (cur_quad->corners[i]->pt.x + cur_quad->corners[(i+3)%4]->pt.x)/2;
1718 float y3 = (cur_quad->corners[i]->pt.y + cur_quad->corners[(i+3)%4]->pt.y)/2;
1719 float x4 = (cur_quad->corners[(i+1)%4]->pt.x + cur_quad->corners[(i+2)%4]->pt.x)/2;
1720 float y4 = (cur_quad->corners[(i+1)%4]->pt.y + cur_quad->corners[(i+2)%4]->pt.y)/2;
1730 float c11 = cur_quad->corners[i]->pt.x - x2;
1731 float d11 = cur_quad->corners[i]->pt.y - y2;
1733 float c12 = new_quads[k]->corners[j]->pt.x - x2;
1734 float d12 = new_quads[k]->corners[j]->pt.y - y2;
1735 float sign11 =
a1*d11 - c11*
b1;
1736 float sign12 =
a1*d12 - c12*
b1;
1741 float c21 = cur_quad->corners[i]->pt.x - x4;
1742 float d21 = cur_quad->corners[i]->pt.y - y4;
1744 float c22 = new_quads[k]->corners[j]->pt.x - x4;
1745 float d22 = new_quads[k]->corners[j]->pt.y - y4;
1746 float sign21 =
a2*d21 - c21*
b2;
1747 float sign22 =
a2*d22 - c22*
b2;
1754 float c13 = new_quads[k]->corners[(j+2)%4]->pt.x - x2;
1755 float d13 = new_quads[k]->corners[(j+2)%4]->pt.y - y2;
1756 float c23 = new_quads[k]->corners[(j+2)%4]->pt.x - x4;
1757 float d23 = new_quads[k]->corners[(j+2)%4]->pt.y - y4;
1758 float sign13 =
a1*d13 - c13*
b1;
1759 float sign23 =
a2*d23 - c23*
b2;
1765 float u1 = (new_quads[k]->corners[j]->pt.x + new_quads[k]->corners[(j+1)%4]->pt.x)/2;
1766 float v1 = (new_quads[k]->corners[j]->pt.y + new_quads[k]->corners[(j+1)%4]->pt.y)/2;
1767 float u2 = (new_quads[k]->corners[(j+2)%4]->pt.x + new_quads[k]->corners[(j+3)%4]->pt.x)/2;
1768 float v2 = (new_quads[k]->corners[(j+2)%4]->pt.y + new_quads[k]->corners[(j+3)%4]->pt.y)/2;
1770 float u3 = (new_quads[k]->corners[j]->pt.x + new_quads[k]->corners[(j+3)%4]->pt.x)/2;
1771 float v3 = (new_quads[k]->corners[j]->pt.y + new_quads[k]->corners[(j+3)%4]->pt.y)/2;
1772 float u4 = (new_quads[k]->corners[(j+1)%4]->pt.x + new_quads[k]->corners[(j+2)%4]->pt.x)/2;
1773 float v4 = (new_quads[k]->corners[(j+1)%4]->pt.y + new_quads[k]->corners[(j+2)%4]->pt.y)/2;
1783 float c31 = cur_quad->corners[i]->pt.x -
u2;
1784 float d31 = cur_quad->corners[i]->pt.y -
v2;
1786 float c32 = new_quads[k]->corners[j]->pt.x -
u2;
1787 float d32 = new_quads[k]->corners[j]->pt.y -
v2;
1788 float sign31 =
a3*d31-c31*
b3;
1789 float sign32 =
a3*d32-c32*
b3;
1794 float c41 = cur_quad->corners[i]->pt.x - u4;
1795 float d41 = cur_quad->corners[i]->pt.y - v4;
1797 float c42 = new_quads[k]->corners[j]->pt.x - u4;
1798 float d42 = new_quads[k]->corners[j]->pt.y - v4;
1799 float sign41 = a4*d41-c41*b4;
1800 float sign42 = a4*d42-c42*b4;
1807 float c33 = cur_quad->corners[(i+2)%4]->pt.x -
u2;
1808 float d33 = cur_quad->corners[(i+2)%4]->pt.y -
v2;
1809 float c43 = cur_quad->corners[(i+2)%4]->pt.x - u4;
1810 float d43 = cur_quad->corners[(i+2)%4]->pt.y - v4;
1811 float sign33 =
a3*d33-c33*
b3;
1812 float sign43 = a4*d43-c43*b4;
1821 float x5 = cur_quad->corners[i]->pt.x;
1822 float y5 = cur_quad->corners[i]->pt.y;
1823 float x6 = cur_quad->corners[(i+1)%4]->pt.x;
1824 float y6 = cur_quad->corners[(i+1)%4]->pt.y;
1828 float x8 = cur_quad->corners[(i+3)%4]->pt.x;
1829 float y8 = cur_quad->corners[(i+3)%4]->pt.y;
1839 float c51 = cur_quad->corners[(i+2)%4]->pt.x - x5;
1840 float d51 = cur_quad->corners[(i+2)%4]->pt.y - y5;
1842 float c52 = new_quads[k]->corners[j]->pt.x - x5;
1843 float d52 = new_quads[k]->corners[j]->pt.y - y5;
1844 float sign51 = a5*d51 - c51*b5;
1845 float sign52 = a5*d52 - c52*b5;
1850 float c61 = cur_quad->corners[(i+2)%4]->pt.x - x7;
1851 float d61 = cur_quad->corners[(i+2)%4]->pt.y - y7;
1853 float c62 = new_quads[k]->corners[j]->pt.x - x7;
1854 float d62 = new_quads[k]->corners[j]->pt.y - y7;
1855 float sign61 = a6*d61 - c61*b6;
1856 float sign62 = a6*d62 - c62*b6;
1862 float u5 = new_quads[k]->corners[j]->pt.x;
1863 float v5 = new_quads[k]->corners[j]->pt.y;
1864 float u6 = new_quads[k]->corners[(j+1)%4]->pt.x;
1865 float v6 = new_quads[k]->corners[(j+1)%4]->pt.y;
1869 float u8 = new_quads[k]->corners[(j+3)%4]->pt.x;
1870 float v8 = new_quads[k]->corners[(j+3)%4]->pt.y;
1880 float c71 = cur_quad->corners[i]->pt.x - u5;
1881 float d71 = cur_quad->corners[i]->pt.y - v5;
1883 float c72 = new_quads[k]->corners[(j+2)%4]->pt.x - u5;
1884 float d72 = new_quads[k]->corners[(j+2)%4]->pt.y - v5;
1885 float sign71 = a7*d71-c71*b7;
1886 float sign72 = a7*d72-c72*b7;
1891 float c81 = cur_quad->corners[i]->pt.x - u7;
1892 float d81 = cur_quad->corners[i]->pt.y - v7;
1894 float c82 = new_quads[k]->corners[(j+2)%4]->pt.x - u7;
1895 float d82 = new_quads[k]->corners[(j+2)%4]->pt.y - v7;
1896 float sign81 = a8*d81-c81*b8;
1897 float sign82 = a8*d82-c82*b8;
1904 if ( ((sign11 < 0 && sign12 < 0) || (sign11 > 0 && sign12 > 0)) &&
1905 ((sign21 < 0 && sign22 < 0) || (sign21 > 0 && sign22 > 0)) &&
1906 ((sign31 < 0 && sign32 < 0) || (sign31 > 0 && sign32 > 0)) &&
1907 ((sign41 < 0 && sign42 < 0) || (sign41 > 0 && sign42 > 0)) &&
1908 ((sign11 < 0 && sign13 < 0) || (sign11 > 0 && sign13 > 0)) &&
1909 ((sign21 < 0 && sign23 < 0) || (sign21 > 0 && sign23 > 0)) &&
1910 ((sign31 < 0 && sign33 < 0) || (sign31 > 0 && sign33 > 0)) &&
1911 ((sign41 < 0 && sign43 < 0) || (sign41 > 0 && sign43 > 0)) &&
1912 ((sign51 < 0 && sign52 > 0) || (sign51 > 0 && sign52 < 0)) &&
1913 ((sign61 < 0 && sign62 > 0) || (sign61 > 0 && sign62 < 0)) &&
1914 ((sign71 < 0 && sign72 > 0) || (sign71 > 0 && sign72 < 0)) &&
1915 ((sign81 < 0 && sign82 > 0) || (sign81 > 0 && sign82 < 0)) )
1917 closest_corner_idx = j;
1918 closest_quad = new_quads[k];
1926 if( closest_corner_idx >= 0 && min_dist < FLT_MAX )
1928 CvCBCornerPtr &closest_corner = closest_quad->corners[closest_corner_idx];
1929 closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f;
1930 closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f;
1936 cur_quad->corners[i]->pt.x = closest_corner->pt.x;
1937 cur_quad->corners[i]->pt.y = closest_corner->pt.y;
1938 cur_quad->neighbors[i] = closest_quad;
1939 closest_quad->corners[closest_corner_idx]->pt.x = closest_corner->pt.x;
1940 closest_quad->corners[closest_corner_idx]->pt.y = closest_corner->pt.y;
1945 closest_quad->labeled =
true;
1952 newQuad->edge_len = closest_quad->edge_len;
1953 newQuad->group_idx = cur_quad->group_idx;
1954 newQuad->labeled =
false;
1958 newQuad->neighbors[closest_corner_idx] = cur_quad;
1959 newQuad->neighbors[(closest_corner_idx+1)%4].
reset();
1960 newQuad->neighbors[(closest_corner_idx+2)%4].
reset();
1961 newQuad->neighbors[(closest_corner_idx+3)%4].
reset();
1963 for (
int j = 0; j < 4; j++)
1966 newQuad->corners[j]->pt.x = closest_quad->corners[j]->pt.x;
1967 newQuad->corners[j]->pt.y = closest_quad->corners[j]->pt.y;
1970 old_quads.push_back(newQuad);
1971 cur_quad->neighbors[i] = newQuad;
1997 #if CV_MAJOR_VERSION==1 1998 CvMemStorage* temp_storage = cvCreateMemStorage(0);
2000 cv::MemStorage temp_storage = cv::MemStorage(cvCreateMemStorage(0));
2003 CvSeq *src_contour = 0;
2006 CvContourScanner scanner;
2010 const int min_size = cvRound(
image.getWidth() *
image.getHeight() * .03 * 0.01 * 0.92 * 0.1);
2013 root = cvCreateSeq( 0,
sizeof(CvSeq),
sizeof(CvSeq*), temp_storage );
2016 scanner = cvStartFindContours( const_cast<IplImage*>(
image.getAs<IplImage>()), temp_storage,
sizeof(
CvContourEx), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
2019 while( (src_contour = cvFindNextContour( scanner )) != 0 )
2021 CvSeq *dst_contour = 0;
2022 CvRect rect = ((CvContour*)src_contour)->rect;
2031 if( CV_IS_SEQ_HOLE(src_contour) && rect.width*rect.height >= min_size )
2033 int min_approx_level = 2, max_approx_level;
2034 if (firstRun ==
true)
2035 max_approx_level = 3;
2039 for( approx_level = min_approx_level; approx_level <= max_approx_level; approx_level++ )
2041 dst_contour = cvApproxPoly( src_contour,
sizeof(CvContour), temp_storage,
2042 CV_POLY_APPROX_DP, (
float)approx_level );
2047 dst_contour = cvApproxPoly( dst_contour,
sizeof(CvContour), temp_storage,
2048 CV_POLY_APPROX_DP, (
float)approx_level );
2050 if( dst_contour->total == 4 )
2056 if(dst_contour->total == 4 && cvCheckContourConvexity(dst_contour) )
2063 for(
int i = 0; i < 4; i++ )
2064 pt[i] = *(CvPoint*)cvGetSeqElem(dst_contour, i);
2091 dst_contour->v_prev = (CvSeq*)parent;
2092 cvSeqPush( root, &dst_contour );
2100 cvEndFindContours( &scanner );
2105 for (
int q=0;
q<root->total;
q++)
2108 out_corners.clear();
2109 for (
int q=0;
q< 4 * root->total;
q++)
2113 for(
int idx = 0; idx < root->total; idx++ )
2116 src_contour = *(CvSeq**)cvGetSeqElem( root, idx );
2117 if( (flags & cv::CALIB_CB_FILTER_QUADS) && src_contour->v_prev != (CvSeq*)board )
2123 assert( src_contour->total == 4 );
2124 for(
int i = 0; i < 4; i++ )
2126 CvPoint2D32f pt = cvPointTo32f(*(CvPoint*)cvGetSeqElem(src_contour, i));
2131 q->corners[i] = corner;
2133 q->edge_len = FLT_MAX;
2134 for(
int i = 0; i < 4; i++ )
2136 float dx =
q->corners[i]->pt.x -
q->corners[(i+1)&3]->pt.x;
2137 float dy =
q->corners[i]->pt.y -
q->corners[(i+1)&3]->pt.y;
2138 float d = dx*dx + dy*dy;
2139 if(
q->edge_len > d )
2146 if( cvGetErrStatus() < 0 )
2150 out_corners.clear();
2156 #if CV_MAJOR_VERSION==1 2157 cvReleaseMemStorage(&temp_storage);
2165 int myQuads2Points(
const std::vector<CvCBQuadPtr> &output_quads,
const CvSize &pattern_size, std::vector<CvPoint2D32f> &out_corners)
2168 out_corners.clear();
2170 bool flagRow =
false;
2171 bool flagColumn =
false;
2172 int maxPattern_sizeRow = -1;
2173 int maxPattern_sizeColumn = -1;
2179 int min_column = 127;
2180 int max_column = -127;
2182 for(
size_t i = 0; i < output_quads.size(); i++ )
2186 for(
int j = 0; j < 4; j++ )
2188 if( (
q->corners[j])->row > max_row)
2189 max_row = (
q->corners[j])->row;
2190 if( (
q->corners[j])->row < min_row)
2191 min_row = (
q->corners[j])->row;
2192 if( (
q->corners[j])->column > max_column)
2193 max_column = (
q->corners[j])->column;
2194 if( (
q->corners[j])->column < min_column)
2195 min_column = (
q->corners[j])->column;
2203 for(
size_t i = 0; i < output_quads.size(); i++ )
2207 for(
int j = 0; j < 4; j++ )
2209 if( (
q->corners[j])->column == max_column && (
q->corners[j])->
row != min_row && (
q->corners[j])->row != max_row )
2211 if( (
q->corners[j]->needsNeighbor) ==
false)
2218 if( (
q->corners[j])->row == max_row && (
q->corners[j])->
column != min_column && (
q->corners[j])->column != max_column )
2220 if( (
q->corners[j]->needsNeighbor) ==
false)
2230 if( flagColumn ==
true)
2232 if( max_column - min_column == pattern_size.width + 1)
2234 maxPattern_sizeColumn = pattern_size.width;
2235 maxPattern_sizeRow = pattern_size.height;
2239 maxPattern_sizeColumn = pattern_size.height;
2240 maxPattern_sizeRow = pattern_size.width;
2243 else if( flagRow ==
true)
2245 if( max_row - min_row == pattern_size.width + 1)
2247 maxPattern_sizeRow = pattern_size.width;
2248 maxPattern_sizeColumn = pattern_size.height;
2252 maxPattern_sizeRow = pattern_size.height;
2253 maxPattern_sizeColumn = pattern_size.width;
2261 maxPattern_sizeColumn = max(pattern_size.width, pattern_size.height);
2262 maxPattern_sizeRow = max(pattern_size.width, pattern_size.height);
2266 if (maxPattern_sizeRow * maxPattern_sizeColumn != pattern_size.width * pattern_size.height )
2269 bool do_swap_col_row = maxPattern_sizeRow != pattern_size.height;
2271 if (do_swap_col_row)
2273 std::swap(min_row,min_column);
2274 std::swap(maxPattern_sizeRow, maxPattern_sizeColumn);
2279 for(
int i = min_row + 1; i < maxPattern_sizeRow + min_row + 1; i++)
2281 for(
int j = min_column + 1; j < maxPattern_sizeColumn + min_column + 1; j++)
2286 for(
size_t k = 0; k < output_quads.size(); k++ )
2288 for(
int l = 0; l < 4; l++)
2290 int r = output_quads[k]->corners[l]->row;
2291 int c = output_quads[k]->corners[l]->column;
2292 if (do_swap_col_row)
2295 if(
r == i &&
c == j)
2302 out_corners.push_back( output_quads[k]->corners[l]->pt );
2318 if (iter == 1 || iter == 2)
2329 return (out_corners.size() == size_t( pattern_size.width * pattern_size.height) ) ? 1:0;
2335 std::map<CvCBQuad*,size_t> pointer2index;
2336 for (
size_t i=0;i<quads.size();i++)
2337 pointer2index[quads[i].
get()] = i;
2339 vector<CArray<size_t,4> > neig_indices(quads.size());
2340 for (
size_t i=0;i<quads.size();i++)
2341 for (
size_t j=0;j<4;j++)
2342 neig_indices[i][j] = pointer2index[ quads[i]->neighbors[j].
get() ];
2344 std::vector<CvCBQuadPtr> new_quads = quads;
2347 new_quads.begin(), new_quads.end(),
2350 for (
size_t i=0;i<new_quads.size();i++)
2351 for (
size_t j=0;j<4;j++)
2352 new_quads[i]->neighbors[j] = new_quads[ neig_indices[i][j] ];
2360 #endif // MRPT_HAS_OPENCV int cvFindChessboardCorners3(const mrpt::utils::CImage &img_, CvSize pattern_size, std::vector< CvPoint2D32f > &out_corners)
GLuint GLuint GLsizei count
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
bool do_special_dilation(mrpt::utils::CImage &thresh_img, const int dilations, IplConvKernel *kernel_cross, IplConvKernel *kernel_rect, IplConvKernel *kernel_diag1, IplConvKernel *kernel_diag2, IplConvKernel *kernel_horz, IplConvKernel *kernel_vert)
A class for storing images as grayscale or RGB bitmaps.
void mrFindQuadNeighbors2(std::vector< CvCBQuadPtr > &quads, int dilation)
GLenum GLenum GLenum GLenum GLenum scale
GLdouble GLdouble GLdouble GLdouble q
void icvCleanFoundConnectedQuads(std::vector< CvCBQuadPtr > &quad_group, const CvSize &pattern_size)
GLenum GLsizei GLenum GLenum const GLvoid * image
int myQuads2Points(const std::vector< CvCBQuadPtr > &output_quads, const CvSize &pattern_size, std::vector< CvPoint2D32f > &out_corners)
void icvFindConnectedQuads(std::vector< CvCBQuadPtr > &quad, std::vector< CvCBQuadPtr > &out_group, const int group_idx, const int dilation)
const T * getAs() const
Returns a pointer to a const T* containing the image - the idea is to call like "img.getAs<IplImage>()" so we can avoid here including OpenCV's headers.
void mrLabelQuadGroup(std::vector< CvCBQuadPtr > &quad_group, const CvSize &pattern_size, bool firstRun)
int mrAugmentBestRun(std::vector< CvCBQuadPtr > &new_quads, int new_dilation, std::vector< CvCBQuadPtr > &old_quads, int old_dilation)
This base provides a set of functions for maths stuff.
double median(const std::vector< double > &vec)
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
double triangleArea(double x0, double y0, double x1, double y1, double x2, double y2)
GLfloat GLfloat GLfloat GLfloat v3
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
#define MAX_CONTOUR_APPROX
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
GLdouble GLdouble GLdouble r
GLenum GLenum GLvoid * row
void quadListMakeUnique(std::vector< CvCBQuadPtr > &quads)
std::shared_ptr< CvCBCorner > CvCBCornerPtr
int BASE_IMPEXP sprintf(char *buf, size_t bufSize, const char *format,...) MRPT_NO_THROWS MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
GLfloat GLfloat GLfloat v2
int icvGenerateQuads(vector< CvCBQuadPtr > &out_quads, vector< CvCBCornerPtr > &out_corners, const mrpt::utils::CImage &image, int flags, int dilation, bool firstRun)
GLenum GLenum GLvoid GLvoid * column
GLubyte GLubyte GLubyte a
std::shared_ptr< CvCBQuad > CvCBQuadPtr