<h5 dir="auto">System information (version)</h5>
<ul dir="auto">
<li>OpenCV =&gt; 4.0</li>
<li>Operating System / Platform =&gt; ARM 64</li>
<li>Compiler =&gt; GCC</li>
</ul>
<h5 dir="auto">Detailed description</h5>
<p dir="auto">I passed the input image with lena.jpg, got the following error.<br>
error: (-215:Assertion failed) !fixedSize() || ((Mat*)obj)-&gt;size.operator()() == _sz in function 'create'</p>
<h5 dir="auto">Steps to reproduce</h5>
<p dir="auto">compile the sample/cpp/tutorial_code/decolorization/decolor.cpp<br>
run the binary.</p>
<p dir="auto">Inside the function, outer quads might be added through function icvAddOuterQuad. However, icvAddOuterQuad doesn't check the bound of the allocated quads buffer when adding a new quad. The same bug has existed as early as opencv 2.4, as well as in 3.0.</p>
<p dir="auto">I verified this bug with the following code on Windows 7 64bit:</p>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="               // read image
        char *path = &quot;ImageCauseCrash.png&quot;;  // the attached image
        cv::Mat image = cv::imread(path, CV_LOAD_IMAGE_GRAYSCALE);
        assert(!image.empty());

        // find chessboard corners
        int nRows = 9;
        int nCols = 7;
        int nCorners = (nRows - 1) * (nCols - 1);

        std::vector&lt;cv::Point2f&gt; vCorners(nCorners);

        bool bFound = cv::findChessboardCorners(cv::Mat(image), cv::Size(nRows - 1, nCols - 1), vCorners, CV_CALIB_CB_ADAPTIVE_THRESH);"><pre class="notranslate">               <span class="pl-c"><span class="pl-c">//</span> read image</span>
        <span class="pl-k">char</span> *path = <span class="pl-s"><span class="pl-pds">"</span>ImageCauseCrash.png<span class="pl-pds">"</span></span>;  <span class="pl-c"><span class="pl-c">//</span> the attached image</span>
        cv::Mat image = cv::imread(path, CV_LOAD_IMAGE_GRAYSCALE);
        <span class="pl-en">assert</span>(!image.empty());

        <span class="pl-c"><span class="pl-c">//</span> find chessboard corners</span>
        <span class="pl-k">int</span> nRows = <span class="pl-c1">9</span>;
        <span class="pl-k">int</span> nCols = <span class="pl-c1">7</span>;
        <span class="pl-k">int</span> nCorners = (nRows - <span class="pl-c1">1</span>) * (nCols - <span class="pl-c1">1</span>);

        std::vector&lt;cv::Point2f&gt; <span class="pl-en">vCorners</span>(nCorners);

        <span class="pl-k">bool</span> bFound = cv::findChessboardCorners(cv::Mat(image), cv::<span class="pl-c1">Size</span>(nRows - <span class="pl-c1">1</span>, nCols - <span class="pl-c1">1</span>), vCorners, CV_CALIB_CB_ADAPTIVE_THRESH);</pre></div>
<p dir="auto">== Image used in the verification:<br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://cloud.githubusercontent.com/assets/13682989/9120371/c3fdbae4-3c30-11e5-980e-469207a7237b.png"><img src="https://cloud.githubusercontent.com/assets/13682989/9120371/c3fdbae4-3c30-11e5-980e-469207a7237b.png" alt="imagecausecrash" style="max-width: 100%;"></a></p>
<p dir="auto">== Proposed fix, the following is copy calibinit.cpp with my fix. Search for max_quad_buf_size</p>
<div class="highlight highlight-source-c++ notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="//M*//////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors &quot;as is&quot; and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

/************************************************************************************\
    This is improved variant of chessboard corner detection algorithm that
    uses a graph of connected quads. It is based on the code contributed
    by Vladimir Vezhnevets and Philip Gruebele.
    Here is the copyright notice from the original Vladimir's code:
    ===============================================================

    The algorithms developed and implemented by Vezhnevets Vldimir
    aka Dead Moroz (vvp@graphics.cs.msu.ru)
    See http://graphics.cs.msu.su/en/research/calibration/opencv.html
    for detailed information.

    Reliability additions and modifications made by Philip Gruebele.
    &lt;a href=&quot;mailto:pgruebele@cox.net&quot;&gt;pgruebele@cox.net&lt;/a&gt;

    Some further improvements for detection of partially ocluded boards at non-ideal
    lighting conditions have been made by Alex Bovyrin and Kurt Kolonige

\************************************************************************************/

#include &quot;precomp.hpp&quot;
#include &quot;circlesgrid.hpp&quot;
#include &lt;stdarg.h&gt;

//#define ENABLE_TRIM_COL_ROW

//#define DEBUG_CHESSBOARD
#ifdef DEBUG_CHESSBOARD
#  include &quot;opencv2/opencv_modules.hpp&quot;
#  ifdef HAVE_OPENCV_HIGHGUI
#    include &quot;opencv2/highgui/highgui.hpp&quot;
#  else
#    undef DEBUG_CHESSBOARD
#  endif
#endif
#ifdef DEBUG_CHESSBOARD
static int PRINTF( const char* fmt, ... )
{
    va_list args;
    va_start(args, fmt);
    return vprintf(fmt, args);
}
#else
static int PRINTF( const char*, ... )
{
    return 0;
}
#endif


//=====================================================================================
// Implementation for the enhanced calibration object detection
//=====================================================================================

#define MAX_CONTOUR_APPROX  7

struct CvContourEx
{
    CV_CONTOUR_FIELDS()
    int counter;
};

//=====================================================================================

/// Corner info structure
/** This structure stores information about the chessboard corner.*/
struct CvCBCorner
{
    CvPoint2D32f pt; // Coordinates of the corner
    int row;         // Board row index
    int count;       // Number of neighbor corners
    struct CvCBCorner* neighbors[4]; // Neighbor corners

    float meanDist(int *_n) const
    {
        float sum = 0;
        int n = 0;
        for( int i = 0; i &lt; 4; i++ )
        {
            if( neighbors[i] )
            {
                float dx = neighbors[i]-&gt;pt.x - pt.x;
                float dy = neighbors[i]-&gt;pt.y - pt.y;
                sum += sqrt(dx*dx + dy*dy);
                n++;
            }
        }
        if(_n)
            *_n = n;
        return sum/MAX(n,1);
    }
};

//=====================================================================================
/// Quadrangle contour info structure
/** This structure stores information about the chessboard quadrange.*/
struct CvCBQuad
{
    int count;      // Number of quad neighbors
    int group_idx;  // quad group ID
    int row, col;   // row and column of this quad
    bool ordered;   // true if corners/neighbors are ordered counter-clockwise
    float edge_len; // quad edge len, in pix^2
    // neighbors and corners are synced, i.e., neighbor 0 shares corner 0
    CvCBCorner *corners[4]; // Coordinates of quad corners
    struct CvCBQuad *neighbors[4]; // Pointers of quad neighbors
};

//=====================================================================================

//static CvMat* debug_img = 0;

static int icvGenerateQuads( CvCBQuad **quads, CvCBCorner **corners,
                             CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size);

/*static int
icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners,
    CvMemStorage *storage, CvMat *image, CvMat *thresh_img, int dilation, int flags );*/

static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count );

static int icvFindConnectedQuads( CvCBQuad *quads, int quad_count,
                                  CvCBQuad **quad_group, int group_idx,
                                  CvMemStorage* storage );

static int icvCheckQuadGroup( CvCBQuad **quad_group, int count,
                              CvCBCorner **out_corners, CvSize pattern_size );

static int icvCleanFoundConnectedQuads( int quad_count,
                CvCBQuad **quads, CvSize pattern_size );

static int icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads,
           int *all_count, CvCBQuad **all_quads, CvCBCorner **corners,
           CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage );

static void icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common);

#ifdef ENABLE_TRIM_COL_ROW
static int icvTrimCol(CvCBQuad **quads, int count, int col, int dir);

static int icvTrimRow(CvCBQuad **quads, int count, int row, int dir);
#endif

static int icvAddOuterQuad(CvCBQuad *quad, CvCBQuad **quads, int quad_count,
                    CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size);

static void icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0);

static int icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size );

#if 0
static void
icvCalcAffineTranf2D32f(CvPoint2D32f* pts1, CvPoint2D32f* pts2, int count, CvMat* affine_trans)
{
    int i, j;
    int real_count = 0;
    for( j = 0; j &lt; count; j++ )
    {
        if( pts1[j].x &gt;= 0 ) real_count++;
    }
    if(real_count &lt; 3) return;
    cv::Ptr&lt;CvMat&gt; xy = cvCreateMat( 2*real_count, 6, CV_32FC1 );
    cv::Ptr&lt;CvMat&gt; uv = cvCreateMat( 2*real_count, 1, CV_32FC1 );
    //estimate affine transfromation
    for( i = 0, j = 0; j &lt; count; j++ )
    {
        if( pts1[j].x &gt;= 0 )
        {
            CV_MAT_ELEM( *xy, float, i*2+1, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 0 ) = pts2[j].x;
            CV_MAT_ELEM( *xy, float, i*2+1, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 1 ) = pts2[j].y;
            CV_MAT_ELEM( *xy, float, i*2, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 5 ) = \
                CV_MAT_ELEM( *xy, float, i*2+1, 0 ) = CV_MAT_ELEM( *xy, float, i*2+1, 1 ) = CV_MAT_ELEM( *xy, float, i*2+1, 4 ) = 0;
            CV_MAT_ELEM( *xy, float, i*2, 4 ) = CV_MAT_ELEM( *xy, float, i*2+1, 5 ) = 1;
            CV_MAT_ELEM( *uv, float, i*2, 0 ) = pts1[j].x;
            CV_MAT_ELEM( *uv, float, i*2+1, 0 ) = pts1[j].y;
            i++;
        }
    }

    cvSolve( xy, uv, affine_trans, CV_SVD );
}
#endif

CV_IMPL
int cvFindChessboardCorners( const void* arr, CvSize pattern_size,
                             CvPoint2D32f* out_corners, int* out_corner_count,
                             int flags )
{
    int found = 0;
    CvCBQuad *quads = 0, **quad_group = 0;
    CvCBCorner *corners = 0, **corner_group = 0;

    try
    {
    int k = 0;
    const int min_dilations = 0;
    const int max_dilations = 7;
    cv::Ptr&lt;CvMat&gt; norm_img, thresh_img;
#ifdef DEBUG_CHESSBOARD
    cv::Ptr&lt;IplImage&gt; dbg_img;
    cv::Ptr&lt;IplImage&gt; dbg1_img;
    cv::Ptr&lt;IplImage&gt; dbg2_img;
#endif
    cv::Ptr&lt;CvMemStorage&gt; storage;

    CvMat stub, *img = (CvMat*)arr;

    int expected_corners_num = (pattern_size.width/2+1)*(pattern_size.height/2+1);

    int prev_sqr_size = 0;

    if( out_corner_count )
        *out_corner_count = 0;

    IplImage _img;
    int check_chessboard_result;
    int quad_count = 0, group_idx = 0, dilations = 0;

    img = cvGetMat( img, &amp;stub );
    //debug_img = img;

    if( CV_MAT_DEPTH( img-&gt;type ) != CV_8U || CV_MAT_CN( img-&gt;type ) == 2 )
        CV_Error( CV_StsUnsupportedFormat, &quot;Only 8-bit grayscale or color images are supported&quot; );

    if( pattern_size.width &lt;= 2 || pattern_size.height &lt;= 2 )
        CV_Error( CV_StsOutOfRange, &quot;Both width and height of the pattern should have bigger than 2&quot; );

    if( !out_corners )
        CV_Error( CV_StsNullPtr, &quot;Null pointer to corners&quot; );

    storage = cvCreateMemStorage(0);
    thresh_img = cvCreateMat( img-&gt;rows, img-&gt;cols, CV_8UC1 );

#ifdef DEBUG_CHESSBOARD
    dbg_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
    dbg1_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
    dbg2_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
#endif

    if( CV_MAT_CN(img-&gt;type) != 1 || (flags &amp; CV_CALIB_CB_NORMALIZE_IMAGE) )
    {
        // equalize the input image histogram -
        // that should make the contrast between &quot;black&quot; and &quot;white&quot; areas big enough
        norm_img = cvCreateMat( img-&gt;rows, img-&gt;cols, CV_8UC1 );

        if( CV_MAT_CN(img-&gt;type) != 1 )
        {
            cvCvtColor( img, norm_img, CV_BGR2GRAY );
            img = norm_img;
        }

        if( flags &amp; CV_CALIB_CB_NORMALIZE_IMAGE )
        {
            cvEqualizeHist( img, norm_img );
            img = norm_img;
        }
    }

    if( flags &amp; CV_CALIB_CB_FAST_CHECK)
    {
        cvGetImage(img, &amp;_img);
        check_chessboard_result = cvCheckChessboard(&amp;_img, pattern_size);
        if(check_chessboard_result &lt;= 0)
        {
            return 0;
        }
    }

    // Try our standard &quot;1&quot; dilation, but if the pattern is not found, iterate the whole procedure with higher dilations.
    // This is necessary because some squares simply do not separate properly with a single dilation.  However,
    // we want to use the minimum number of dilations possible since dilations cause the squares to become smaller,
    // making it difficult to detect smaller squares.
    for( k = 0; k &lt; 6; k++ )
    {
        int max_quad_buf_size = 0;
        for( dilations = min_dilations; dilations &lt;= max_dilations; dilations++ )
        {
            if (found)
                break;      // already found it

            cvFree(&amp;quads);
            cvFree(&amp;corners);

            /*if( k == 1 )
            {
                //Pattern was not found using binarization
                // Run multi-level quads extraction
                // In case one-level binarization did not give enough number of quads
                CV_CALL( quad_count = icvGenerateQuadsEx( &amp;quads, &amp;corners, storage, img, thresh_img, dilations, flags ));
                PRINTF(&quot;EX quad count: %d/%d\n&quot;, quad_count, expected_corners_num);
            }
            else*/
            {
                // convert the input grayscale image to binary (black-n-white)
                if( flags &amp; CV_CALIB_CB_ADAPTIVE_THRESH )
                {
                    int block_size = cvRound(prev_sqr_size == 0 ?
                        MIN(img-&gt;cols,img-&gt;rows)*(k%2 == 0 ? 0.2 : 0.1): prev_sqr_size*2)|1;

                    // convert to binary
                    cvAdaptiveThreshold( img, thresh_img, 255,
                        CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/2)*5 );
                    if (dilations &gt; 0)
                        cvDilate( thresh_img, thresh_img, 0, dilations-1 );
                }
                else
                {
                    // Make dilation before the thresholding.
                    // It splits chessboard corners
                    //cvDilate( img, thresh_img, 0, 1 );

                    // empiric threshold level
                    double mean = cvAvg( img ).val[0];
                    int thresh_level = cvRound( mean - 10 );
                    thresh_level = MAX( thresh_level, 10 );

                    cvThreshold( img, thresh_img, thresh_level, 255, CV_THRESH_BINARY );
                    cvDilate( thresh_img, thresh_img, 0, dilations );
                }

#ifdef DEBUG_CHESSBOARD
                cvCvtColor(thresh_img,dbg_img,CV_GRAY2BGR);
#endif

                // So we can find rectangles that go to the edge, we draw a white line around the image edge.
                // Otherwise FindContours will miss those clipped rectangle contours.
                // The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()...
                cvRectangle( thresh_img, cvPoint(0,0), cvPoint(thresh_img-&gt;cols-1,
                    thresh_img-&gt;rows-1), CV_RGB(255,255,255), 3, 8);

                quad_count = icvGenerateQuads( &amp;quads, &amp;corners, storage, thresh_img, flags, &amp;max_quad_buf_size);

                PRINTF(&quot;Quad count: %d/%d\n&quot;, quad_count, expected_corners_num);
            }


#ifdef DEBUG_CHESSBOARD
            cvCopy(dbg_img, dbg1_img);
            cvNamedWindow(&quot;all_quads&quot;, 1);
            // copy corners to temp array
            for(int i = 0; i &lt; quad_count; i++ )
            {
                for (int k=0; k&lt;4; k++)
                {
                    CvPoint2D32f pt1, pt2;
                    CvScalar color = CV_RGB(30,255,30);
                    pt1 = quads[i].corners[k]-&gt;pt;
                    pt2 = quads[i].corners[(k+1)%4]-&gt;pt;
                    pt2.x = (pt1.x + pt2.x)/2;
                    pt2.y = (pt1.y + pt2.y)/2;
                    if (k&gt;0)
                        color = CV_RGB(200,200,0);
                    cvLine( dbg1_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8);
                }
            }


            cvShowImage(&quot;all_quads&quot;, (IplImage*)dbg1_img);
            cvWaitKey();
#endif

            if( quad_count &lt;= 0 )
                continue;

            // Find quad's neighbors
            icvFindQuadNeighbors( quads, quad_count );

            // allocate extra for adding in icvOrderFoundQuads
            cvFree(&amp;quad_group);
            cvFree(&amp;corner_group);
            quad_group = (CvCBQuad**)cvAlloc( sizeof(quad_group[0]) * max_quad_buf_size);
            corner_group = (CvCBCorner**)cvAlloc( sizeof(corner_group[0]) * max_quad_buf_size * 4 );

            for( group_idx = 0; ; group_idx++ )
            {
                int count = 0;
                count = icvFindConnectedQuads( quads, quad_count, quad_group, group_idx, storage );

                int icount = count;
                if( count == 0 )
                    break;

                // order the quad corners globally
                // maybe delete or add some
                PRINTF(&quot;Starting ordering of inner quads\n&quot;);
                count = icvOrderFoundConnectedQuads(count, quad_group, &amp;quad_count, &amp;quads, &amp;corners,
                    pattern_size, max_quad_buf_size, storage );
                PRINTF(&quot;Orig count: %d  After ordering: %d\n&quot;, icount, count);


#ifdef DEBUG_CHESSBOARD
                cvCopy(dbg_img,dbg2_img);
                cvNamedWindow(&quot;connected_group&quot;, 1);
                // copy corners to temp array
                for(int i = 0; i &lt; quad_count; i++ )
                {
                    if (quads[i].group_idx == group_idx)
                        for (int k=0; k&lt;4; k++)
                        {
                            CvPoint2D32f pt1, pt2;
                            CvScalar color = CV_RGB(30,255,30);
                            if (quads[i].ordered)
                                color = CV_RGB(255,30,30);
                            pt1 = quads[i].corners[k]-&gt;pt;
                            pt2 = quads[i].corners[(k+1)%4]-&gt;pt;
                            pt2.x = (pt1.x + pt2.x)/2;
                            pt2.y = (pt1.y + pt2.y)/2;
                            if (k&gt;0)
                                color = CV_RGB(200,200,0);
                            cvLine( dbg2_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 3, 8);
                        }
                }
                cvShowImage(&quot;connected_group&quot;, (IplImage*)dbg2_img);
                cvWaitKey();
#endif

                if (count == 0)
                    continue;       // haven't found inner quads


                // If count is more than it should be, this will remove those quads
                // which cause maximum deviation from a nice square pattern.
                count = icvCleanFoundConnectedQuads( count, quad_group, pattern_size );
                PRINTF(&quot;Connected group: %d  orig count: %d cleaned: %d\n&quot;, group_idx, icount, count);

                count = icvCheckQuadGroup( quad_group, count, corner_group, pattern_size );
                PRINTF(&quot;Connected group: %d  count: %d  cleaned: %d\n&quot;, group_idx, icount, count);

                {
                int n = count &gt; 0 ? pattern_size.width * pattern_size.height : -count;
                n = MIN( n, pattern_size.width * pattern_size.height );
                float sum_dist = 0;
                int total = 0;

                for(int i = 0; i &lt; n; i++ )
                {
                    int ni = 0;
                    float avgi = corner_group[i]-&gt;meanDist(&amp;ni);
                    sum_dist += avgi*ni;
                    total += ni;
                }
                prev_sqr_size = cvRound(sum_dist/MAX(total, 1));

                if( count &gt; 0 || (out_corner_count &amp;&amp; -count &gt; *out_corner_count) )
                {
                    // copy corners to output array
                    for(int i = 0; i &lt; n; i++ )
                        out_corners[i] = corner_group[i]-&gt;pt;

                    if( out_corner_count )
                        *out_corner_count = n;

                    if( count == pattern_size.width*pattern_size.height &amp;&amp;
                        icvCheckBoardMonotony( out_corners, pattern_size ))
                    {
                        found = 1;
                        break;
                    }
                }
                }
            }
        }//dilations
    }//

    if( found )
        found = icvCheckBoardMonotony( out_corners, pattern_size );

    // check that none of the found corners is too close to the image boundary
    if( found )
    {
        const int BORDER = 8;
        for( k = 0; k &lt; pattern_size.width*pattern_size.height; k++ )
        {
            if( out_corners[k].x &lt;= BORDER || out_corners[k].x &gt; img-&gt;cols - BORDER ||
                out_corners[k].y &lt;= BORDER || out_corners[k].y &gt; img-&gt;rows - BORDER )
                break;
        }

        found = k == pattern_size.width*pattern_size.height;
    }

    if( found &amp;&amp; pattern_size.height % 2 == 0 &amp;&amp; pattern_size.width % 2 == 0 )
    {
        int last_row = (pattern_size.height-1)*pattern_size.width;
        double dy0 = out_corners[last_row].y - out_corners[0].y;
        if( dy0 &lt; 0 )
        {
            int n = pattern_size.width*pattern_size.height;
            for(int i = 0; i &lt; n/2; i++ )
            {
                CvPoint2D32f temp;
                CV_SWAP(out_corners[i], out_corners[n-i-1], temp);
            }
        }
    }

    if( found )
    {
        cv::Ptr&lt;CvMat&gt; gray;
        if( CV_MAT_CN(img-&gt;type) != 1 )
        {
            gray = cvCreateMat(img-&gt;rows, img-&gt;cols, CV_8UC1);
            cvCvtColor(img, gray, CV_BGR2GRAY);
        }
        else
        {
            gray = cvCloneMat(img);
        }
        int wsize = 2;
        cvFindCornerSubPix( gray, out_corners, pattern_size.width*pattern_size.height,
            cvSize(wsize, wsize), cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 15, 0.1));
    }
    }
    catch(...)
    {
        cvFree(&amp;quads);
        cvFree(&amp;corners);
        cvFree(&amp;quad_group);
        cvFree(&amp;corner_group);
        throw;
    }

    cvFree(&amp;quads);
    cvFree(&amp;corners);
    cvFree(&amp;quad_group);
    cvFree(&amp;corner_group);
    return found;
}

//
// Checks that each board row and column is pretty much monotonous curve:
// It analyzes each row and each column of the chessboard as following:
//    for each corner c lying between end points in the same row/column it checks that
//    the point projection to the line segment (a,b) is lying between projections
//    of the neighbor corners in the same row/column.
//
// This function has been created as temporary workaround for the bug in current implementation
// of cvFindChessboardCornes that produces absolutely unordered sets of corners.
//

static int
icvCheckBoardMonotony( CvPoint2D32f* corners, CvSize pattern_size )
{
    int i, j, k;

    for( k = 0; k &lt; 2; k++ )
    {
        for( i = 0; i &lt; (k == 0 ? pattern_size.height : pattern_size.width); i++ )
        {
            CvPoint2D32f a = k == 0 ? corners[i*pattern_size.width] : corners[i];
            CvPoint2D32f b = k == 0 ? corners[(i+1)*pattern_size.width-1] :
                corners[(pattern_size.height-1)*pattern_size.width + i];
            float prevt = 0, dx0 = b.x - a.x, dy0 = b.y - a.y;
            if( fabs(dx0) + fabs(dy0) &lt; FLT_EPSILON )
                return 0;
            for( j = 1; j &lt; (k == 0 ? pattern_size.width : pattern_size.height) - 1; j++ )
            {
                CvPoint2D32f c = k == 0 ? corners[i*pattern_size.width + j] :
                    corners[j*pattern_size.width + i];
                float t = ((c.x - a.x)*dx0 + (c.y - a.y)*dy0)/(dx0*dx0 + dy0*dy0);
                if( t &lt; prevt || t &gt; 1 )
                    return 0;
                prevt = t;
            }
        }
    }

    return 1;
}

//
// order a group of connected quads
// order of corners:
//   0 is top left
//   clockwise from there
// note: &quot;top left&quot; is nominal, depends on initial ordering of starting quad
//   but all other quads are ordered consistently
//
// can change the number of quads in the group
// can add quads, so we need to have quad/corner arrays passed in
//

static int
icvOrderFoundConnectedQuads( int quad_count, CvCBQuad **quads,
        int *all_count, CvCBQuad **all_quads, CvCBCorner **corners,
        CvSize pattern_size, int max_quad_buf_size, CvMemStorage* storage )
{
    cv::Ptr&lt;CvMemStorage&gt; temp_storage = cvCreateChildMemStorage( storage );
    CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage );

    // first find an interior quad
    CvCBQuad *start = NULL;
    for (int i=0; i&lt;quad_count; i++)
    {
        if (quads[i]-&gt;count == 4)
        {
            start = quads[i];
            break;
        }
    }

    if (start == NULL)
        return 0;   // no 4-connected quad

    // start with first one, assign rows/cols
    int row_min = 0, col_min = 0, row_max=0, col_max = 0;

    std::map&lt;int, int&gt; col_hist;
    std::map&lt;int, int&gt; row_hist;

    cvSeqPush(stack, &amp;start);
    start-&gt;row = 0;
    start-&gt;col = 0;
    start-&gt;ordered = true;

    // Recursively order the quads so that all position numbers (e.g.,
    // 0,1,2,3) are in the at the same relative corner (e.g., lower right).

    while( stack-&gt;total )
    {
        CvCBQuad* q;
        cvSeqPop( stack, &amp;q );
        int col = q-&gt;col;
        int row = q-&gt;row;
        col_hist[col]++;
        row_hist[row]++;

        // check min/max
        if (row &gt; row_max) row_max = row;
        if (row &lt; row_min) row_min = row;
        if (col &gt; col_max) col_max = col;
        if (col &lt; col_min) col_min = col;

        for(int i = 0; i &lt; 4; i++ )
        {
            CvCBQuad *neighbor = q-&gt;neighbors[i];
            switch(i)   // adjust col, row for this quad
            {           // start at top left, go clockwise
            case 0:
                row--; col--; break;
            case 1:
                col += 2; break;
            case 2:
                row += 2;   break;
            case 3:
                col -= 2; break;
            }

            // just do inside quads
            if (neighbor &amp;&amp; neighbor-&gt;ordered == false &amp;&amp; neighbor-&gt;count == 4)
            {
                PRINTF(&quot;col: %d  row: %d\n&quot;, col, row);
                icvOrderQuad(neighbor, q-&gt;corners[i], (i+2)%4); // set in order
                neighbor-&gt;ordered = true;
                neighbor-&gt;row = row;
                neighbor-&gt;col = col;
                cvSeqPush( stack, &amp;neighbor );
            }
        }
    }

    for (int i=col_min; i&lt;=col_max; i++)
        PRINTF(&quot;HIST[%d] = %d\n&quot;, i, col_hist[i]);

    // analyze inner quad structure
    int w = pattern_size.width - 1;
    int h = pattern_size.height - 1;
    int drow = row_max - row_min + 1;
    int dcol = col_max - col_min + 1;

    // normalize pattern and found quad indices
    if ((w &gt; h &amp;&amp; dcol &lt; drow) ||
        (w &lt; h &amp;&amp; drow &lt; dcol))
    {
        h = pattern_size.width - 1;
        w = pattern_size.height - 1;
    }

    PRINTF(&quot;Size: %dx%d  Pattern: %dx%d\n&quot;, dcol, drow, w, h);

    // check if there are enough inner quads
    if (dcol &lt; w || drow &lt; h)   // found enough inner quads?
    {
        PRINTF(&quot;Too few inner quad rows/cols\n&quot;);
        return 0;   // no, return
    }
#ifdef ENABLE_TRIM_COL_ROW
    // too many columns, not very common
    if (dcol == w+1)    // too many, trim
    {
        PRINTF(&quot;Trimming cols\n&quot;);
        if (col_hist[col_max] &gt; col_hist[col_min])
        {
            PRINTF(&quot;Trimming left col\n&quot;);
            quad_count = icvTrimCol(quads,quad_count,col_min,-1);
        }
        else
        {
            PRINTF(&quot;Trimming right col\n&quot;);
            quad_count = icvTrimCol(quads,quad_count,col_max,+1);
        }
    }

    // too many rows, not very common
    if (drow == h+1)    // too many, trim
    {
        PRINTF(&quot;Trimming rows\n&quot;);
        if (row_hist[row_max] &gt; row_hist[row_min])
        {
            PRINTF(&quot;Trimming top row\n&quot;);
            quad_count = icvTrimRow(quads,quad_count,row_min,-1);
        }
        else
        {
            PRINTF(&quot;Trimming bottom row\n&quot;);
            quad_count = icvTrimRow(quads,quad_count,row_max,+1);
        }
    }
#endif

    // check edges of inner quads
    // if there is an outer quad missing, fill it in
    // first order all inner quads
    int found = 0;
    for (int i=0; i&lt;quad_count; i++)
    {
        if (quads[i]-&gt;count == 4)
        {   // ok, look at neighbors
            int col = quads[i]-&gt;col;
            int row = quads[i]-&gt;row;
            for (int j=0; j&lt;4; j++)
            {
                switch(j)   // adjust col, row for this quad
                {       // start at top left, go clockwise
                case 0:
                    row--; col--; break;
                case 1:
                    col += 2; break;
                case 2:
                    row += 2;   break;
                case 3:
                    col -= 2; break;
                }
                CvCBQuad *neighbor = quads[i]-&gt;neighbors[j];
                if (neighbor &amp;&amp; !neighbor-&gt;ordered &amp;&amp; // is it an inner quad?
                    col &lt;= col_max &amp;&amp; col &gt;= col_min &amp;&amp;
                    row &lt;= row_max &amp;&amp; row &gt;= row_min)
                {
                    // if so, set in order
                    PRINTF(&quot;Adding inner: col: %d  row: %d\n&quot;, col, row);
                    found++;
                    icvOrderQuad(neighbor, quads[i]-&gt;corners[j], (j+2)%4);
                    neighbor-&gt;ordered = true;
                    neighbor-&gt;row = row;
                    neighbor-&gt;col = col;
                }
            }
        }
    }

    // if we have found inner quads, add corresponding outer quads,
    //   which are missing
    if (found &gt; 0)
    {
        PRINTF(&quot;Found %d inner quads not connected to outer quads, repairing\n&quot;, found);
        for (int i=0; i&lt;quad_count &amp;&amp; *all_count &lt; max_quad_buf_size; i++)
        {
            if (quads[i]-&gt;count &lt; 4 &amp;&amp; quads[i]-&gt;ordered)
            {
                int added = icvAddOuterQuad(quads[i],quads,quad_count,all_quads,*all_count,corners, max_quad_buf_size);
                *all_count += added;
                quad_count += added;
            }
        }

        if (*all_count &gt;= max_quad_buf_size)
            return 0;
    }


    // final trimming of outer quads
    if (dcol == w &amp;&amp; drow == h) // found correct inner quads
    {
        PRINTF(&quot;Inner bounds ok, check outer quads\n&quot;);
        int rcount = quad_count;
        for (int i=quad_count-1; i&gt;=0; i--) // eliminate any quad not connected to
            // an ordered quad
        {
            if (quads[i]-&gt;ordered == false)
            {
                bool outer = false;
                for (int j=0; j&lt;4; j++) // any neighbors that are ordered?
                {
                    if (quads[i]-&gt;neighbors[j] &amp;&amp; quads[i]-&gt;neighbors[j]-&gt;ordered)
                        outer = true;
                }
                if (!outer) // not an outer quad, eliminate
                {
                    PRINTF(&quot;Removing quad %d\n&quot;, i);
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]);
                    rcount--;
                }
            }

        }
        return rcount;
    }

    return 0;
}


// add an outer quad
// looks for the neighbor of &lt;quad&gt; that isn't present,
//   tries to add it in.
// &lt;quad&gt; is ordered

static int
icvAddOuterQuad( CvCBQuad *quad, CvCBQuad **quads, int quad_count,
        CvCBQuad **all_quads, int all_count, CvCBCorner **corners, int max_quad_buf_size )

{
    int added = 0;
    for (int i=0; i&lt;4 &amp;&amp; all_count &lt; max_quad_buf_size; i++) // find no-neighbor corners
    {
        if (!quad-&gt;neighbors[i])    // ok, create and add neighbor
        {
            int j = (i+2)%4;
            PRINTF(&quot;Adding quad as neighbor 2\n&quot;);
            CvCBQuad *q = &amp;(*all_quads)[all_count];
            memset( q, 0, sizeof(*q) );
            added++;
            quads[quad_count] = q;
            quad_count++;

            // set neighbor and group id
            quad-&gt;neighbors[i] = q;
            quad-&gt;count += 1;
            q-&gt;neighbors[j] = quad;
            q-&gt;group_idx = quad-&gt;group_idx;
            q-&gt;count = 1;   // number of neighbors
            q-&gt;ordered = false;
            q-&gt;edge_len = quad-&gt;edge_len;

            // make corners of new quad
            // same as neighbor quad, but offset
            CvPoint2D32f pt = quad-&gt;corners[i]-&gt;pt;
            CvCBCorner* corner;
            float dx = pt.x - quad-&gt;corners[j]-&gt;pt.x;
            float dy = pt.y - quad-&gt;corners[j]-&gt;pt.y;
            for (int k=0; k&lt;4; k++)
            {
                corner = &amp;(*corners)[all_count*4+k];
                pt = quad-&gt;corners[k]-&gt;pt;
                memset( corner, 0, sizeof(*corner) );
                corner-&gt;pt = pt;
                q-&gt;corners[k] = corner;
                corner-&gt;pt.x += dx;
                corner-&gt;pt.y += dy;
            }
            // have to set exact corner
            q-&gt;corners[j] = quad-&gt;corners[i];

            // now find other neighbor and add it, if possible
            if (quad-&gt;neighbors[(i+3)%4] &amp;&amp;
                quad-&gt;neighbors[(i+3)%4]-&gt;ordered &amp;&amp;
                quad-&gt;neighbors[(i+3)%4]-&gt;neighbors[i] &amp;&amp;
                quad-&gt;neighbors[(i+3)%4]-&gt;neighbors[i]-&gt;ordered )
            {
                CvCBQuad *qn = quad-&gt;neighbors[(i+3)%4]-&gt;neighbors[i];
                q-&gt;count = 2;
                q-&gt;neighbors[(j+1)%4] = qn;
                qn-&gt;neighbors[(i+1)%4] = q;
                qn-&gt;count += 1;
                // have to set exact corner
                q-&gt;corners[(j+1)%4] = qn-&gt;corners[(i+1)%4];
            }

            all_count++;
        }
    }
    return added;
}


// trimming routines
#ifdef ENABLE_TRIM_COL_ROW
static int
icvTrimCol(CvCBQuad **quads, int count, int col, int dir)
{
    int rcount = count;
    // find the right quad(s)
    for (int i=0; i&lt;count; i++)
    {
#ifdef DEBUG_CHESSBOARD
        if (quads[i]-&gt;ordered)
            PRINTF(&quot;index: %d  cur: %d\n&quot;, col, quads[i]-&gt;col);
#endif
        if (quads[i]-&gt;ordered &amp;&amp; quads[i]-&gt;col == col)
        {
            if (dir == 1)
            {
                if (quads[i]-&gt;neighbors[1])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[1]);
                    rcount--;
                }
                if (quads[i]-&gt;neighbors[2])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[2]);
                    rcount--;
                }
            }
            else
            {
                if (quads[i]-&gt;neighbors[0])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[0]);
                    rcount--;
                }
                if (quads[i]-&gt;neighbors[3])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[3]);
                    rcount--;
                }
            }

        }
    }
    return rcount;
}

static int
icvTrimRow(CvCBQuad **quads, int count, int row, int dir)
{
    int i, rcount = count;
    // find the right quad(s)
    for (i=0; i&lt;count; i++)
    {
#ifdef DEBUG_CHESSBOARD
        if (quads[i]-&gt;ordered)
            PRINTF(&quot;index: %d  cur: %d\n&quot;, row, quads[i]-&gt;row);
#endif
        if (quads[i]-&gt;ordered &amp;&amp; quads[i]-&gt;row == row)
        {
            if (dir == 1)   // remove from bottom
            {
                if (quads[i]-&gt;neighbors[2])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[2]);
                    rcount--;
                }
                if (quads[i]-&gt;neighbors[3])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[3]);
                    rcount--;
                }
            }
            else    // remove from top
            {
                if (quads[i]-&gt;neighbors[0])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[0]);
                    rcount--;
                }
                if (quads[i]-&gt;neighbors[1])
                {
                    icvRemoveQuadFromGroup(quads,rcount,quads[i]-&gt;neighbors[1]);
                    rcount--;
                }
            }

        }
    }
    return rcount;
}
#endif

//
// remove quad from quad group
//

static void
icvRemoveQuadFromGroup(CvCBQuad **quads, int count, CvCBQuad *q0)
{
    int i, j;
    // remove any references to this quad as a neighbor
    for(i = 0; i &lt; count; i++ )
    {
        CvCBQuad *q = quads[i];
        for(j = 0; j &lt; 4; j++ )
        {
            if( q-&gt;neighbors[j] == q0 )
            {
                q-&gt;neighbors[j] = 0;
                q-&gt;count--;
                for(int k = 0; k &lt; 4; k++ )
                    if( q0-&gt;neighbors[k] == q )
                    {
                        q0-&gt;neighbors[k] = 0;
                        q0-&gt;count--;
                        break;
                    }
                    break;
            }
        }
    }

    // remove the quad
    for(i = 0; i &lt; count; i++ )
    {
        CvCBQuad *q = quads[i];
        if (q == q0)
        {
            quads[i] = quads[count-1];
            break;
        }
    }
}

//
// put quad into correct order, where &lt;corner&gt; has value &lt;common&gt;
//

static void
icvOrderQuad(CvCBQuad *quad, CvCBCorner *corner, int common)
{
    // find the corner
    int tc;
    for (tc=0; tc&lt;4; tc++)
        if (quad-&gt;corners[tc]-&gt;pt.x == corner-&gt;pt.x &amp;&amp;
            quad-&gt;corners[tc]-&gt;pt.y == corner-&gt;pt.y)
            break;

    // set corner order
    // shift
    while (tc != common)
    {
        // shift by one
        CvCBCorner *tempc;
        CvCBQuad *tempq;
        tempc = quad-&gt;corners[3];
        tempq = quad-&gt;neighbors[3];
        for (int i=3; i&gt;0; i--)
        {
            quad-&gt;corners[i] = quad-&gt;corners[i-1];
            quad-&gt;neighbors[i] = quad-&gt;neighbors[i-1];
        }
        quad-&gt;corners[0] = tempc;
        quad-&gt;neighbors[0] = tempq;
        tc++;
        tc = tc%4;
    }
}


// if we found too many connect quads, remove those which probably do not belong.
static int
icvCleanFoundConnectedQuads( int quad_count, CvCBQuad **quad_group, CvSize pattern_size )
{
    CvPoint2D32f center = {0,0};
    int i, j, k;
    // number of quads this pattern should contain
    int count = ((pattern_size.width + 1)*(pattern_size.height + 1) + 1)/2;

    // if we have more quadrangles than we should,
    // try to eliminate duplicates or ones which don't belong to the pattern rectangle...
    if( quad_count &lt;= count )
        return quad_count;

    // create an array of quadrangle centers
    cv::AutoBuffer&lt;CvPoint2D32f&gt; centers( quad_count );
    cv::Ptr&lt;CvMemStorage&gt; temp_storage = cvCreateMemStorage(0);

    for( i = 0; i &lt; quad_count; i++ )
    {
        CvPoint2D32f ci = {0,0};
        CvCBQuad* q = quad_group[i];

        for( j = 0; j &lt; 4; j++ )
        {
            CvPoint2D32f pt = q-&gt;corners[j]-&gt;pt;
            ci.x += pt.x;
            ci.y += pt.y;
        }

        ci.x *= 0.25f;
        ci.y *= 0.25f;

        centers[i] = ci;
        center.x += ci.x;
        center.y += ci.y;
    }
    center.x /= quad_count;
    center.y /= quad_count;

    // If we still have more quadrangles than we should,
    // we try to eliminate bad ones based on minimizing the bounding box.
    // We iteratively remove the point which reduces the size of
    // the bounding box of the blobs the most
    // (since we want the rectangle to be as small as possible)
    // remove the quadrange that causes the biggest reduction
    // in pattern size until we have the correct number
    for( ; quad_count &gt; count; quad_count-- )
    {
        double min_box_area = DBL_MAX;
        int skip, min_box_area_index = -1;
        CvCBQuad *q0, *q;

        // For each point, calculate box area without that point
        for( skip = 0; skip &lt; quad_count; skip++ )
        {
            // get bounding rectangle
            CvPoint2D32f temp = centers[skip]; // temporarily make index 'skip' the same as
            centers[skip] = center;            // pattern center (so it is not counted for convex hull)
            CvMat pointMat = cvMat(1, quad_count, CV_32FC2, centers);
            CvSeq *hull = cvConvexHull2( &amp;pointMat, temp_storage, CV_CLOCKWISE, 1 );
            centers[skip] = temp;
            double hull_area = fabs(cvContourArea(hull, CV_WHOLE_SEQ));

            // remember smallest box area
            if( hull_area &lt; min_box_area )
            {
                min_box_area = hull_area;
                min_box_area_index = skip;
            }
            cvClearMemStorage( temp_storage );
        }

        q0 = quad_group[min_box_area_index];

        // remove any references to this quad as a neighbor
        for( i = 0; i &lt; quad_count; i++ )
        {
            q = quad_group[i];
            for( j = 0; j &lt; 4; j++ )
            {
                if( q-&gt;neighbors[j] == q0 )
                {
                    q-&gt;neighbors[j] = 0;
                    q-&gt;count--;
                    for( k = 0; k &lt; 4; k++ )
                        if( q0-&gt;neighbors[k] == q )
                        {
                            q0-&gt;neighbors[k] = 0;
                            q0-&gt;count--;
                            break;
                        }
                    break;
                }
            }
        }

        // remove the quad
        quad_count--;
        quad_group[min_box_area_index] = quad_group[quad_count];
        centers[min_box_area_index] = centers[quad_count];
    }

    return quad_count;
}

//=====================================================================================

static int
icvFindConnectedQuads( CvCBQuad *quad, int quad_count, CvCBQuad **out_group,
                       int group_idx, CvMemStorage* storage )
{
    cv::Ptr&lt;CvMemStorage&gt; temp_storage = cvCreateChildMemStorage( storage );
    CvSeq* stack = cvCreateSeq( 0, sizeof(*stack), sizeof(void*), temp_storage );
    int i, count = 0;

    // Scan the array for a first unlabeled quad
    for( i = 0; i &lt; quad_count; i++ )
    {
        if( quad[i].count &gt; 0 &amp;&amp; quad[i].group_idx &lt; 0)
            break;
    }

    // Recursively find a group of connected quads starting from the seed quad[i]
    if( i &lt; quad_count )
    {
        CvCBQuad* q = &amp;quad[i];
        cvSeqPush( stack, &amp;q );
        out_group[count++] = q;
        q-&gt;group_idx = group_idx;
        q-&gt;ordered = false;

        while( stack-&gt;total )
        {
            cvSeqPop( stack, &amp;q );
            for( i = 0; i &lt; 4; i++ )
            {
                CvCBQuad *neighbor = q-&gt;neighbors[i];
                if( neighbor &amp;&amp; neighbor-&gt;count &gt; 0 &amp;&amp; neighbor-&gt;group_idx &lt; 0 )
                {
                    cvSeqPush( stack, &amp;neighbor );
                    out_group[count++] = neighbor;
                    neighbor-&gt;group_idx = group_idx;
                    neighbor-&gt;ordered = false;
                }
            }
        }
    }

    return count;
}


//=====================================================================================

static int
icvCheckQuadGroup( CvCBQuad **quad_group, int quad_count,
                   CvCBCorner **out_corners, CvSize pattern_size )
{
    const int ROW1 = 1000000;
    const int ROW2 = 2000000;
    const int ROW_ = 3000000;
    int result = 0;
    int i, out_corner_count = 0, corner_count = 0;
    std::vector&lt;CvCBCorner*&gt; corners(quad_count*4);

    int j, k, kk;
    int width = 0, height = 0;
    int hist[5] = {0,0,0,0,0};
    CvCBCorner* first = 0, *first2 = 0, *right, *cur, *below, *c;

    // build dual graph, which vertices are internal quad corners
    // and two vertices are connected iff they lie on the same quad edge
    for( i = 0; i &lt; quad_count; i++ )
    {
        CvCBQuad* q = quad_group[i];
        /*CvScalar color = q-&gt;count == 0 ? cvScalar(0,255,255) :
                         q-&gt;count == 1 ? cvScalar(0,0,255) :
                         q-&gt;count == 2 ? cvScalar(0,255,0) :
                         q-&gt;count == 3 ? cvScalar(255,255,0) :
                                         cvScalar(255,0,0);*/

        for( j = 0; j &lt; 4; j++ )
        {
            //cvLine( debug_img, cvPointFrom32f(q-&gt;corners[j]-&gt;pt), cvPointFrom32f(q-&gt;corners[(j+1)&amp;3]-&gt;pt), color, 1, CV_AA, 0 );
            if( q-&gt;neighbors[j] )
            {
                CvCBCorner *a = q-&gt;corners[j], *b = q-&gt;corners[(j+1)&amp;3];
                // mark internal corners that belong to:
                //   - a quad with a single neighbor - with ROW1,
                //   - a quad with two neighbors     - with ROW2
                // make the rest of internal corners with ROW_
                int row_flag = q-&gt;count == 1 ? ROW1 : q-&gt;count == 2 ? ROW2 : ROW_;

                if( a-&gt;row == 0 )
                {
                    corners[corner_count++] = a;
                    a-&gt;row = row_flag;
                }
                else if( a-&gt;row &gt; row_flag )
                    a-&gt;row = row_flag;

                if( q-&gt;neighbors[(j+1)&amp;3] )
                {
                    if( a-&gt;count &gt;= 4 || b-&gt;count &gt;= 4 )
                        goto finalize;
                    for( k = 0; k &lt; 4; k++ )
                    {
                        if( a-&gt;neighbors[k] == b )
                            goto finalize;
                        if( b-&gt;neighbors[k] == a )
                            goto finalize;
                    }
                    a-&gt;neighbors[a-&gt;count++] = b;
                    b-&gt;neighbors[b-&gt;count++] = a;
                }
            }
        }
    }

    if( corner_count != pattern_size.width*pattern_size.height )
        goto finalize;

    for( i = 0; i &lt; corner_count; i++ )
    {
        int n = corners[i]-&gt;count;
        assert( 0 &lt;= n &amp;&amp; n &lt;= 4 );
        hist[n]++;
        if( !first &amp;&amp; n == 2 )
        {
            if( corners[i]-&gt;row == ROW1 )
                first = corners[i];
            else if( !first2 &amp;&amp; corners[i]-&gt;row == ROW2 )
                first2 = corners[i];
        }
    }

    // start with a corner that belongs to a quad with a signle neighbor.
    // if we do not have such, start with a corner of a quad with two neighbors.
    if( !first )
        first = first2;

    if( !first || hist[0] != 0 || hist[1] != 0 || hist[2] != 4 ||
        hist[3] != (pattern_size.width + pattern_size.height)*2 - 8 )
        goto finalize;

    cur = first;
    right = below = 0;
    out_corners[out_corner_count++] = cur;

    for( k = 0; k &lt; 4; k++ )
    {
        c = cur-&gt;neighbors[k];
        if( c )
        {
            if( !right )
                right = c;
            else if( !below )
                below = c;
        }
    }

    if( !right || (right-&gt;count != 2 &amp;&amp; right-&gt;count != 3) ||
        !below || (below-&gt;count != 2 &amp;&amp; below-&gt;count != 3) )
        goto finalize;

    cur-&gt;row = 0;
    //cvCircle( debug_img, cvPointFrom32f(cur-&gt;pt), 3, cvScalar(0,255,0), -1, 8, 0 );

    first = below; // remember the first corner in the next row
    // find and store the first row (or column)
    for(j=1;;j++)
    {
        right-&gt;row = 0;
        out_corners[out_corner_count++] = right;
        //cvCircle( debug_img, cvPointFrom32f(right-&gt;pt), 3, cvScalar(0,255-j*10,0), -1, 8, 0 );
        if( right-&gt;count == 2 )
            break;
        if( right-&gt;count != 3 || out_corner_count &gt;= MAX(pattern_size.width,pattern_size.height) )
            goto finalize;
        cur = right;
        for( k = 0; k &lt; 4; k++ )
        {
            c = cur-&gt;neighbors[k];
            if( c &amp;&amp; c-&gt;row &gt; 0 )
            {
                for( kk = 0; kk &lt; 4; kk++ )
                {
                    if( c-&gt;neighbors[kk] == below )
                        break;
                }
                if( kk &lt; 4 )
                    below = c;
                else
                    right = c;
            }
        }
    }

    width = out_corner_count;
    if( width == pattern_size.width )
        height = pattern_size.height;
    else if( width == pattern_size.height )
        height = pattern_size.width;
    else
        goto finalize;

    // find and store all the other rows
    for( i = 1; ; i++ )
    {
        if( !first )
            break;
        cur = first;
        first = 0;
        for( j = 0;; j++ )
        {
            cur-&gt;row = i;
            out_corners[out_corner_count++] = cur;
            //cvCircle( debug_img, cvPointFrom32f(cur-&gt;pt), 3, cvScalar(0,0,255-j*10), -1, 8, 0 );
            if( cur-&gt;count == 2 + (i &lt; height-1) &amp;&amp; j &gt; 0 )
                break;

            right = 0;

            // find a neighbor that has not been processed yet
            // and that has a neighbor from the previous row
            for( k = 0; k &lt; 4; k++ )
            {
                c = cur-&gt;neighbors[k];
                if( c &amp;&amp; c-&gt;row &gt; i )
                {
                    for( kk = 0; kk &lt; 4; kk++ )
                    {
                        if( c-&gt;neighbors[kk] &amp;&amp; c-&gt;neighbors[kk]-&gt;row == i-1 )
                            break;
                    }
                    if( kk &lt; 4 )
                    {
                        right = c;
                        if( j &gt; 0 )
                            break;
                    }
                    else if( j == 0 )
                        first = c;
                }
            }
            if( !right )
                goto finalize;
            cur = right;
        }

        if( j != width - 1 )
            goto finalize;
    }

    if( out_corner_count != corner_count )
        goto finalize;

    // check if we need to transpose the board
    if( width != pattern_size.width )
    {
        CV_SWAP( width, height, k );

        memcpy( &amp;corners[0], out_corners, corner_count*sizeof(corners[0]) );
        for( i = 0; i &lt; height; i++ )
            for( j = 0; j &lt; width; j++ )
                out_corners[i*width + j] = corners[j*height + i];
    }

    // check if we need to revert the order in each row
    {
        CvPoint2D32f p0 = out_corners[0]-&gt;pt, p1 = out_corners[pattern_size.width-1]-&gt;pt,
                     p2 = out_corners[pattern_size.width]-&gt;pt;
        if( (p1.x - p0.x)*(p2.y - p1.y) - (p1.y - p0.y)*(p2.x - p1.x) &lt; 0 )
        {
            if( width % 2 == 0 )
            {
                for( i = 0; i &lt; height; i++ )
                    for( j = 0; j &lt; width/2; j++ )
                        CV_SWAP( out_corners[i*width+j], out_corners[i*width+width-j-1], c );
            }
            else
            {
                for( j = 0; j &lt; width; j++ )
                    for( i = 0; i &lt; height/2; i++ )
                        CV_SWAP( out_corners[i*width+j], out_corners[(height - i - 1)*width+j], c );
            }
        }
    }

    result = corner_count;

finalize:

    if( result &lt;= 0 )
    {
        corner_count = MIN( corner_count, pattern_size.width*pattern_size.height );
        for( i = 0; i &lt; corner_count; i++ )
            out_corners[i] = corners[i];
        result = -corner_count;

        if (result == -pattern_size.width*pattern_size.height)
            result = -result;
    }

    return result;
}




//=====================================================================================

static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count )
{
    const float thresh_scale = 1.f;
    int idx, i, k, j;
    float dx, dy, dist;

    // find quad neighbors
    for( idx = 0; idx &lt; quad_count; idx++ )
    {
        CvCBQuad* cur_quad = &amp;quads[idx];

        // choose the points of the current quadrangle that are close to
        // some points of the other quadrangles
        // (it can happen for split corners (due to dilation) of the
        // checker board). Search only in other quadrangles!

        // for each corner of this quadrangle
        for( i = 0; i &lt; 4; i++ )
        {
            CvPoint2D32f pt;
            float min_dist = FLT_MAX;
            int closest_corner_idx = -1;
            CvCBQuad *closest_quad = 0;
            CvCBCorner *closest_corner = 0;

            if( cur_quad-&gt;neighbors[i] )
                continue;

            pt = cur_quad-&gt;corners[i]-&gt;pt;

            // find the closest corner in all other quadrangles
            for( k = 0; k &lt; quad_count; k++ )
            {
                if( k == idx )
                    continue;

                for( j = 0; j &lt; 4; j++ )
                {
                    if( quads[k].neighbors[j] )
                        continue;

                    dx = pt.x - quads[k].corners[j]-&gt;pt.x;
                    dy = pt.y - quads[k].corners[j]-&gt;pt.y;
                    dist = dx * dx + dy * dy;

                    if( dist &lt; min_dist &amp;&amp;
                        dist &lt;= cur_quad-&gt;edge_len*thresh_scale &amp;&amp;
                        dist &lt;= quads[k].edge_len*thresh_scale )
                    {
                        // check edge lengths, make sure they're compatible
                        // edges that are different by more than 1:4 are rejected
                        float ediff = cur_quad-&gt;edge_len - quads[k].edge_len;
                        if (ediff &gt; 32*cur_quad-&gt;edge_len ||
                            ediff &gt; 32*quads[k].edge_len)
                        {
                            PRINTF(&quot;Incompatible edge lengths\n&quot;);
                            continue;
                        }
                        closest_corner_idx = j;
                        closest_quad = &amp;quads[k];
                        min_dist = dist;
                    }
                }
            }

            // we found a matching corner point?
            if( closest_corner_idx &gt;= 0 &amp;&amp; min_dist &lt; FLT_MAX )
            {
                // If another point from our current quad is closer to the found corner
                // than the current one, then we don't count this one after all.
                // This is necessary to support small squares where otherwise the wrong
                // corner will get matched to closest_quad;
                closest_corner = closest_quad-&gt;corners[closest_corner_idx];

                for( j = 0; j &lt; 4; j++ )
                {
                    if( cur_quad-&gt;neighbors[j] == closest_quad )
                        break;

                    dx = closest_corner-&gt;pt.x - cur_quad-&gt;corners[j]-&gt;pt.x;
                    dy = closest_corner-&gt;pt.y - cur_quad-&gt;corners[j]-&gt;pt.y;

                    if( dx * dx + dy * dy &lt; min_dist )
                        break;
                }

                if( j &lt; 4 || cur_quad-&gt;count &gt;= 4 || closest_quad-&gt;count &gt;= 4 )
                    continue;

                // Check that each corner is a neighbor of different quads
                for( j = 0; j &lt; closest_quad-&gt;count; j++ )
                {
                    if( closest_quad-&gt;neighbors[j] == cur_quad )
                        break;
                }
                if( j &lt; closest_quad-&gt;count )
                    continue;

                // check whether the closest corner to closest_corner
                // is different from cur_quad-&gt;corners[i]-&gt;pt
                for( k = 0; k &lt; quad_count; k++ )
                {
                    CvCBQuad* q = &amp;quads[k];
                    if( k == idx || q == closest_quad )
                        continue;

                    for( j = 0; j &lt; 4; j++ )
                        if( !q-&gt;neighbors[j] )
                        {
                            dx = closest_corner-&gt;pt.x - q-&gt;corners[j]-&gt;pt.x;
                            dy = closest_corner-&gt;pt.y - q-&gt;corners[j]-&gt;pt.y;
                            dist = dx*dx + dy*dy;
                            if( dist &lt; min_dist )
                                break;
                        }
                    if( j &lt; 4 )
                        break;
                }

                if( k &lt; quad_count )
                    continue;

                closest_corner-&gt;pt.x = (pt.x + closest_corner-&gt;pt.x) * 0.5f;
                closest_corner-&gt;pt.y = (pt.y + closest_corner-&gt;pt.y) * 0.5f;

                // We've found one more corner - remember it
                cur_quad-&gt;count++;
                cur_quad-&gt;neighbors[i] = closest_quad;
                cur_quad-&gt;corners[i] = closest_corner;

                closest_quad-&gt;count++;
                closest_quad-&gt;neighbors[closest_corner_idx] = cur_quad;
            }
        }
    }
}

//=====================================================================================

// returns corners in clockwise order
// corners don't necessarily start at same position on quad (e.g.,
//   top left corner)

static int
icvGenerateQuads( CvCBQuad **out_quads, CvCBCorner **out_corners,
                  CvMemStorage *storage, CvMat *image, int flags, int *max_quad_buf_size )
{
    int quad_count = 0;
    cv::Ptr&lt;CvMemStorage&gt; temp_storage;

    if( out_quads )
        *out_quads = 0;

    if( out_corners )
        *out_corners = 0;

    CvSeq *src_contour = 0;
    CvSeq *root;
    CvContourEx* board = 0;
    CvContourScanner scanner;
    int i, idx, min_size;

    CV_Assert( out_corners &amp;&amp; out_quads );

    // empiric bound for minimal allowed perimeter for squares
    min_size = 25; //cvRound( image-&gt;cols * image-&gt;rows * .03 * 0.01 * 0.92 );

    // create temporary storage for contours and the sequence of pointers to found quadrangles
    temp_storage = cvCreateChildMemStorage( storage );
    root = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvSeq*), temp_storage );

    // initialize contour retrieving routine
    scanner = cvStartFindContours( image, temp_storage, sizeof(CvContourEx),
                                   CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    // get all the contours one by one
    while( (src_contour = cvFindNextContour( scanner )) != 0 )
    {
        CvSeq *dst_contour = 0;
        CvRect rect = ((CvContour*)src_contour)-&gt;rect;

        // reject contours with too small perimeter
        if( CV_IS_SEQ_HOLE(src_contour) &amp;&amp; rect.width*rect.height &gt;= min_size )
        {
            const int min_approx_level = 1, max_approx_level = MAX_CONTOUR_APPROX;
            int approx_level;
            for( approx_level = min_approx_level; approx_level &lt;= max_approx_level; approx_level++ )
            {
                dst_contour = cvApproxPoly( src_contour, sizeof(CvContour), temp_storage,
                                            CV_POLY_APPROX_DP, (float)approx_level );
                if( dst_contour-&gt;total == 4 )
                    break;

                // we call this again on its own output, because sometimes
                // cvApproxPoly() does not simplify as much as it should.
                dst_contour = cvApproxPoly( dst_contour, sizeof(CvContour), temp_storage,
                                            CV_POLY_APPROX_DP, (float)approx_level );

                if( dst_contour-&gt;total == 4 )
                    break;
            }

            // reject non-quadrangles
            if( dst_contour-&gt;total == 4 &amp;&amp; cvCheckContourConvexity(dst_contour) )
            {
                CvPoint pt[4];
                double d1, d2, p = cvContourPerimeter(dst_contour);
                double area = fabs(cvContourArea(dst_contour, CV_WHOLE_SEQ));
                double dx, dy;

                for( i = 0; i &lt; 4; i++ )
                    pt[i] = *(CvPoint*)cvGetSeqElem(dst_contour, i);

                dx = pt[0].x - pt[2].x;
                dy = pt[0].y - pt[2].y;
                d1 = sqrt(dx*dx + dy*dy);

                dx = pt[1].x - pt[3].x;
                dy = pt[1].y - pt[3].y;
                d2 = sqrt(dx*dx + dy*dy);

                // philipg.  Only accept those quadrangles which are more square
                // than rectangular and which are big enough
                double d3, d4;
                dx = pt[0].x - pt[1].x;
                dy = pt[0].y - pt[1].y;
                d3 = sqrt(dx*dx + dy*dy);
                dx = pt[1].x - pt[2].x;
                dy = pt[1].y - pt[2].y;
                d4 = sqrt(dx*dx + dy*dy);
                if( !(flags &amp; CV_CALIB_CB_FILTER_QUADS) ||
                    (d3*4 &gt; d4 &amp;&amp; d4*4 &gt; d3 &amp;&amp; d3*d4 &lt; area*1.5 &amp;&amp; area &gt; min_size &amp;&amp;
                    d1 &gt;= 0.15 * p &amp;&amp; d2 &gt;= 0.15 * p) )
                {
                    CvContourEx* parent = (CvContourEx*)(src_contour-&gt;v_prev);
                    parent-&gt;counter++;
                    if( !board || board-&gt;counter &lt; parent-&gt;counter )
                        board = parent;
                    dst_contour-&gt;v_prev = (CvSeq*)parent;
                    //for( i = 0; i &lt; 4; i++ ) cvLine( debug_img, pt[i], pt[(i+1)&amp;3], cvScalar(200,255,255), 1, CV_AA, 0 );
                    cvSeqPush( root, &amp;dst_contour );
                }
            }
        }
    }

    // finish contour retrieving
    cvEndFindContours( &amp;scanner );

    // allocate quad &amp; corner buffers
    *max_quad_buf_size = MAX(1, (root-&gt;total+root-&gt;total / 2)) * 2; 
    *out_quads = (CvCBQuad*)cvAlloc(*max_quad_buf_size * sizeof((*out_quads)[0]));
    *out_corners = (CvCBCorner*)cvAlloc(*max_quad_buf_size * 4 * sizeof((*out_corners)[0]));

    // Create array of quads structures
    for( idx = 0; idx &lt; root-&gt;total; idx++ )
    {
        CvCBQuad* q = &amp;(*out_quads)[quad_count];
        src_contour = *(CvSeq**)cvGetSeqElem( root, idx );
        if( (flags &amp; CV_CALIB_CB_FILTER_QUADS) &amp;&amp; src_contour-&gt;v_prev != (CvSeq*)board )
            continue;

        // reset group ID
        memset( q, 0, sizeof(*q) );
        q-&gt;group_idx = -1;
        assert( src_contour-&gt;total == 4 );
        for( i = 0; i &lt; 4; i++ )
        {
            CvPoint2D32f pt = cvPointTo32f(*(CvPoint*)cvGetSeqElem(src_contour, i));
            CvCBCorner* corner = &amp;(*out_corners)[quad_count*4 + i];

            memset( corner, 0, sizeof(*corner) );
            corner-&gt;pt = pt;
            q-&gt;corners[i] = corner;
        }
        q-&gt;edge_len = FLT_MAX;
        for( i = 0; i &lt; 4; i++ )
        {
            float dx = q-&gt;corners[i]-&gt;pt.x - q-&gt;corners[(i+1)&amp;3]-&gt;pt.x;
            float dy = q-&gt;corners[i]-&gt;pt.y - q-&gt;corners[(i+1)&amp;3]-&gt;pt.y;
            float d = dx*dx + dy*dy;
            if( q-&gt;edge_len &gt; d )
                q-&gt;edge_len = d;
        }
        quad_count++;
    }

    return quad_count;
}


CV_IMPL void
cvDrawChessboardCorners( CvArr* _image, CvSize pattern_size,
                         CvPoint2D32f* corners, int count, int found )
{
    const int shift = 0;
    const int radius = 4;
    const int r = radius*(1 &lt;&lt; shift);
    int i;
    CvMat stub, *image;
    double scale = 1;
    int type, cn, line_type;

    image = cvGetMat( _image, &amp;stub );

    type = CV_MAT_TYPE(image-&gt;type);
    cn = CV_MAT_CN(type);
    if( cn != 1 &amp;&amp; cn != 3 &amp;&amp; cn != 4 )
        CV_Error( CV_StsUnsupportedFormat, &quot;Number of channels must be 1, 3 or 4&quot; );

    switch( CV_MAT_DEPTH(image-&gt;type) )
    {
    case CV_8U:
        scale = 1;
        break;
    case CV_16U:
        scale = 256;
        break;
    case CV_32F:
        scale = 1./255;
        break;
    default:
        CV_Error( CV_StsUnsupportedFormat,
            &quot;Only 8-bit, 16-bit or floating-point 32-bit images are supported&quot; );
    }

    line_type = type == CV_8UC1 || type == CV_8UC3 ? CV_AA : 8;

    if( !found )
    {
        CvScalar color = {{0,0,255}};
        if( cn == 1 )
            color = cvScalarAll(200);
        color.val[0] *= scale;
        color.val[1] *= scale;
        color.val[2] *= scale;
        color.val[3] *= scale;

        for( i = 0; i &lt; count; i++ )
        {
            CvPoint pt;
            pt.x = cvRound(corners[i].x*(1 &lt;&lt; shift));
            pt.y = cvRound(corners[i].y*(1 &lt;&lt; shift));
            cvLine( image, cvPoint( pt.x - r, pt.y - r ),
                    cvPoint( pt.x + r, pt.y + r ), color, 1, line_type, shift );
            cvLine( image, cvPoint( pt.x - r, pt.y + r),
                    cvPoint( pt.x + r, pt.y - r), color, 1, line_type, shift );
            cvCircle( image, pt, r+(1&lt;&lt;shift), color, 1, line_type, shift );
        }
    }
    else
    {
        int x, y;
        CvPoint prev_pt = {0, 0};
        const int line_max = 7;
        static const CvScalar line_colors[line_max] =
        {
            {{0,0,255}},
            {{0,128,255}},
            {{0,200,200}},
            {{0,255,0}},
            {{200,200,0}},
            {{255,0,0}},
            {{255,0,255}}
        };

        for( y = 0, i = 0; y &lt; pattern_size.height; y++ )
        {
            CvScalar color = line_colors[y % line_max];
            if( cn == 1 )
                color = cvScalarAll(200);
            color.val[0] *= scale;
            color.val[1] *= scale;
            color.val[2] *= scale;
            color.val[3] *= scale;

            for( x = 0; x &lt; pattern_size.width; x++, i++ )
            {
                CvPoint pt;
                pt.x = cvRound(corners[i].x*(1 &lt;&lt; shift));
                pt.y = cvRound(corners[i].y*(1 &lt;&lt; shift));

                if( i != 0 )
                    cvLine( image, prev_pt, pt, color, 1, line_type, shift );

                cvLine( image, cvPoint(pt.x - r, pt.y - r),
                        cvPoint(pt.x + r, pt.y + r), color, 1, line_type, shift );
                cvLine( image, cvPoint(pt.x - r, pt.y + r),
                        cvPoint(pt.x + r, pt.y - r), color, 1, line_type, shift );
                cvCircle( image, pt, r+(1&lt;&lt;shift), color, 1, line_type, shift );
                prev_pt = pt;
            }
        }
    }
}

bool cv::findChessboardCorners( InputArray _image, Size patternSize,
                            OutputArray corners, int flags )
{
    int count = patternSize.area()*2;
    vector&lt;Point2f&gt; tmpcorners(count+1);
    Mat image = _image.getMat(); CvMat c_image = image;
    bool ok = cvFindChessboardCorners(&amp;c_image, patternSize,
        (CvPoint2D32f*)&amp;tmpcorners[0], &amp;count, flags ) &gt; 0;
    if( count &gt; 0 )
    {
        tmpcorners.resize(count);
        Mat(tmpcorners).copyTo(corners);
    }
    else
        corners.release();
    return ok;
}

namespace
{
int quiet_error(int /*status*/, const char* /*func_name*/,
                                       const char* /*err_msg*/, const char* /*file_name*/,
                                       int /*line*/, void* /*userdata*/ )
{
  return 0;
}
}

void cv::drawChessboardCorners( InputOutputArray _image, Size patternSize,
                            InputArray _corners,
                            bool patternWasFound )
{
    Mat corners = _corners.getMat();
    if( corners.empty() )
        return;
    Mat image = _image.getMat(); CvMat c_image = _image.getMat();
    int nelems = corners.checkVector(2, CV_32F, true);
    CV_Assert(nelems &gt;= 0);
    cvDrawChessboardCorners( &amp;c_image, patternSize, (CvPoint2D32f*)corners.data,
                             nelems, patternWasFound );
}

bool cv::findCirclesGrid( InputArray _image, Size patternSize,
                          OutputArray _centers, int flags, const Ptr&lt;FeatureDetector&gt; &amp;blobDetector )
{
    bool isAsymmetricGrid = (flags &amp; CALIB_CB_ASYMMETRIC_GRID) ? true : false;
    bool isSymmetricGrid  = (flags &amp; CALIB_CB_SYMMETRIC_GRID ) ? true : false;
    CV_Assert(isAsymmetricGrid ^ isSymmetricGrid);

    Mat image = _image.getMat();
    vector&lt;Point2f&gt; centers;

    vector&lt;KeyPoint&gt; keypoints;
    blobDetector-&gt;detect(image, keypoints);
    vector&lt;Point2f&gt; points;
    for (size_t i = 0; i &lt; keypoints.size(); i++)
    {
      points.push_back (keypoints[i].pt);
    }

    if(flags &amp; CALIB_CB_CLUSTERING)
    {
      CirclesGridClusterFinder circlesGridClusterFinder(isAsymmetricGrid);
      circlesGridClusterFinder.findGrid(points, patternSize, centers);
      Mat(centers).copyTo(_centers);
      return !centers.empty();
    }

    CirclesGridFinderParameters parameters;
    parameters.vertexPenalty = -0.6f;
    parameters.vertexGain = 1;
    parameters.existingVertexGain = 10000;
    parameters.edgeGain = 1;
    parameters.edgePenalty = -0.6f;

    if(flags &amp; CALIB_CB_ASYMMETRIC_GRID)
      parameters.gridType = CirclesGridFinderParameters::ASYMMETRIC_GRID;
    if(flags &amp; CALIB_CB_SYMMETRIC_GRID)
      parameters.gridType = CirclesGridFinderParameters::SYMMETRIC_GRID;

    const int attempts = 2;
    const size_t minHomographyPoints = 4;
    Mat H;
    for (int i = 0; i &lt; attempts; i++)
    {
      centers.clear();
      CirclesGridFinder boxFinder(patternSize, points, parameters);
      bool isFound = false;
#define BE_QUIET 1
#if BE_QUIET
      void* oldCbkData;
      ErrorCallback oldCbk = redirectError(quiet_error, 0, &amp;oldCbkData);
#endif
      try
      {
        isFound = boxFinder.findHoles();
      }
      catch (cv::Exception)
      {

      }
#if BE_QUIET
      redirectError(oldCbk, oldCbkData);
#endif
      if (isFound)
      {
        switch(parameters.gridType)
        {
          case CirclesGridFinderParameters::SYMMETRIC_GRID:
            boxFinder.getHoles(centers);
            break;
          case CirclesGridFinderParameters::ASYMMETRIC_GRID:
        boxFinder.getAsymmetricHoles(centers);
        break;
          default:
            CV_Error(CV_StsBadArg, &quot;Unkown pattern type&quot;);
        }

        if (i != 0)
        {
          Mat orgPointsMat;
          transform(centers, orgPointsMat, H.inv());
          convertPointsFromHomogeneous(orgPointsMat, centers);
        }
        Mat(centers).copyTo(_centers);
        return true;
      }

      boxFinder.getHoles(centers);
      if (i != attempts - 1)
      {
        if (centers.size() &lt; minHomographyPoints)
          break;
        H = CirclesGridFinder::rectifyGrid(boxFinder.getDetectedGridSize(), centers, points, points);
      }
    }
    Mat(centers).copyTo(_centers);
    return false;
}

/* End of file. */"><pre class="notranslate"><span class="pl-c"><span class="pl-c">//</span>M*//////////////////////////////////////////////////////////////////////////////////////</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>  By downloading, copying, installing or using the software you agree to this license.</span>
<span class="pl-c"><span class="pl-c">//</span>  If you do not agree to this license, do not download, install,</span>
<span class="pl-c"><span class="pl-c">//</span>  copy or use the software.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>                        Intel License Agreement</span>
<span class="pl-c"><span class="pl-c">//</span>                For Open Source Computer Vision Library</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> Copyright (C) 2000, Intel Corporation, all rights reserved.</span>
<span class="pl-c"><span class="pl-c">//</span> Third party copyrights are property of their respective owners.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> Redistribution and use in source and binary forms, with or without modification,</span>
<span class="pl-c"><span class="pl-c">//</span> are permitted provided that the following conditions are met:</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>   * Redistribution's of source code must retain the above copyright notice,</span>
<span class="pl-c"><span class="pl-c">//</span>     this list of conditions and the following disclaimer.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>   * Redistribution's in binary form must reproduce the above copyright notice,</span>
<span class="pl-c"><span class="pl-c">//</span>     this list of conditions and the following disclaimer in the documentation</span>
<span class="pl-c"><span class="pl-c">//</span>     and/or other materials provided with the distribution.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>   * The name of Intel Corporation may not be used to endorse or promote products</span>
<span class="pl-c"><span class="pl-c">//</span>     derived from this software without specific prior written permission.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> This software is provided by the copyright holders and contributors "as is" and</span>
<span class="pl-c"><span class="pl-c">//</span> any express or implied warranties, including, but not limited to, the implied</span>
<span class="pl-c"><span class="pl-c">//</span> warranties of merchantability and fitness for a particular purpose are disclaimed.</span>
<span class="pl-c"><span class="pl-c">//</span> In no event shall the Intel Corporation or contributors be liable for any direct,</span>
<span class="pl-c"><span class="pl-c">//</span> indirect, incidental, special, exemplary, or consequential damages</span>
<span class="pl-c"><span class="pl-c">//</span> (including, but not limited to, procurement of substitute goods or services;</span>
<span class="pl-c"><span class="pl-c">//</span> loss of use, data, or profits; or business interruption) however caused</span>
<span class="pl-c"><span class="pl-c">//</span> and on any theory of liability, whether in contract, strict liability,</span>
<span class="pl-c"><span class="pl-c">//</span> or tort (including negligence or otherwise) arising in any way out of</span>
<span class="pl-c"><span class="pl-c">//</span> the use of this software, even if advised of the possibility of such damage.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span>M*/</span>

<span class="pl-c"><span class="pl-c">/*</span>***********************************************************************************\</span>
<span class="pl-c">    This is improved variant of chessboard corner detection algorithm that</span>
<span class="pl-c">    uses a graph of connected quads. It is based on the code contributed</span>
<span class="pl-c">    by Vladimir Vezhnevets and Philip Gruebele.</span>
<span class="pl-c">    Here is the copyright notice from the original Vladimir's code:</span>
<span class="pl-c">    ===============================================================</span>
<span class="pl-c"></span>
<span class="pl-c">    The algorithms developed and implemented by Vezhnevets Vldimir</span>
<span class="pl-c">    aka Dead Moroz (vvp@graphics.cs.msu.ru)</span>
<span class="pl-c">    See http://graphics.cs.msu.su/en/research/calibration/opencv.html</span>
<span class="pl-c">    for detailed information.</span>
<span class="pl-c"></span>
<span class="pl-c">    Reliability additions and modifications made by Philip Gruebele.</span>
<span class="pl-c">    &lt;a href="mailto:pgruebele@cox.net"&gt;pgruebele@cox.net&lt;/a&gt;</span>
<span class="pl-c"></span>
<span class="pl-c">    Some further improvements for detection of partially ocluded boards at non-ideal</span>
<span class="pl-c">    lighting conditions have been made by Alex Bovyrin and Kurt Kolonige</span>
<span class="pl-c"></span>
<span class="pl-c">\***********************************************************************************<span class="pl-c">*/</span></span>

#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>precomp.hpp<span class="pl-pds">"</span></span>
#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>circlesgrid.hpp<span class="pl-pds">"</span></span>
#<span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">&lt;</span>stdarg.h<span class="pl-pds">&gt;</span></span>

<span class="pl-c"><span class="pl-c">//</span>#define ENABLE_TRIM_COL_ROW</span>

<span class="pl-c"><span class="pl-c">//</span>#define DEBUG_CHESSBOARD</span>
#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
#  <span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>opencv2/opencv_modules.hpp<span class="pl-pds">"</span></span>
#  <span class="pl-k">ifdef</span> HAVE_OPENCV_HIGHGUI
#    <span class="pl-k">include</span> <span class="pl-s"><span class="pl-pds">"</span>opencv2/highgui/highgui.hpp<span class="pl-pds">"</span></span>
#  <span class="pl-k">else</span>
#    <span class="pl-k">undef</span> DEBUG_CHESSBOARD
#  <span class="pl-k">endif</span>
#<span class="pl-k">endif</span>
#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">PRINTF</span>( <span class="pl-k">const</span> <span class="pl-k">char</span>* fmt, ... )
{
    <span class="pl-c1">va_list</span> args;
    <span class="pl-c1">va_start</span>(args, fmt);
    <span class="pl-k">return</span> <span class="pl-c1">vprintf</span>(fmt, args);
}
#<span class="pl-k">else</span>
<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">PRINTF</span>( <span class="pl-k">const</span> <span class="pl-k">char</span>*, ... )
{
    <span class="pl-k">return</span> <span class="pl-c1">0</span>;
}
#<span class="pl-k">endif</span>


<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>
<span class="pl-c"><span class="pl-c">//</span> Implementation for the enhanced calibration object detection</span>
<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

#<span class="pl-k">define</span> <span class="pl-en">MAX_CONTOUR_APPROX</span>  <span class="pl-c1">7</span>

<span class="pl-k">struct</span> <span class="pl-en">CvContourEx</span>
{
    <span class="pl-en">CV_CONTOUR_FIELDS</span>()
    <span class="pl-k">int</span> counter;
};

<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

<span class="pl-c"><span class="pl-c">//</span>/ Corner info structure</span>
<span class="pl-c"><span class="pl-c">/*</span>* This structure stores information about the chessboard corner.<span class="pl-c">*/</span></span>
<span class="pl-k">struct</span> <span class="pl-en">CvCBCorner</span>
{
    CvPoint2D32f pt; <span class="pl-c"><span class="pl-c">//</span> Coordinates of the corner</span>
    <span class="pl-k">int</span> row;         <span class="pl-c"><span class="pl-c">//</span> Board row index</span>
    <span class="pl-k">int</span> count;       <span class="pl-c"><span class="pl-c">//</span> Number of neighbor corners</span>
    <span class="pl-k">struct</span> <span class="pl-en">CvCBCorner</span>* neighbors[<span class="pl-c1">4</span>]; <span class="pl-c"><span class="pl-c">//</span> Neighbor corners</span>

    <span class="pl-k">float</span> <span class="pl-en">meanDist</span>(<span class="pl-k">int</span> *_n) <span class="pl-k">const</span>
    {
        <span class="pl-k">float</span> sum = <span class="pl-c1">0</span>;
        <span class="pl-k">int</span> n = <span class="pl-c1">0</span>;
        <span class="pl-k">for</span>( <span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
        {
            <span class="pl-k">if</span>( neighbors[i] )
            {
                <span class="pl-k">float</span> dx = neighbors[i]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> - pt.<span class="pl-smi">x</span>;
                <span class="pl-k">float</span> dy = neighbors[i]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> - pt.<span class="pl-smi">y</span>;
                sum += <span class="pl-c1">sqrt</span>(dx*dx + dy*dy);
                n++;
            }
        }
        <span class="pl-k">if</span>(_n)
            *_n = n;
        <span class="pl-k">return</span> sum/<span class="pl-c1">MAX</span>(n,<span class="pl-c1">1</span>);
    }
};

<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>
<span class="pl-c"><span class="pl-c">//</span>/ Quadrangle contour info structure</span>
<span class="pl-c"><span class="pl-c">/*</span>* This structure stores information about the chessboard quadrange.<span class="pl-c">*/</span></span>
<span class="pl-k">struct</span> <span class="pl-en">CvCBQuad</span>
{
    <span class="pl-k">int</span> count;      <span class="pl-c"><span class="pl-c">//</span> Number of quad neighbors</span>
    <span class="pl-k">int</span> group_idx;  <span class="pl-c"><span class="pl-c">//</span> quad group ID</span>
    <span class="pl-k">int</span> row, col;   <span class="pl-c"><span class="pl-c">//</span> row and column of this quad</span>
    <span class="pl-k">bool</span> ordered;   <span class="pl-c"><span class="pl-c">//</span> true if corners/neighbors are ordered counter-clockwise</span>
    <span class="pl-k">float</span> edge_len; <span class="pl-c"><span class="pl-c">//</span> quad edge len, in pix^2</span>
    <span class="pl-c"><span class="pl-c">//</span> neighbors and corners are synced, i.e., neighbor 0 shares corner 0</span>
    CvCBCorner *corners[<span class="pl-c1">4</span>]; <span class="pl-c"><span class="pl-c">//</span> Coordinates of quad corners</span>
    <span class="pl-k">struct</span> <span class="pl-en">CvCBQuad</span> *neighbors[<span class="pl-c1">4</span>]; <span class="pl-c"><span class="pl-c">//</span> Pointers of quad neighbors</span>
};

<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

<span class="pl-c"><span class="pl-c">//</span>static CvMat* debug_img = 0;</span>

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvGenerateQuads</span>( CvCBQuad **quads, CvCBCorner **corners,
                             CvMemStorage *storage, CvMat *image, <span class="pl-k">int</span> flags, <span class="pl-k">int</span> *max_quad_buf_size);

<span class="pl-c"><span class="pl-c">/*</span>static int</span>
<span class="pl-c">icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners,</span>
<span class="pl-c">    CvMemStorage *storage, CvMat *image, CvMat *thresh_img, int dilation, int flags );<span class="pl-c">*/</span></span>

<span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">icvFindQuadNeighbors</span>( CvCBQuad *quads, <span class="pl-k">int</span> quad_count );

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvFindConnectedQuads</span>( CvCBQuad *quads, <span class="pl-k">int</span> quad_count,
                                  CvCBQuad **quad_group, <span class="pl-k">int</span> group_idx,
                                  CvMemStorage* storage );

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvCheckQuadGroup</span>( CvCBQuad **quad_group, <span class="pl-k">int</span> count,
                              CvCBCorner **out_corners, CvSize pattern_size );

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvCleanFoundConnectedQuads</span>( <span class="pl-k">int</span> quad_count,
                CvCBQuad **quads, CvSize pattern_size );

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvOrderFoundConnectedQuads</span>( <span class="pl-k">int</span> quad_count, CvCBQuad **quads,
           <span class="pl-k">int</span> *all_count, CvCBQuad **all_quads, CvCBCorner **corners,
           CvSize pattern_size, <span class="pl-k">int</span> max_quad_buf_size, CvMemStorage* storage );

<span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">icvOrderQuad</span>(CvCBQuad *quad, CvCBCorner *corner, <span class="pl-k">int</span> common);

#<span class="pl-k">ifdef</span> ENABLE_TRIM_COL_ROW
<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvTrimCol</span>(CvCBQuad **quads, <span class="pl-k">int</span> count, <span class="pl-k">int</span> col, <span class="pl-k">int</span> dir);

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvTrimRow</span>(CvCBQuad **quads, <span class="pl-k">int</span> count, <span class="pl-k">int</span> row, <span class="pl-k">int</span> dir);
#<span class="pl-k">endif</span>

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvAddOuterQuad</span>(CvCBQuad *quad, CvCBQuad **quads, <span class="pl-k">int</span> quad_count,
                    CvCBQuad **all_quads, <span class="pl-k">int</span> all_count, CvCBCorner **corners, <span class="pl-k">int</span> max_quad_buf_size);

<span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">icvRemoveQuadFromGroup</span>(CvCBQuad **quads, <span class="pl-k">int</span> count, CvCBQuad *q0);

<span class="pl-k">static</span> <span class="pl-k">int</span> <span class="pl-en">icvCheckBoardMonotony</span>( CvPoint2D32f* corners, CvSize pattern_size );

#<span class="pl-k">if</span> <span class="pl-c1">0</span>
static void
icvCalcAffineTranf2D32f(CvPoint2D32f* pts1, CvPoint2D32f* pts2, int count, CvMat* affine_trans)
{
    int i, j;
    int real_count = 0;
    for( j = 0; j &lt; count; j++ )
    {
        if( pts1[j].x &gt;= 0 ) real_count++;
    }
    if(real_count &lt; 3) return;
    cv::Ptr&lt;CvMat&gt; xy = cvCreateMat( 2*real_count, 6, CV_32FC1 );
    cv::Ptr&lt;CvMat&gt; uv = cvCreateMat( 2*real_count, 1, CV_32FC1 );
    //estimate affine transfromation
    for( i = 0, j = 0; j &lt; count; j++ )
    {
        if( pts1[j].x &gt;= 0 )
        {
            CV_MAT_ELEM( *xy, float, i*2+1, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 0 ) = pts2[j].x;
            CV_MAT_ELEM( *xy, float, i*2+1, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 1 ) = pts2[j].y;
            CV_MAT_ELEM( *xy, float, i*2, 2 ) = CV_MAT_ELEM( *xy, float, i*2, 3 ) = CV_MAT_ELEM( *xy, float, i*2, 5 ) = \
                CV_MAT_ELEM( *xy, float, i*2+1, 0 ) = CV_MAT_ELEM( *xy, float, i*2+1, 1 ) = CV_MAT_ELEM( *xy, float, i*2+1, 4 ) = 0;
            CV_MAT_ELEM( *xy, float, i*2, 4 ) = CV_MAT_ELEM( *xy, float, i*2+1, 5 ) = 1;
            CV_MAT_ELEM( *uv, float, i*2, 0 ) = pts1[j].x;
            CV_MAT_ELEM( *uv, float, i*2+1, 0 ) = pts1[j].y;
            i++;
        }
    }

    cvSolve( xy, uv, affine_trans, CV_SVD );
}
#<span class="pl-k">endif</span>

CV_IMPL
<span class="pl-k">int</span> <span class="pl-en">cvFindChessboardCorners</span>( <span class="pl-k">const</span> <span class="pl-k">void</span>* arr, CvSize pattern_size,
                             CvPoint2D32f* out_corners, <span class="pl-k">int</span>* out_corner_count,
                             <span class="pl-k">int</span> flags )
{
    <span class="pl-k">int</span> found = <span class="pl-c1">0</span>;
    CvCBQuad *quads = <span class="pl-c1">0</span>, **quad_group = <span class="pl-c1">0</span>;
    CvCBCorner *corners = <span class="pl-c1">0</span>, **corner_group = <span class="pl-c1">0</span>;

    <span class="pl-k">try</span>
    {
    <span class="pl-k">int</span> k = <span class="pl-c1">0</span>;
    <span class="pl-k">const</span> <span class="pl-k">int</span> min_dilations = <span class="pl-c1">0</span>;
    <span class="pl-k">const</span> <span class="pl-k">int</span> max_dilations = <span class="pl-c1">7</span>;
    cv::<span class="pl-c1">Ptr</span>&lt;CvMat&gt; norm_img, thresh_img;
#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
    cv::<span class="pl-c1">Ptr</span>&lt;IplImage&gt; dbg_img;
    cv::<span class="pl-c1">Ptr</span>&lt;IplImage&gt; dbg1_img;
    cv::<span class="pl-c1">Ptr</span>&lt;IplImage&gt; dbg2_img;
#<span class="pl-k">endif</span>
    cv::<span class="pl-c1">Ptr</span>&lt;CvMemStorage&gt; storage;

    CvMat stub, *img = (CvMat*)arr;

    <span class="pl-k">int</span> expected_corners_num = (pattern_size.<span class="pl-smi">width</span>/<span class="pl-c1">2</span>+<span class="pl-c1">1</span>)*(pattern_size.<span class="pl-smi">height</span>/<span class="pl-c1">2</span>+<span class="pl-c1">1</span>);

    <span class="pl-k">int</span> prev_sqr_size = <span class="pl-c1">0</span>;

    <span class="pl-k">if</span>( out_corner_count )
        *out_corner_count = <span class="pl-c1">0</span>;

    IplImage _img;
    <span class="pl-k">int</span> check_chessboard_result;
    <span class="pl-k">int</span> quad_count = <span class="pl-c1">0</span>, group_idx = <span class="pl-c1">0</span>, dilations = <span class="pl-c1">0</span>;

    img = <span class="pl-c1">cvGetMat</span>( img, &amp;stub );
    <span class="pl-c"><span class="pl-c">//</span>debug_img = img;</span>

    <span class="pl-k">if</span>( <span class="pl-c1">CV_MAT_DEPTH</span>( img-&gt;<span class="pl-smi">type</span> ) != CV_8U || <span class="pl-c1">CV_MAT_CN</span>( img-&gt;<span class="pl-smi">type</span> ) == <span class="pl-c1">2</span> )
        <span class="pl-c1">CV_Error</span>( CV_StsUnsupportedFormat, <span class="pl-s"><span class="pl-pds">"</span>Only 8-bit grayscale or color images are supported<span class="pl-pds">"</span></span> );

    <span class="pl-k">if</span>( pattern_size.<span class="pl-smi">width</span> &lt;= <span class="pl-c1">2</span> || pattern_size.<span class="pl-smi">height</span> &lt;= <span class="pl-c1">2</span> )
        <span class="pl-c1">CV_Error</span>( CV_StsOutOfRange, <span class="pl-s"><span class="pl-pds">"</span>Both width and height of the pattern should have bigger than 2<span class="pl-pds">"</span></span> );

    <span class="pl-k">if</span>( !out_corners )
        <span class="pl-c1">CV_Error</span>( CV_StsNullPtr, <span class="pl-s"><span class="pl-pds">"</span>Null pointer to corners<span class="pl-pds">"</span></span> );

    storage = <span class="pl-c1">cvCreateMemStorage</span>(<span class="pl-c1">0</span>);
    thresh_img = <span class="pl-c1">cvCreateMat</span>( img-&gt;<span class="pl-smi">rows</span>, img-&gt;<span class="pl-smi">cols</span>, CV_8UC1 );

#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
    dbg_img = <span class="pl-c1">cvCreateImage</span>(<span class="pl-c1">cvGetSize</span>(img), IPL_DEPTH_8U, <span class="pl-c1">3</span> );
    dbg1_img = <span class="pl-c1">cvCreateImage</span>(<span class="pl-c1">cvGetSize</span>(img), IPL_DEPTH_8U, <span class="pl-c1">3</span> );
    dbg2_img = <span class="pl-c1">cvCreateImage</span>(<span class="pl-c1">cvGetSize</span>(img), IPL_DEPTH_8U, <span class="pl-c1">3</span> );
#<span class="pl-k">endif</span>

    <span class="pl-k">if</span>( <span class="pl-c1">CV_MAT_CN</span>(img-&gt;<span class="pl-smi">type</span>) != <span class="pl-c1">1</span> || (flags &amp; CV_CALIB_CB_NORMALIZE_IMAGE) )
    {
        <span class="pl-c"><span class="pl-c">//</span> equalize the input image histogram -</span>
        <span class="pl-c"><span class="pl-c">//</span> that should make the contrast between "black" and "white" areas big enough</span>
        norm_img = <span class="pl-c1">cvCreateMat</span>( img-&gt;<span class="pl-smi">rows</span>, img-&gt;<span class="pl-smi">cols</span>, CV_8UC1 );

        <span class="pl-k">if</span>( <span class="pl-c1">CV_MAT_CN</span>(img-&gt;<span class="pl-smi">type</span>) != <span class="pl-c1">1</span> )
        {
            <span class="pl-c1">cvCvtColor</span>( img, norm_img, CV_BGR2GRAY );
            img = norm_img;
        }

        <span class="pl-k">if</span>( flags &amp; CV_CALIB_CB_NORMALIZE_IMAGE )
        {
            <span class="pl-c1">cvEqualizeHist</span>( img, norm_img );
            img = norm_img;
        }
    }

    <span class="pl-k">if</span>( flags &amp; CV_CALIB_CB_FAST_CHECK)
    {
        <span class="pl-c1">cvGetImage</span>(img, &amp;_img);
        check_chessboard_result = <span class="pl-c1">cvCheckChessboard</span>(&amp;_img, pattern_size);
        <span class="pl-k">if</span>(check_chessboard_result &lt;= <span class="pl-c1">0</span>)
        {
            <span class="pl-k">return</span> <span class="pl-c1">0</span>;
        }
    }

    <span class="pl-c"><span class="pl-c">//</span> Try our standard "1" dilation, but if the pattern is not found, iterate the whole procedure with higher dilations.</span>
    <span class="pl-c"><span class="pl-c">//</span> This is necessary because some squares simply do not separate properly with a single dilation.  However,</span>
    <span class="pl-c"><span class="pl-c">//</span> we want to use the minimum number of dilations possible since dilations cause the squares to become smaller,</span>
    <span class="pl-c"><span class="pl-c">//</span> making it difficult to detect smaller squares.</span>
    <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">6</span>; k++ )
    {
        <span class="pl-k">int</span> max_quad_buf_size = <span class="pl-c1">0</span>;
        <span class="pl-k">for</span>( dilations = min_dilations; dilations &lt;= max_dilations; dilations++ )
        {
            <span class="pl-k">if</span> (found)
                <span class="pl-k">break</span>;      <span class="pl-c"><span class="pl-c">//</span> already found it</span>

            <span class="pl-c1">cvFree</span>(&amp;quads);
            <span class="pl-c1">cvFree</span>(&amp;corners);

            <span class="pl-c"><span class="pl-c">/*</span>if( k == 1 )</span>
<span class="pl-c">            {</span>
<span class="pl-c">                //Pattern was not found using binarization</span>
<span class="pl-c">                // Run multi-level quads extraction</span>
<span class="pl-c">                // In case one-level binarization did not give enough number of quads</span>
<span class="pl-c">                CV_CALL( quad_count = icvGenerateQuadsEx( &amp;quads, &amp;corners, storage, img, thresh_img, dilations, flags ));</span>
<span class="pl-c">                PRINTF("EX quad count: %d/%d\n", quad_count, expected_corners_num);</span>
<span class="pl-c">            }</span>
<span class="pl-c">            else<span class="pl-c">*/</span></span>
            {
                <span class="pl-c"><span class="pl-c">//</span> convert the input grayscale image to binary (black-n-white)</span>
                <span class="pl-k">if</span>( flags &amp; CV_CALIB_CB_ADAPTIVE_THRESH )
                {
                    <span class="pl-k">int</span> block_size = <span class="pl-c1">cvRound</span>(prev_sqr_size == <span class="pl-c1">0</span> ?
                        <span class="pl-c1">MIN</span>(img-&gt;<span class="pl-smi">cols</span>,img-&gt;<span class="pl-smi">rows</span>)*(k%<span class="pl-c1">2</span> == <span class="pl-c1">0</span> ? <span class="pl-c1">0.2</span> : <span class="pl-c1">0.1</span>): prev_sqr_size*<span class="pl-c1">2</span>)|<span class="pl-c1">1</span>;

                    <span class="pl-c"><span class="pl-c">//</span> convert to binary</span>
                    <span class="pl-c1">cvAdaptiveThreshold</span>( img, thresh_img, <span class="pl-c1">255</span>,
                        CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, block_size, (k/<span class="pl-c1">2</span>)*<span class="pl-c1">5</span> );
                    <span class="pl-k">if</span> (dilations &gt; <span class="pl-c1">0</span>)
                        <span class="pl-c1">cvDilate</span>( thresh_img, thresh_img, <span class="pl-c1">0</span>, dilations-<span class="pl-c1">1</span> );
                }
                <span class="pl-k">else</span>
                {
                    <span class="pl-c"><span class="pl-c">//</span> Make dilation before the thresholding.</span>
                    <span class="pl-c"><span class="pl-c">//</span> It splits chessboard corners</span>
                    <span class="pl-c"><span class="pl-c">//</span>cvDilate( img, thresh_img, 0, 1 );</span>

                    <span class="pl-c"><span class="pl-c">//</span> empiric threshold level</span>
                    <span class="pl-k">double</span> mean = <span class="pl-c1">cvAvg</span>( img ).<span class="pl-smi">val</span>[<span class="pl-c1">0</span>];
                    <span class="pl-k">int</span> thresh_level = <span class="pl-c1">cvRound</span>( mean - <span class="pl-c1">10</span> );
                    thresh_level = <span class="pl-c1">MAX</span>( thresh_level, <span class="pl-c1">10</span> );

                    <span class="pl-c1">cvThreshold</span>( img, thresh_img, thresh_level, <span class="pl-c1">255</span>, CV_THRESH_BINARY );
                    <span class="pl-c1">cvDilate</span>( thresh_img, thresh_img, <span class="pl-c1">0</span>, dilations );
                }

#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
                <span class="pl-c1">cvCvtColor</span>(thresh_img,dbg_img,CV_GRAY2BGR);
#<span class="pl-k">endif</span>

                <span class="pl-c"><span class="pl-c">//</span> So we can find rectangles that go to the edge, we draw a white line around the image edge.</span>
                <span class="pl-c"><span class="pl-c">//</span> Otherwise FindContours will miss those clipped rectangle contours.</span>
                <span class="pl-c"><span class="pl-c">//</span> The border color will be the image mean, because otherwise we risk screwing up filters like cvSmooth()...</span>
                <span class="pl-c1">cvRectangle</span>( thresh_img, <span class="pl-c1">cvPoint</span>(<span class="pl-c1">0</span>,<span class="pl-c1">0</span>), <span class="pl-c1">cvPoint</span>(thresh_img-&gt;<span class="pl-smi">cols</span>-<span class="pl-c1">1</span>,
                    thresh_img-&gt;<span class="pl-smi">rows</span>-<span class="pl-c1">1</span>), <span class="pl-c1">CV_RGB</span>(<span class="pl-c1">255</span>,<span class="pl-c1">255</span>,<span class="pl-c1">255</span>), <span class="pl-c1">3</span>, <span class="pl-c1">8</span>);

                quad_count = <span class="pl-c1">icvGenerateQuads</span>( &amp;quads, &amp;corners, storage, thresh_img, flags, &amp;max_quad_buf_size);

                <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Quad count: %d/%d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, quad_count, expected_corners_num);
            }


#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
            <span class="pl-c1">cvCopy</span>(dbg_img, dbg1_img);
            <span class="pl-c1">cvNamedWindow</span>(<span class="pl-s"><span class="pl-pds">"</span>all_quads<span class="pl-pds">"</span></span>, <span class="pl-c1">1</span>);
            <span class="pl-c"><span class="pl-c">//</span> copy corners to temp array</span>
            <span class="pl-k">for</span>(<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; quad_count; i++ )
            {
                <span class="pl-k">for</span> (<span class="pl-k">int</span> k=<span class="pl-c1">0</span>; k&lt;<span class="pl-c1">4</span>; k++)
                {
                    CvPoint2D32f pt1, pt2;
                    CvScalar color = <span class="pl-c1">CV_RGB</span>(<span class="pl-c1">30</span>,<span class="pl-c1">255</span>,<span class="pl-c1">30</span>);
                    pt1 = quads[i].<span class="pl-smi">corners</span>[k]-&gt;<span class="pl-smi">pt</span>;
                    pt2 = quads[i].<span class="pl-smi">corners</span>[(k+<span class="pl-c1">1</span>)%<span class="pl-c1">4</span>]-&gt;<span class="pl-smi">pt</span>;
                    pt2.<span class="pl-smi">x</span> = (pt1.<span class="pl-smi">x</span> + pt2.<span class="pl-smi">x</span>)/<span class="pl-c1">2</span>;
                    pt2.<span class="pl-smi">y</span> = (pt1.<span class="pl-smi">y</span> + pt2.<span class="pl-smi">y</span>)/<span class="pl-c1">2</span>;
                    <span class="pl-k">if</span> (k&gt;<span class="pl-c1">0</span>)
                        color = <span class="pl-c1">CV_RGB</span>(<span class="pl-c1">200</span>,<span class="pl-c1">200</span>,<span class="pl-c1">0</span>);
                    <span class="pl-c1">cvLine</span>( dbg1_img, <span class="pl-c1">cvPointFrom32f</span>(pt1), <span class="pl-c1">cvPointFrom32f</span>(pt2), color, <span class="pl-c1">3</span>, <span class="pl-c1">8</span>);
                }
            }


            <span class="pl-c1">cvShowImage</span>(<span class="pl-s"><span class="pl-pds">"</span>all_quads<span class="pl-pds">"</span></span>, (IplImage*)dbg1_img);
            <span class="pl-c1">cvWaitKey</span>();
#<span class="pl-k">endif</span>

            <span class="pl-k">if</span>( quad_count &lt;= <span class="pl-c1">0</span> )
                <span class="pl-k">continue</span>;

            <span class="pl-c"><span class="pl-c">//</span> Find quad's neighbors</span>
            <span class="pl-c1">icvFindQuadNeighbors</span>( quads, quad_count );

            <span class="pl-c"><span class="pl-c">//</span> allocate extra for adding in icvOrderFoundQuads</span>
            <span class="pl-c1">cvFree</span>(&amp;quad_group);
            <span class="pl-c1">cvFree</span>(&amp;corner_group);
            quad_group = (CvCBQuad**)<span class="pl-c1">cvAlloc</span>( <span class="pl-k">sizeof</span>(quad_group[<span class="pl-c1">0</span>]) * max_quad_buf_size);
            corner_group = (CvCBCorner**)<span class="pl-c1">cvAlloc</span>( <span class="pl-k">sizeof</span>(corner_group[<span class="pl-c1">0</span>]) * max_quad_buf_size * <span class="pl-c1">4</span> );

            <span class="pl-k">for</span>( group_idx = <span class="pl-c1">0</span>; ; group_idx++ )
            {
                <span class="pl-k">int</span> count = <span class="pl-c1">0</span>;
                count = <span class="pl-c1">icvFindConnectedQuads</span>( quads, quad_count, quad_group, group_idx, storage );

                <span class="pl-k">int</span> icount = count;
                <span class="pl-k">if</span>( count == <span class="pl-c1">0</span> )
                    <span class="pl-k">break</span>;

                <span class="pl-c"><span class="pl-c">//</span> order the quad corners globally</span>
                <span class="pl-c"><span class="pl-c">//</span> maybe delete or add some</span>
                <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Starting ordering of inner quads<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
                count = <span class="pl-c1">icvOrderFoundConnectedQuads</span>(count, quad_group, &amp;quad_count, &amp;quads, &amp;corners,
                    pattern_size, max_quad_buf_size, storage );
                <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Orig count: %d  After ordering: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, icount, count);


#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
                <span class="pl-c1">cvCopy</span>(dbg_img,dbg2_img);
                <span class="pl-c1">cvNamedWindow</span>(<span class="pl-s"><span class="pl-pds">"</span>connected_group<span class="pl-pds">"</span></span>, <span class="pl-c1">1</span>);
                <span class="pl-c"><span class="pl-c">//</span> copy corners to temp array</span>
                <span class="pl-k">for</span>(<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; quad_count; i++ )
                {
                    <span class="pl-k">if</span> (quads[i].<span class="pl-smi">group_idx</span> == group_idx)
                        <span class="pl-k">for</span> (<span class="pl-k">int</span> k=<span class="pl-c1">0</span>; k&lt;<span class="pl-c1">4</span>; k++)
                        {
                            CvPoint2D32f pt1, pt2;
                            CvScalar color = <span class="pl-c1">CV_RGB</span>(<span class="pl-c1">30</span>,<span class="pl-c1">255</span>,<span class="pl-c1">30</span>);
                            <span class="pl-k">if</span> (quads[i].<span class="pl-smi">ordered</span>)
                                color = <span class="pl-c1">CV_RGB</span>(<span class="pl-c1">255</span>,<span class="pl-c1">30</span>,<span class="pl-c1">30</span>);
                            pt1 = quads[i].<span class="pl-smi">corners</span>[k]-&gt;<span class="pl-smi">pt</span>;
                            pt2 = quads[i].<span class="pl-smi">corners</span>[(k+<span class="pl-c1">1</span>)%<span class="pl-c1">4</span>]-&gt;<span class="pl-smi">pt</span>;
                            pt2.<span class="pl-smi">x</span> = (pt1.<span class="pl-smi">x</span> + pt2.<span class="pl-smi">x</span>)/<span class="pl-c1">2</span>;
                            pt2.<span class="pl-smi">y</span> = (pt1.<span class="pl-smi">y</span> + pt2.<span class="pl-smi">y</span>)/<span class="pl-c1">2</span>;
                            <span class="pl-k">if</span> (k&gt;<span class="pl-c1">0</span>)
                                color = <span class="pl-c1">CV_RGB</span>(<span class="pl-c1">200</span>,<span class="pl-c1">200</span>,<span class="pl-c1">0</span>);
                            <span class="pl-c1">cvLine</span>( dbg2_img, <span class="pl-c1">cvPointFrom32f</span>(pt1), <span class="pl-c1">cvPointFrom32f</span>(pt2), color, <span class="pl-c1">3</span>, <span class="pl-c1">8</span>);
                        }
                }
                <span class="pl-c1">cvShowImage</span>(<span class="pl-s"><span class="pl-pds">"</span>connected_group<span class="pl-pds">"</span></span>, (IplImage*)dbg2_img);
                <span class="pl-c1">cvWaitKey</span>();
#<span class="pl-k">endif</span>

                <span class="pl-k">if</span> (count == <span class="pl-c1">0</span>)
                    <span class="pl-k">continue</span>;       <span class="pl-c"><span class="pl-c">//</span> haven't found inner quads</span>


                <span class="pl-c"><span class="pl-c">//</span> If count is more than it should be, this will remove those quads</span>
                <span class="pl-c"><span class="pl-c">//</span> which cause maximum deviation from a nice square pattern.</span>
                count = <span class="pl-c1">icvCleanFoundConnectedQuads</span>( count, quad_group, pattern_size );
                <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Connected group: %d  orig count: %d cleaned: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, group_idx, icount, count);

                count = <span class="pl-c1">icvCheckQuadGroup</span>( quad_group, count, corner_group, pattern_size );
                <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Connected group: %d  count: %d  cleaned: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, group_idx, icount, count);

                {
                <span class="pl-k">int</span> n = count &gt; <span class="pl-c1">0</span> ? pattern_size.<span class="pl-smi">width</span> * pattern_size.<span class="pl-smi">height</span> : -count;
                n = <span class="pl-c1">MIN</span>( n, pattern_size.<span class="pl-smi">width</span> * pattern_size.<span class="pl-smi">height</span> );
                <span class="pl-k">float</span> sum_dist = <span class="pl-c1">0</span>;
                <span class="pl-k">int</span> total = <span class="pl-c1">0</span>;

                <span class="pl-k">for</span>(<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; n; i++ )
                {
                    <span class="pl-k">int</span> ni = <span class="pl-c1">0</span>;
                    <span class="pl-k">float</span> avgi = corner_group[i]-&gt;<span class="pl-c1">meanDist</span>(&amp;ni);
                    sum_dist += avgi*ni;
                    total += ni;
                }
                prev_sqr_size = <span class="pl-c1">cvRound</span>(sum_dist/<span class="pl-c1">MAX</span>(total, <span class="pl-c1">1</span>));

                <span class="pl-k">if</span>( count &gt; <span class="pl-c1">0</span> || (out_corner_count &amp;&amp; -count &gt; *out_corner_count) )
                {
                    <span class="pl-c"><span class="pl-c">//</span> copy corners to output array</span>
                    <span class="pl-k">for</span>(<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; n; i++ )
                        out_corners[i] = corner_group[i]-&gt;<span class="pl-smi">pt</span>;

                    <span class="pl-k">if</span>( out_corner_count )
                        *out_corner_count = n;

                    <span class="pl-k">if</span>( count == pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span> &amp;&amp;
                        <span class="pl-c1">icvCheckBoardMonotony</span>( out_corners, pattern_size ))
                    {
                        found = <span class="pl-c1">1</span>;
                        <span class="pl-k">break</span>;
                    }
                }
                }
            }
        }<span class="pl-c"><span class="pl-c">//</span>dilations</span>
    }<span class="pl-c"><span class="pl-c">//</span></span>

    <span class="pl-k">if</span>( found )
        found = <span class="pl-c1">icvCheckBoardMonotony</span>( out_corners, pattern_size );

    <span class="pl-c"><span class="pl-c">//</span> check that none of the found corners is too close to the image boundary</span>
    <span class="pl-k">if</span>( found )
    {
        <span class="pl-k">const</span> <span class="pl-k">int</span> BORDER = <span class="pl-c1">8</span>;
        <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span>; k++ )
        {
            <span class="pl-k">if</span>( out_corners[k].<span class="pl-smi">x</span> &lt;= BORDER || out_corners[k].<span class="pl-smi">x</span> &gt; img-&gt;<span class="pl-smi">cols</span> - BORDER ||
                out_corners[k].<span class="pl-smi">y</span> &lt;= BORDER || out_corners[k].<span class="pl-smi">y</span> &gt; img-&gt;<span class="pl-smi">rows</span> - BORDER )
                <span class="pl-k">break</span>;
        }

        found = k == pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span>;
    }

    <span class="pl-k">if</span>( found &amp;&amp; pattern_size.<span class="pl-smi">height</span> % <span class="pl-c1">2</span> == <span class="pl-c1">0</span> &amp;&amp; pattern_size.<span class="pl-smi">width</span> % <span class="pl-c1">2</span> == <span class="pl-c1">0</span> )
    {
        <span class="pl-k">int</span> last_row = (pattern_size.<span class="pl-smi">height</span>-<span class="pl-c1">1</span>)*pattern_size.<span class="pl-smi">width</span>;
        <span class="pl-k">double</span> dy0 = out_corners[last_row].<span class="pl-smi">y</span> - out_corners[<span class="pl-c1">0</span>].<span class="pl-smi">y</span>;
        <span class="pl-k">if</span>( dy0 &lt; <span class="pl-c1">0</span> )
        {
            <span class="pl-k">int</span> n = pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span>;
            <span class="pl-k">for</span>(<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; n/<span class="pl-c1">2</span>; i++ )
            {
                CvPoint2D32f temp;
                <span class="pl-c1">CV_SWAP</span>(out_corners[i], out_corners[n-i-<span class="pl-c1">1</span>], temp);
            }
        }
    }

    <span class="pl-k">if</span>( found )
    {
        cv::<span class="pl-c1">Ptr</span>&lt;CvMat&gt; gray;
        <span class="pl-k">if</span>( <span class="pl-c1">CV_MAT_CN</span>(img-&gt;<span class="pl-smi">type</span>) != <span class="pl-c1">1</span> )
        {
            gray = <span class="pl-c1">cvCreateMat</span>(img-&gt;<span class="pl-smi">rows</span>, img-&gt;<span class="pl-smi">cols</span>, CV_8UC1);
            <span class="pl-c1">cvCvtColor</span>(img, gray, CV_BGR2GRAY);
        }
        <span class="pl-k">else</span>
        {
            gray = <span class="pl-c1">cvCloneMat</span>(img);
        }
        <span class="pl-k">int</span> wsize = <span class="pl-c1">2</span>;
        <span class="pl-c1">cvFindCornerSubPix</span>( gray, out_corners, pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span>,
            <span class="pl-c1">cvSize</span>(wsize, wsize), <span class="pl-c1">cvSize</span>(-<span class="pl-c1">1</span>,-<span class="pl-c1">1</span>), <span class="pl-c1">cvTermCriteria</span>(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, <span class="pl-c1">15</span>, <span class="pl-c1">0.1</span>));
    }
    }
    <span class="pl-k">catch</span>(...)
    {
        <span class="pl-c1">cvFree</span>(&amp;quads);
        <span class="pl-c1">cvFree</span>(&amp;corners);
        <span class="pl-c1">cvFree</span>(&amp;quad_group);
        <span class="pl-c1">cvFree</span>(&amp;corner_group);
        <span class="pl-k">throw</span>;
    }

    <span class="pl-c1">cvFree</span>(&amp;quads);
    <span class="pl-c1">cvFree</span>(&amp;corners);
    <span class="pl-c1">cvFree</span>(&amp;quad_group);
    <span class="pl-c1">cvFree</span>(&amp;corner_group);
    <span class="pl-k">return</span> found;
}

<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> Checks that each board row and column is pretty much monotonous curve:</span>
<span class="pl-c"><span class="pl-c">//</span> It analyzes each row and each column of the chessboard as following:</span>
<span class="pl-c"><span class="pl-c">//</span>    for each corner c lying between end points in the same row/column it checks that</span>
<span class="pl-c"><span class="pl-c">//</span>    the point projection to the line segment (a,b) is lying between projections</span>
<span class="pl-c"><span class="pl-c">//</span>    of the neighbor corners in the same row/column.</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> This function has been created as temporary workaround for the bug in current implementation</span>
<span class="pl-c"><span class="pl-c">//</span> of cvFindChessboardCornes that produces absolutely unordered sets of corners.</span>
<span class="pl-c"><span class="pl-c">//</span></span>

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvCheckBoardMonotony</span>( CvPoint2D32f* corners, CvSize pattern_size )
{
    <span class="pl-k">int</span> i, j, k;

    <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">2</span>; k++ )
    {
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; (k == <span class="pl-c1">0</span> ? pattern_size.<span class="pl-smi">height</span> : pattern_size.<span class="pl-smi">width</span>); i++ )
        {
            CvPoint2D32f a = k == <span class="pl-c1">0</span> ? corners[i*pattern_size.<span class="pl-smi">width</span>] : corners[i];
            CvPoint2D32f b = k == <span class="pl-c1">0</span> ? corners[(i+<span class="pl-c1">1</span>)*pattern_size.<span class="pl-smi">width</span>-<span class="pl-c1">1</span>] :
                corners[(pattern_size.<span class="pl-smi">height</span>-<span class="pl-c1">1</span>)*pattern_size.<span class="pl-smi">width</span> + i];
            <span class="pl-k">float</span> prevt = <span class="pl-c1">0</span>, dx0 = b.<span class="pl-smi">x</span> - a.<span class="pl-smi">x</span>, dy0 = b.<span class="pl-smi">y</span> - a.<span class="pl-smi">y</span>;
            <span class="pl-k">if</span>( <span class="pl-c1">fabs</span>(dx0) + <span class="pl-c1">fabs</span>(dy0) &lt; FLT_EPSILON )
                <span class="pl-k">return</span> <span class="pl-c1">0</span>;
            <span class="pl-k">for</span>( j = <span class="pl-c1">1</span>; j &lt; (k == <span class="pl-c1">0</span> ? pattern_size.<span class="pl-smi">width</span> : pattern_size.<span class="pl-smi">height</span>) - <span class="pl-c1">1</span>; j++ )
            {
                CvPoint2D32f c = k == <span class="pl-c1">0</span> ? corners[i*pattern_size.<span class="pl-smi">width</span> + j] :
                    corners[j*pattern_size.<span class="pl-smi">width</span> + i];
                <span class="pl-k">float</span> t = ((c.<span class="pl-smi">x</span> - a.<span class="pl-smi">x</span>)*dx0 + (c.<span class="pl-smi">y</span> - a.<span class="pl-smi">y</span>)*dy0)/(dx0*dx0 + dy0*dy0);
                <span class="pl-k">if</span>( t &lt; prevt || t &gt; <span class="pl-c1">1</span> )
                    <span class="pl-k">return</span> <span class="pl-c1">0</span>;
                prevt = t;
            }
        }
    }

    <span class="pl-k">return</span> <span class="pl-c1">1</span>;
}

<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> order a group of connected quads</span>
<span class="pl-c"><span class="pl-c">//</span> order of corners:</span>
<span class="pl-c"><span class="pl-c">//</span>   0 is top left</span>
<span class="pl-c"><span class="pl-c">//</span>   clockwise from there</span>
<span class="pl-c"><span class="pl-c">//</span> note: "top left" is nominal, depends on initial ordering of starting quad</span>
<span class="pl-c"><span class="pl-c">//</span>   but all other quads are ordered consistently</span>
<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> can change the number of quads in the group</span>
<span class="pl-c"><span class="pl-c">//</span> can add quads, so we need to have quad/corner arrays passed in</span>
<span class="pl-c"><span class="pl-c">//</span></span>

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvOrderFoundConnectedQuads</span>( <span class="pl-k">int</span> quad_count, CvCBQuad **quads,
        <span class="pl-k">int</span> *all_count, CvCBQuad **all_quads, CvCBCorner **corners,
        CvSize pattern_size, <span class="pl-k">int</span> max_quad_buf_size, CvMemStorage* storage )
{
    cv::<span class="pl-c1">Ptr</span>&lt;CvMemStorage&gt; temp_storage = <span class="pl-c1">cvCreateChildMemStorage</span>( storage );
    CvSeq* stack = <span class="pl-c1">cvCreateSeq</span>( <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(*stack), <span class="pl-k">sizeof</span>(<span class="pl-k">void</span>*), temp_storage );

    <span class="pl-c"><span class="pl-c">//</span> first find an interior quad</span>
    CvCBQuad *start = <span class="pl-c1">NULL</span>;
    <span class="pl-k">for</span> (<span class="pl-k">int</span> i=<span class="pl-c1">0</span>; i&lt;quad_count; i++)
    {
        <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">4</span>)
        {
            start = quads[i];
            <span class="pl-k">break</span>;
        }
    }

    <span class="pl-k">if</span> (start == <span class="pl-c1">NULL</span>)
        <span class="pl-k">return</span> <span class="pl-c1">0</span>;   <span class="pl-c"><span class="pl-c">//</span> no 4-connected quad</span>

    <span class="pl-c"><span class="pl-c">//</span> start with first one, assign rows/cols</span>
    <span class="pl-k">int</span> row_min = <span class="pl-c1">0</span>, col_min = <span class="pl-c1">0</span>, row_max=<span class="pl-c1">0</span>, col_max = <span class="pl-c1">0</span>;

    std::map&lt;<span class="pl-k">int</span>, <span class="pl-k">int</span>&gt; col_hist;
    std::map&lt;<span class="pl-k">int</span>, <span class="pl-k">int</span>&gt; row_hist;

    <span class="pl-c1">cvSeqPush</span>(stack, &amp;start);
    start-&gt;<span class="pl-smi">row</span> = <span class="pl-c1">0</span>;
    start-&gt;<span class="pl-smi">col</span> = <span class="pl-c1">0</span>;
    start-&gt;<span class="pl-smi">ordered</span> = <span class="pl-c1">true</span>;

    <span class="pl-c"><span class="pl-c">//</span> Recursively order the quads so that all position numbers (e.g.,</span>
    <span class="pl-c"><span class="pl-c">//</span> 0,1,2,3) are in the at the same relative corner (e.g., lower right).</span>

    <span class="pl-k">while</span>( stack-&gt;<span class="pl-smi">total</span> )
    {
        CvCBQuad* q;
        <span class="pl-c1">cvSeqPop</span>( stack, &amp;q );
        <span class="pl-k">int</span> col = q-&gt;<span class="pl-smi">col</span>;
        <span class="pl-k">int</span> row = q-&gt;<span class="pl-smi">row</span>;
        col_hist[col]++;
        row_hist[row]++;

        <span class="pl-c"><span class="pl-c">//</span> check min/max</span>
        <span class="pl-k">if</span> (row &gt; row_max) row_max = row;
        <span class="pl-k">if</span> (row &lt; row_min) row_min = row;
        <span class="pl-k">if</span> (col &gt; col_max) col_max = col;
        <span class="pl-k">if</span> (col &lt; col_min) col_min = col;

        <span class="pl-k">for</span>(<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
        {
            CvCBQuad *neighbor = q-&gt;<span class="pl-smi">neighbors</span>[i];
            <span class="pl-k">switch</span>(i)   <span class="pl-c"><span class="pl-c">//</span> adjust col, row for this quad</span>
            {           <span class="pl-c"><span class="pl-c">//</span> start at top left, go clockwise</span>
            <span class="pl-k">case</span> <span class="pl-c1">0</span>:
                row--; col--; <span class="pl-k">break</span>;
            <span class="pl-k">case</span> <span class="pl-c1">1</span>:
                col += <span class="pl-c1">2</span>; <span class="pl-k">break</span>;
            <span class="pl-k">case</span> <span class="pl-c1">2</span>:
                row += <span class="pl-c1">2</span>;   <span class="pl-k">break</span>;
            <span class="pl-k">case</span> <span class="pl-c1">3</span>:
                col -= <span class="pl-c1">2</span>; <span class="pl-k">break</span>;
            }

            <span class="pl-c"><span class="pl-c">//</span> just do inside quads</span>
            <span class="pl-k">if</span> (neighbor &amp;&amp; neighbor-&gt;<span class="pl-smi">ordered</span> == <span class="pl-c1">false</span> &amp;&amp; neighbor-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">4</span>)
            {
                <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>col: %d  row: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, col, row);
                <span class="pl-c1">icvOrderQuad</span>(neighbor, q-&gt;<span class="pl-smi">corners</span>[i], (i+<span class="pl-c1">2</span>)%<span class="pl-c1">4</span>); <span class="pl-c"><span class="pl-c">//</span> set in order</span>
                neighbor-&gt;<span class="pl-smi">ordered</span> = <span class="pl-c1">true</span>;
                neighbor-&gt;<span class="pl-smi">row</span> = row;
                neighbor-&gt;<span class="pl-smi">col</span> = col;
                <span class="pl-c1">cvSeqPush</span>( stack, &amp;neighbor );
            }
        }
    }

    <span class="pl-k">for</span> (<span class="pl-k">int</span> i=col_min; i&lt;=col_max; i++)
        <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>HIST[%d] = %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, i, col_hist[i]);

    <span class="pl-c"><span class="pl-c">//</span> analyze inner quad structure</span>
    <span class="pl-k">int</span> w = pattern_size.<span class="pl-smi">width</span> - <span class="pl-c1">1</span>;
    <span class="pl-k">int</span> h = pattern_size.<span class="pl-smi">height</span> - <span class="pl-c1">1</span>;
    <span class="pl-k">int</span> drow = row_max - row_min + <span class="pl-c1">1</span>;
    <span class="pl-k">int</span> dcol = col_max - col_min + <span class="pl-c1">1</span>;

    <span class="pl-c"><span class="pl-c">//</span> normalize pattern and found quad indices</span>
    <span class="pl-k">if</span> ((w &gt; h &amp;&amp; dcol &lt; drow) ||
        (w &lt; h &amp;&amp; drow &lt; dcol))
    {
        h = pattern_size.<span class="pl-smi">width</span> - <span class="pl-c1">1</span>;
        w = pattern_size.<span class="pl-smi">height</span> - <span class="pl-c1">1</span>;
    }

    <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Size: %dx%d  Pattern: %dx%d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, dcol, drow, w, h);

    <span class="pl-c"><span class="pl-c">//</span> check if there are enough inner quads</span>
    <span class="pl-k">if</span> (dcol &lt; w || drow &lt; h)   <span class="pl-c"><span class="pl-c">//</span> found enough inner quads?</span>
    {
        <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Too few inner quad rows/cols<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
        <span class="pl-k">return</span> <span class="pl-c1">0</span>;   <span class="pl-c"><span class="pl-c">//</span> no, return</span>
    }
#<span class="pl-k">ifdef</span> ENABLE_TRIM_COL_ROW
    <span class="pl-c"><span class="pl-c">//</span> too many columns, not very common</span>
    <span class="pl-k">if</span> (dcol == w+<span class="pl-c1">1</span>)    <span class="pl-c"><span class="pl-c">//</span> too many, trim</span>
    {
        <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Trimming cols<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
        <span class="pl-k">if</span> (col_hist[col_max] &gt; col_hist[col_min])
        {
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Trimming left col<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
            quad_count = <span class="pl-c1">icvTrimCol</span>(quads,quad_count,col_min,-<span class="pl-c1">1</span>);
        }
        <span class="pl-k">else</span>
        {
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Trimming right col<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
            quad_count = <span class="pl-c1">icvTrimCol</span>(quads,quad_count,col_max,+<span class="pl-c1">1</span>);
        }
    }

    <span class="pl-c"><span class="pl-c">//</span> too many rows, not very common</span>
    <span class="pl-k">if</span> (drow == h+<span class="pl-c1">1</span>)    <span class="pl-c"><span class="pl-c">//</span> too many, trim</span>
    {
        <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Trimming rows<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
        <span class="pl-k">if</span> (row_hist[row_max] &gt; row_hist[row_min])
        {
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Trimming top row<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
            quad_count = <span class="pl-c1">icvTrimRow</span>(quads,quad_count,row_min,-<span class="pl-c1">1</span>);
        }
        <span class="pl-k">else</span>
        {
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Trimming bottom row<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
            quad_count = <span class="pl-c1">icvTrimRow</span>(quads,quad_count,row_max,+<span class="pl-c1">1</span>);
        }
    }
#<span class="pl-k">endif</span>

    <span class="pl-c"><span class="pl-c">//</span> check edges of inner quads</span>
    <span class="pl-c"><span class="pl-c">//</span> if there is an outer quad missing, fill it in</span>
    <span class="pl-c"><span class="pl-c">//</span> first order all inner quads</span>
    <span class="pl-k">int</span> found = <span class="pl-c1">0</span>;
    <span class="pl-k">for</span> (<span class="pl-k">int</span> i=<span class="pl-c1">0</span>; i&lt;quad_count; i++)
    {
        <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">4</span>)
        {   <span class="pl-c"><span class="pl-c">//</span> ok, look at neighbors</span>
            <span class="pl-k">int</span> col = quads[i]-&gt;<span class="pl-smi">col</span>;
            <span class="pl-k">int</span> row = quads[i]-&gt;<span class="pl-smi">row</span>;
            <span class="pl-k">for</span> (<span class="pl-k">int</span> j=<span class="pl-c1">0</span>; j&lt;<span class="pl-c1">4</span>; j++)
            {
                <span class="pl-k">switch</span>(j)   <span class="pl-c"><span class="pl-c">//</span> adjust col, row for this quad</span>
                {       <span class="pl-c"><span class="pl-c">//</span> start at top left, go clockwise</span>
                <span class="pl-k">case</span> <span class="pl-c1">0</span>:
                    row--; col--; <span class="pl-k">break</span>;
                <span class="pl-k">case</span> <span class="pl-c1">1</span>:
                    col += <span class="pl-c1">2</span>; <span class="pl-k">break</span>;
                <span class="pl-k">case</span> <span class="pl-c1">2</span>:
                    row += <span class="pl-c1">2</span>;   <span class="pl-k">break</span>;
                <span class="pl-k">case</span> <span class="pl-c1">3</span>:
                    col -= <span class="pl-c1">2</span>; <span class="pl-k">break</span>;
                }
                CvCBQuad *neighbor = quads[i]-&gt;<span class="pl-smi">neighbors</span>[j];
                <span class="pl-k">if</span> (neighbor &amp;&amp; !neighbor-&gt;<span class="pl-smi">ordered</span> &amp;&amp; <span class="pl-c"><span class="pl-c">//</span> is it an inner quad?</span>
                    col &lt;= col_max &amp;&amp; col &gt;= col_min &amp;&amp;
                    row &lt;= row_max &amp;&amp; row &gt;= row_min)
                {
                    <span class="pl-c"><span class="pl-c">//</span> if so, set in order</span>
                    <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Adding inner: col: %d  row: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, col, row);
                    found++;
                    <span class="pl-c1">icvOrderQuad</span>(neighbor, quads[i]-&gt;<span class="pl-smi">corners</span>[j], (j+<span class="pl-c1">2</span>)%<span class="pl-c1">4</span>);
                    neighbor-&gt;<span class="pl-smi">ordered</span> = <span class="pl-c1">true</span>;
                    neighbor-&gt;<span class="pl-smi">row</span> = row;
                    neighbor-&gt;<span class="pl-smi">col</span> = col;
                }
            }
        }
    }

    <span class="pl-c"><span class="pl-c">//</span> if we have found inner quads, add corresponding outer quads,</span>
    <span class="pl-c"><span class="pl-c">//</span>   which are missing</span>
    <span class="pl-k">if</span> (found &gt; <span class="pl-c1">0</span>)
    {
        <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Found %d inner quads not connected to outer quads, repairing<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, found);
        <span class="pl-k">for</span> (<span class="pl-k">int</span> i=<span class="pl-c1">0</span>; i&lt;quad_count &amp;&amp; *all_count &lt; max_quad_buf_size; i++)
        {
            <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">count</span> &lt; <span class="pl-c1">4</span> &amp;&amp; quads[i]-&gt;<span class="pl-smi">ordered</span>)
            {
                <span class="pl-k">int</span> added = <span class="pl-c1">icvAddOuterQuad</span>(quads[i],quads,quad_count,all_quads,*all_count,corners, max_quad_buf_size);
                *all_count += added;
                quad_count += added;
            }
        }

        <span class="pl-k">if</span> (*all_count &gt;= max_quad_buf_size)
            <span class="pl-k">return</span> <span class="pl-c1">0</span>;
    }


    <span class="pl-c"><span class="pl-c">//</span> final trimming of outer quads</span>
    <span class="pl-k">if</span> (dcol == w &amp;&amp; drow == h) <span class="pl-c"><span class="pl-c">//</span> found correct inner quads</span>
    {
        <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Inner bounds ok, check outer quads<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
        <span class="pl-k">int</span> rcount = quad_count;
        <span class="pl-k">for</span> (<span class="pl-k">int</span> i=quad_count-<span class="pl-c1">1</span>; i&gt;=<span class="pl-c1">0</span>; i--) <span class="pl-c"><span class="pl-c">//</span> eliminate any quad not connected to</span>
            <span class="pl-c"><span class="pl-c">//</span> an ordered quad</span>
        {
            <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">ordered</span> == <span class="pl-c1">false</span>)
            {
                <span class="pl-k">bool</span> outer = <span class="pl-c1">false</span>;
                <span class="pl-k">for</span> (<span class="pl-k">int</span> j=<span class="pl-c1">0</span>; j&lt;<span class="pl-c1">4</span>; j++) <span class="pl-c"><span class="pl-c">//</span> any neighbors that are ordered?</span>
                {
                    <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[j] &amp;&amp; quads[i]-&gt;<span class="pl-smi">neighbors</span>[j]-&gt;<span class="pl-smi">ordered</span>)
                        outer = <span class="pl-c1">true</span>;
                }
                <span class="pl-k">if</span> (!outer) <span class="pl-c"><span class="pl-c">//</span> not an outer quad, eliminate</span>
                {
                    <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Removing quad %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, i);
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]);
                    rcount--;
                }
            }

        }
        <span class="pl-k">return</span> rcount;
    }

    <span class="pl-k">return</span> <span class="pl-c1">0</span>;
}


<span class="pl-c"><span class="pl-c">//</span> add an outer quad</span>
<span class="pl-c"><span class="pl-c">//</span> looks for the neighbor of &lt;quad&gt; that isn't present,</span>
<span class="pl-c"><span class="pl-c">//</span>   tries to add it in.</span>
<span class="pl-c"><span class="pl-c">//</span> &lt;quad&gt; is ordered</span>

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvAddOuterQuad</span>( CvCBQuad *quad, CvCBQuad **quads, <span class="pl-k">int</span> quad_count,
        CvCBQuad **all_quads, <span class="pl-k">int</span> all_count, CvCBCorner **corners, <span class="pl-k">int</span> max_quad_buf_size )

{
    <span class="pl-k">int</span> added = <span class="pl-c1">0</span>;
    <span class="pl-k">for</span> (<span class="pl-k">int</span> i=<span class="pl-c1">0</span>; i&lt;<span class="pl-c1">4</span> &amp;&amp; all_count &lt; max_quad_buf_size; i++) <span class="pl-c"><span class="pl-c">//</span> find no-neighbor corners</span>
    {
        <span class="pl-k">if</span> (!quad-&gt;<span class="pl-smi">neighbors</span>[i])    <span class="pl-c"><span class="pl-c">//</span> ok, create and add neighbor</span>
        {
            <span class="pl-k">int</span> j = (i+<span class="pl-c1">2</span>)%<span class="pl-c1">4</span>;
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Adding quad as neighbor 2<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
            CvCBQuad *q = &amp;(*all_quads)[all_count];
            <span class="pl-c1">memset</span>( q, <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(*q) );
            added++;
            quads[quad_count] = q;
            quad_count++;

            <span class="pl-c"><span class="pl-c">//</span> set neighbor and group id</span>
            quad-&gt;<span class="pl-smi">neighbors</span>[i] = q;
            quad-&gt;<span class="pl-smi">count</span> += <span class="pl-c1">1</span>;
            q-&gt;<span class="pl-smi">neighbors</span>[j] = quad;
            q-&gt;<span class="pl-smi">group_idx</span> = quad-&gt;<span class="pl-smi">group_idx</span>;
            q-&gt;<span class="pl-smi">count</span> = <span class="pl-c1">1</span>;   <span class="pl-c"><span class="pl-c">//</span> number of neighbors</span>
            q-&gt;<span class="pl-smi">ordered</span> = <span class="pl-c1">false</span>;
            q-&gt;<span class="pl-smi">edge_len</span> = quad-&gt;<span class="pl-smi">edge_len</span>;

            <span class="pl-c"><span class="pl-c">//</span> make corners of new quad</span>
            <span class="pl-c"><span class="pl-c">//</span> same as neighbor quad, but offset</span>
            CvPoint2D32f pt = quad-&gt;<span class="pl-smi">corners</span>[i]-&gt;<span class="pl-smi">pt</span>;
            CvCBCorner* corner;
            <span class="pl-k">float</span> dx = pt.<span class="pl-smi">x</span> - quad-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span>;
            <span class="pl-k">float</span> dy = pt.<span class="pl-smi">y</span> - quad-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>;
            <span class="pl-k">for</span> (<span class="pl-k">int</span> k=<span class="pl-c1">0</span>; k&lt;<span class="pl-c1">4</span>; k++)
            {
                corner = &amp;(*corners)[all_count*<span class="pl-c1">4</span>+k];
                pt = quad-&gt;<span class="pl-smi">corners</span>[k]-&gt;<span class="pl-smi">pt</span>;
                <span class="pl-c1">memset</span>( corner, <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(*corner) );
                corner-&gt;<span class="pl-smi">pt</span> = pt;
                q-&gt;<span class="pl-smi">corners</span>[k] = corner;
                corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> += dx;
                corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> += dy;
            }
            <span class="pl-c"><span class="pl-c">//</span> have to set exact corner</span>
            q-&gt;<span class="pl-smi">corners</span>[j] = quad-&gt;<span class="pl-smi">corners</span>[i];

            <span class="pl-c"><span class="pl-c">//</span> now find other neighbor and add it, if possible</span>
            <span class="pl-k">if</span> (quad-&gt;<span class="pl-smi">neighbors</span>[(i+<span class="pl-c1">3</span>)%<span class="pl-c1">4</span>] &amp;&amp;
                quad-&gt;<span class="pl-smi">neighbors</span>[(i+<span class="pl-c1">3</span>)%<span class="pl-c1">4</span>]-&gt;<span class="pl-smi">ordered</span> &amp;&amp;
                quad-&gt;<span class="pl-smi">neighbors</span>[(i+<span class="pl-c1">3</span>)%<span class="pl-c1">4</span>]-&gt;<span class="pl-smi">neighbors</span>[i] &amp;&amp;
                quad-&gt;<span class="pl-smi">neighbors</span>[(i+<span class="pl-c1">3</span>)%<span class="pl-c1">4</span>]-&gt;<span class="pl-smi">neighbors</span>[i]-&gt;<span class="pl-smi">ordered</span> )
            {
                CvCBQuad *qn = quad-&gt;<span class="pl-smi">neighbors</span>[(i+<span class="pl-c1">3</span>)%<span class="pl-c1">4</span>]-&gt;<span class="pl-smi">neighbors</span>[i];
                q-&gt;<span class="pl-smi">count</span> = <span class="pl-c1">2</span>;
                q-&gt;<span class="pl-smi">neighbors</span>[(j+<span class="pl-c1">1</span>)%<span class="pl-c1">4</span>] = qn;
                qn-&gt;<span class="pl-smi">neighbors</span>[(i+<span class="pl-c1">1</span>)%<span class="pl-c1">4</span>] = q;
                qn-&gt;<span class="pl-smi">count</span> += <span class="pl-c1">1</span>;
                <span class="pl-c"><span class="pl-c">//</span> have to set exact corner</span>
                q-&gt;<span class="pl-smi">corners</span>[(j+<span class="pl-c1">1</span>)%<span class="pl-c1">4</span>] = qn-&gt;<span class="pl-smi">corners</span>[(i+<span class="pl-c1">1</span>)%<span class="pl-c1">4</span>];
            }

            all_count++;
        }
    }
    <span class="pl-k">return</span> added;
}


<span class="pl-c"><span class="pl-c">//</span> trimming routines</span>
#<span class="pl-k">ifdef</span> ENABLE_TRIM_COL_ROW
<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvTrimCol</span>(CvCBQuad **quads, <span class="pl-k">int</span> count, <span class="pl-k">int</span> col, <span class="pl-k">int</span> dir)
{
    <span class="pl-k">int</span> rcount = count;
    <span class="pl-c"><span class="pl-c">//</span> find the right quad(s)</span>
    <span class="pl-k">for</span> (<span class="pl-k">int</span> i=<span class="pl-c1">0</span>; i&lt;count; i++)
    {
#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
        <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">ordered</span>)
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>index: %d  cur: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, col, quads[i]-&gt;<span class="pl-smi">col</span>);
#<span class="pl-k">endif</span>
        <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">ordered</span> &amp;&amp; quads[i]-&gt;<span class="pl-smi">col</span> == col)
        {
            <span class="pl-k">if</span> (dir == <span class="pl-c1">1</span>)
            {
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">1</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">1</span>]);
                    rcount--;
                }
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">2</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">2</span>]);
                    rcount--;
                }
            }
            <span class="pl-k">else</span>
            {
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">0</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">0</span>]);
                    rcount--;
                }
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">3</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">3</span>]);
                    rcount--;
                }
            }

        }
    }
    <span class="pl-k">return</span> rcount;
}

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvTrimRow</span>(CvCBQuad **quads, <span class="pl-k">int</span> count, <span class="pl-k">int</span> row, <span class="pl-k">int</span> dir)
{
    <span class="pl-k">int</span> i, rcount = count;
    <span class="pl-c"><span class="pl-c">//</span> find the right quad(s)</span>
    <span class="pl-k">for</span> (i=<span class="pl-c1">0</span>; i&lt;count; i++)
    {
#<span class="pl-k">ifdef</span> DEBUG_CHESSBOARD
        <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">ordered</span>)
            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>index: %d  cur: %d<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, row, quads[i]-&gt;<span class="pl-smi">row</span>);
#<span class="pl-k">endif</span>
        <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">ordered</span> &amp;&amp; quads[i]-&gt;<span class="pl-smi">row</span> == row)
        {
            <span class="pl-k">if</span> (dir == <span class="pl-c1">1</span>)   <span class="pl-c"><span class="pl-c">//</span> remove from bottom</span>
            {
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">2</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">2</span>]);
                    rcount--;
                }
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">3</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">3</span>]);
                    rcount--;
                }
            }
            <span class="pl-k">else</span>    <span class="pl-c"><span class="pl-c">//</span> remove from top</span>
            {
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">0</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">0</span>]);
                    rcount--;
                }
                <span class="pl-k">if</span> (quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">1</span>])
                {
                    <span class="pl-c1">icvRemoveQuadFromGroup</span>(quads,rcount,quads[i]-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">1</span>]);
                    rcount--;
                }
            }

        }
    }
    <span class="pl-k">return</span> rcount;
}
#<span class="pl-k">endif</span>

<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> remove quad from quad group</span>
<span class="pl-c"><span class="pl-c">//</span></span>

<span class="pl-k">static</span> <span class="pl-k">void</span>
<span class="pl-en">icvRemoveQuadFromGroup</span>(CvCBQuad **quads, <span class="pl-k">int</span> count, CvCBQuad *q0)
{
    <span class="pl-k">int</span> i, j;
    <span class="pl-c"><span class="pl-c">//</span> remove any references to this quad as a neighbor</span>
    <span class="pl-k">for</span>(i = <span class="pl-c1">0</span>; i &lt; count; i++ )
    {
        CvCBQuad *q = quads[i];
        <span class="pl-k">for</span>(j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
        {
            <span class="pl-k">if</span>( q-&gt;<span class="pl-smi">neighbors</span>[j] == q0 )
            {
                q-&gt;<span class="pl-smi">neighbors</span>[j] = <span class="pl-c1">0</span>;
                q-&gt;<span class="pl-smi">count</span>--;
                <span class="pl-k">for</span>(<span class="pl-k">int</span> k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">4</span>; k++ )
                    <span class="pl-k">if</span>( q0-&gt;<span class="pl-smi">neighbors</span>[k] == q )
                    {
                        q0-&gt;<span class="pl-smi">neighbors</span>[k] = <span class="pl-c1">0</span>;
                        q0-&gt;<span class="pl-smi">count</span>--;
                        <span class="pl-k">break</span>;
                    }
                    <span class="pl-k">break</span>;
            }
        }
    }

    <span class="pl-c"><span class="pl-c">//</span> remove the quad</span>
    <span class="pl-k">for</span>(i = <span class="pl-c1">0</span>; i &lt; count; i++ )
    {
        CvCBQuad *q = quads[i];
        <span class="pl-k">if</span> (q == q0)
        {
            quads[i] = quads[count-<span class="pl-c1">1</span>];
            <span class="pl-k">break</span>;
        }
    }
}

<span class="pl-c"><span class="pl-c">//</span></span>
<span class="pl-c"><span class="pl-c">//</span> put quad into correct order, where &lt;corner&gt; has value &lt;common&gt;</span>
<span class="pl-c"><span class="pl-c">//</span></span>

<span class="pl-k">static</span> <span class="pl-k">void</span>
<span class="pl-en">icvOrderQuad</span>(CvCBQuad *quad, CvCBCorner *corner, <span class="pl-k">int</span> common)
{
    <span class="pl-c"><span class="pl-c">//</span> find the corner</span>
    <span class="pl-k">int</span> tc;
    <span class="pl-k">for</span> (tc=<span class="pl-c1">0</span>; tc&lt;<span class="pl-c1">4</span>; tc++)
        <span class="pl-k">if</span> (quad-&gt;<span class="pl-smi">corners</span>[tc]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> == corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> &amp;&amp;
            quad-&gt;<span class="pl-smi">corners</span>[tc]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> == corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>)
            <span class="pl-k">break</span>;

    <span class="pl-c"><span class="pl-c">//</span> set corner order</span>
    <span class="pl-c"><span class="pl-c">//</span> shift</span>
    <span class="pl-k">while</span> (tc != common)
    {
        <span class="pl-c"><span class="pl-c">//</span> shift by one</span>
        CvCBCorner *tempc;
        CvCBQuad *tempq;
        tempc = quad-&gt;<span class="pl-smi">corners</span>[<span class="pl-c1">3</span>];
        tempq = quad-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">3</span>];
        <span class="pl-k">for</span> (<span class="pl-k">int</span> i=<span class="pl-c1">3</span>; i&gt;<span class="pl-c1">0</span>; i--)
        {
            quad-&gt;<span class="pl-smi">corners</span>[i] = quad-&gt;<span class="pl-smi">corners</span>[i-<span class="pl-c1">1</span>];
            quad-&gt;<span class="pl-smi">neighbors</span>[i] = quad-&gt;<span class="pl-smi">neighbors</span>[i-<span class="pl-c1">1</span>];
        }
        quad-&gt;<span class="pl-smi">corners</span>[<span class="pl-c1">0</span>] = tempc;
        quad-&gt;<span class="pl-smi">neighbors</span>[<span class="pl-c1">0</span>] = tempq;
        tc++;
        tc = tc%<span class="pl-c1">4</span>;
    }
}


<span class="pl-c"><span class="pl-c">//</span> if we found too many connect quads, remove those which probably do not belong.</span>
<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvCleanFoundConnectedQuads</span>( <span class="pl-k">int</span> quad_count, CvCBQuad **quad_group, CvSize pattern_size )
{
    CvPoint2D32f center = {<span class="pl-c1">0</span>,<span class="pl-c1">0</span>};
    <span class="pl-k">int</span> i, j, k;
    <span class="pl-c"><span class="pl-c">//</span> number of quads this pattern should contain</span>
    <span class="pl-k">int</span> count = ((pattern_size.<span class="pl-smi">width</span> + <span class="pl-c1">1</span>)*(pattern_size.<span class="pl-smi">height</span> + <span class="pl-c1">1</span>) + <span class="pl-c1">1</span>)/<span class="pl-c1">2</span>;

    <span class="pl-c"><span class="pl-c">//</span> if we have more quadrangles than we should,</span>
    <span class="pl-c"><span class="pl-c">//</span> try to eliminate duplicates or ones which don't belong to the pattern rectangle...</span>
    <span class="pl-k">if</span>( quad_count &lt;= count )
        <span class="pl-k">return</span> quad_count;

    <span class="pl-c"><span class="pl-c">//</span> create an array of quadrangle centers</span>
    cv::AutoBuffer&lt;CvPoint2D32f&gt; <span class="pl-c1">centers</span>( quad_count );
    cv::<span class="pl-c1">Ptr</span>&lt;CvMemStorage&gt; temp_storage = <span class="pl-c1">cvCreateMemStorage</span>(<span class="pl-c1">0</span>);

    <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; quad_count; i++ )
    {
        CvPoint2D32f ci = {<span class="pl-c1">0</span>,<span class="pl-c1">0</span>};
        CvCBQuad* q = quad_group[i];

        <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
        {
            CvPoint2D32f pt = q-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>;
            ci.<span class="pl-smi">x</span> += pt.<span class="pl-smi">x</span>;
            ci.<span class="pl-smi">y</span> += pt.<span class="pl-smi">y</span>;
        }

        ci.<span class="pl-smi">x</span> *= <span class="pl-c1">0</span>.<span class="pl-c1">25f</span>;
        ci.<span class="pl-smi">y</span> *= <span class="pl-c1">0</span>.<span class="pl-c1">25f</span>;

        centers[i] = ci;
        center.<span class="pl-smi">x</span> += ci.<span class="pl-smi">x</span>;
        center.<span class="pl-smi">y</span> += ci.<span class="pl-smi">y</span>;
    }
    center.<span class="pl-smi">x</span> /= quad_count;
    center.<span class="pl-smi">y</span> /= quad_count;

    <span class="pl-c"><span class="pl-c">//</span> If we still have more quadrangles than we should,</span>
    <span class="pl-c"><span class="pl-c">//</span> we try to eliminate bad ones based on minimizing the bounding box.</span>
    <span class="pl-c"><span class="pl-c">//</span> We iteratively remove the point which reduces the size of</span>
    <span class="pl-c"><span class="pl-c">//</span> the bounding box of the blobs the most</span>
    <span class="pl-c"><span class="pl-c">//</span> (since we want the rectangle to be as small as possible)</span>
    <span class="pl-c"><span class="pl-c">//</span> remove the quadrange that causes the biggest reduction</span>
    <span class="pl-c"><span class="pl-c">//</span> in pattern size until we have the correct number</span>
    <span class="pl-k">for</span>( ; quad_count &gt; count; quad_count-- )
    {
        <span class="pl-k">double</span> min_box_area = DBL_MAX;
        <span class="pl-k">int</span> skip, min_box_area_index = -<span class="pl-c1">1</span>;
        CvCBQuad *q0, *q;

        <span class="pl-c"><span class="pl-c">//</span> For each point, calculate box area without that point</span>
        <span class="pl-k">for</span>( skip = <span class="pl-c1">0</span>; skip &lt; quad_count; skip++ )
        {
            <span class="pl-c"><span class="pl-c">//</span> get bounding rectangle</span>
            CvPoint2D32f temp = centers[skip]; <span class="pl-c"><span class="pl-c">//</span> temporarily make index 'skip' the same as</span>
            centers[skip] = center;            <span class="pl-c"><span class="pl-c">//</span> pattern center (so it is not counted for convex hull)</span>
            CvMat pointMat = <span class="pl-c1">cvMat</span>(<span class="pl-c1">1</span>, quad_count, CV_32FC2, centers);
            CvSeq *hull = <span class="pl-c1">cvConvexHull2</span>( &amp;pointMat, temp_storage, CV_CLOCKWISE, <span class="pl-c1">1</span> );
            centers[skip] = temp;
            <span class="pl-k">double</span> hull_area = <span class="pl-c1">fabs</span>(<span class="pl-c1">cvContourArea</span>(hull, CV_WHOLE_SEQ));

            <span class="pl-c"><span class="pl-c">//</span> remember smallest box area</span>
            <span class="pl-k">if</span>( hull_area &lt; min_box_area )
            {
                min_box_area = hull_area;
                min_box_area_index = skip;
            }
            <span class="pl-c1">cvClearMemStorage</span>( temp_storage );
        }

        q0 = quad_group[min_box_area_index];

        <span class="pl-c"><span class="pl-c">//</span> remove any references to this quad as a neighbor</span>
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; quad_count; i++ )
        {
            q = quad_group[i];
            <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
            {
                <span class="pl-k">if</span>( q-&gt;<span class="pl-smi">neighbors</span>[j] == q0 )
                {
                    q-&gt;<span class="pl-smi">neighbors</span>[j] = <span class="pl-c1">0</span>;
                    q-&gt;<span class="pl-smi">count</span>--;
                    <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">4</span>; k++ )
                        <span class="pl-k">if</span>( q0-&gt;<span class="pl-smi">neighbors</span>[k] == q )
                        {
                            q0-&gt;<span class="pl-smi">neighbors</span>[k] = <span class="pl-c1">0</span>;
                            q0-&gt;<span class="pl-smi">count</span>--;
                            <span class="pl-k">break</span>;
                        }
                    <span class="pl-k">break</span>;
                }
            }
        }

        <span class="pl-c"><span class="pl-c">//</span> remove the quad</span>
        quad_count--;
        quad_group[min_box_area_index] = quad_group[quad_count];
        centers[min_box_area_index] = centers[quad_count];
    }

    <span class="pl-k">return</span> quad_count;
}

<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvFindConnectedQuads</span>( CvCBQuad *quad, <span class="pl-k">int</span> quad_count, CvCBQuad **out_group,
                       <span class="pl-k">int</span> group_idx, CvMemStorage* storage )
{
    cv::<span class="pl-c1">Ptr</span>&lt;CvMemStorage&gt; temp_storage = <span class="pl-c1">cvCreateChildMemStorage</span>( storage );
    CvSeq* stack = <span class="pl-c1">cvCreateSeq</span>( <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(*stack), <span class="pl-k">sizeof</span>(<span class="pl-k">void</span>*), temp_storage );
    <span class="pl-k">int</span> i, count = <span class="pl-c1">0</span>;

    <span class="pl-c"><span class="pl-c">//</span> Scan the array for a first unlabeled quad</span>
    <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; quad_count; i++ )
    {
        <span class="pl-k">if</span>( quad[i].<span class="pl-smi">count</span> &gt; <span class="pl-c1">0</span> &amp;&amp; quad[i].<span class="pl-smi">group_idx</span> &lt; <span class="pl-c1">0</span>)
            <span class="pl-k">break</span>;
    }

    <span class="pl-c"><span class="pl-c">//</span> Recursively find a group of connected quads starting from the seed quad[i]</span>
    <span class="pl-k">if</span>( i &lt; quad_count )
    {
        CvCBQuad* q = &amp;quad[i];
        <span class="pl-c1">cvSeqPush</span>( stack, &amp;q );
        out_group[count++] = q;
        q-&gt;<span class="pl-smi">group_idx</span> = group_idx;
        q-&gt;<span class="pl-smi">ordered</span> = <span class="pl-c1">false</span>;

        <span class="pl-k">while</span>( stack-&gt;<span class="pl-smi">total</span> )
        {
            <span class="pl-c1">cvSeqPop</span>( stack, &amp;q );
            <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
            {
                CvCBQuad *neighbor = q-&gt;<span class="pl-smi">neighbors</span>[i];
                <span class="pl-k">if</span>( neighbor &amp;&amp; neighbor-&gt;<span class="pl-smi">count</span> &gt; <span class="pl-c1">0</span> &amp;&amp; neighbor-&gt;<span class="pl-smi">group_idx</span> &lt; <span class="pl-c1">0</span> )
                {
                    <span class="pl-c1">cvSeqPush</span>( stack, &amp;neighbor );
                    out_group[count++] = neighbor;
                    neighbor-&gt;<span class="pl-smi">group_idx</span> = group_idx;
                    neighbor-&gt;<span class="pl-smi">ordered</span> = <span class="pl-c1">false</span>;
                }
            }
        }
    }

    <span class="pl-k">return</span> count;
}


<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvCheckQuadGroup</span>( CvCBQuad **quad_group, <span class="pl-k">int</span> quad_count,
                   CvCBCorner **out_corners, CvSize pattern_size )
{
    <span class="pl-k">const</span> <span class="pl-k">int</span> ROW1 = <span class="pl-c1">1000000</span>;
    <span class="pl-k">const</span> <span class="pl-k">int</span> ROW2 = <span class="pl-c1">2000000</span>;
    <span class="pl-k">const</span> <span class="pl-k">int</span> ROW_ = <span class="pl-c1">3000000</span>;
    <span class="pl-k">int</span> result = <span class="pl-c1">0</span>;
    <span class="pl-k">int</span> i, out_corner_count = <span class="pl-c1">0</span>, corner_count = <span class="pl-c1">0</span>;
    std::vector&lt;CvCBCorner*&gt; <span class="pl-c1">corners</span>(quad_count*<span class="pl-c1">4</span>);

    <span class="pl-k">int</span> j, k, kk;
    <span class="pl-k">int</span> width = <span class="pl-c1">0</span>, height = <span class="pl-c1">0</span>;
    <span class="pl-k">int</span> hist[<span class="pl-c1">5</span>] = {<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">0</span>};
    CvCBCorner* first = <span class="pl-c1">0</span>, *first2 = <span class="pl-c1">0</span>, *right, *cur, *below, *c;

    <span class="pl-c"><span class="pl-c">//</span> build dual graph, which vertices are internal quad corners</span>
    <span class="pl-c"><span class="pl-c">//</span> and two vertices are connected iff they lie on the same quad edge</span>
    <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; quad_count; i++ )
    {
        CvCBQuad* q = quad_group[i];
        <span class="pl-c"><span class="pl-c">/*</span>CvScalar color = q-&gt;count == 0 ? cvScalar(0,255,255) :</span>
<span class="pl-c">                         q-&gt;count == 1 ? cvScalar(0,0,255) :</span>
<span class="pl-c">                         q-&gt;count == 2 ? cvScalar(0,255,0) :</span>
<span class="pl-c">                         q-&gt;count == 3 ? cvScalar(255,255,0) :</span>
<span class="pl-c">                                         cvScalar(255,0,0);<span class="pl-c">*/</span></span>

        <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
        {
            <span class="pl-c"><span class="pl-c">//</span>cvLine( debug_img, cvPointFrom32f(q-&gt;corners[j]-&gt;pt), cvPointFrom32f(q-&gt;corners[(j+1)&amp;3]-&gt;pt), color, 1, CV_AA, 0 );</span>
            <span class="pl-k">if</span>( q-&gt;<span class="pl-smi">neighbors</span>[j] )
            {
                CvCBCorner *a = q-&gt;<span class="pl-smi">corners</span>[j], *b = q-&gt;<span class="pl-smi">corners</span>[(j+<span class="pl-c1">1</span>)&amp;<span class="pl-c1">3</span>];
                <span class="pl-c"><span class="pl-c">//</span> mark internal corners that belong to:</span>
                <span class="pl-c"><span class="pl-c">//</span>   - a quad with a single neighbor - with ROW1,</span>
                <span class="pl-c"><span class="pl-c">//</span>   - a quad with two neighbors     - with ROW2</span>
                <span class="pl-c"><span class="pl-c">//</span> make the rest of internal corners with ROW_</span>
                <span class="pl-k">int</span> row_flag = q-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">1</span> ? ROW1 : q-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">2</span> ? ROW2 : ROW_;

                <span class="pl-k">if</span>( a-&gt;<span class="pl-smi">row</span> == <span class="pl-c1">0</span> )
                {
                    corners[corner_count++] = a;
                    a-&gt;<span class="pl-smi">row</span> = row_flag;
                }
                <span class="pl-k">else</span> <span class="pl-k">if</span>( a-&gt;<span class="pl-smi">row</span> &gt; row_flag )
                    a-&gt;<span class="pl-smi">row</span> = row_flag;

                <span class="pl-k">if</span>( q-&gt;<span class="pl-smi">neighbors</span>[(j+<span class="pl-c1">1</span>)&amp;<span class="pl-c1">3</span>] )
                {
                    <span class="pl-k">if</span>( a-&gt;<span class="pl-smi">count</span> &gt;= <span class="pl-c1">4</span> || b-&gt;<span class="pl-smi">count</span> &gt;= <span class="pl-c1">4</span> )
                        <span class="pl-k">goto</span> finalize;
                    <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">4</span>; k++ )
                    {
                        <span class="pl-k">if</span>( a-&gt;<span class="pl-smi">neighbors</span>[k] == b )
                            <span class="pl-k">goto</span> finalize;
                        <span class="pl-k">if</span>( b-&gt;<span class="pl-smi">neighbors</span>[k] == a )
                            <span class="pl-k">goto</span> finalize;
                    }
                    a-&gt;<span class="pl-smi">neighbors</span>[a-&gt;<span class="pl-smi">count</span>++] = b;
                    b-&gt;<span class="pl-smi">neighbors</span>[b-&gt;<span class="pl-smi">count</span>++] = a;
                }
            }
        }
    }

    <span class="pl-k">if</span>( corner_count != pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span> )
        <span class="pl-k">goto</span> finalize;

    <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; corner_count; i++ )
    {
        <span class="pl-k">int</span> n = corners[i]-&gt;<span class="pl-smi">count</span>;
        <span class="pl-c1">assert</span>( <span class="pl-c1">0</span> &lt;= n &amp;&amp; n &lt;= <span class="pl-c1">4</span> );
        hist[n]++;
        <span class="pl-k">if</span>( !first &amp;&amp; n == <span class="pl-c1">2</span> )
        {
            <span class="pl-k">if</span>( corners[i]-&gt;<span class="pl-smi">row</span> == ROW1 )
                first = corners[i];
            <span class="pl-k">else</span> <span class="pl-k">if</span>( !first2 &amp;&amp; corners[i]-&gt;<span class="pl-smi">row</span> == ROW2 )
                first2 = corners[i];
        }
    }

    <span class="pl-c"><span class="pl-c">//</span> start with a corner that belongs to a quad with a signle neighbor.</span>
    <span class="pl-c"><span class="pl-c">//</span> if we do not have such, start with a corner of a quad with two neighbors.</span>
    <span class="pl-k">if</span>( !first )
        first = first2;

    <span class="pl-k">if</span>( !first || hist[<span class="pl-c1">0</span>] != <span class="pl-c1">0</span> || hist[<span class="pl-c1">1</span>] != <span class="pl-c1">0</span> || hist[<span class="pl-c1">2</span>] != <span class="pl-c1">4</span> ||
        hist[<span class="pl-c1">3</span>] != (pattern_size.<span class="pl-smi">width</span> + pattern_size.<span class="pl-smi">height</span>)*<span class="pl-c1">2</span> - <span class="pl-c1">8</span> )
        <span class="pl-k">goto</span> finalize;

    cur = first;
    right = below = <span class="pl-c1">0</span>;
    out_corners[out_corner_count++] = cur;

    <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">4</span>; k++ )
    {
        c = cur-&gt;<span class="pl-smi">neighbors</span>[k];
        <span class="pl-k">if</span>( c )
        {
            <span class="pl-k">if</span>( !right )
                right = c;
            <span class="pl-k">else</span> <span class="pl-k">if</span>( !below )
                below = c;
        }
    }

    <span class="pl-k">if</span>( !right || (right-&gt;<span class="pl-smi">count</span> != <span class="pl-c1">2</span> &amp;&amp; right-&gt;<span class="pl-smi">count</span> != <span class="pl-c1">3</span>) ||
        !below || (below-&gt;<span class="pl-smi">count</span> != <span class="pl-c1">2</span> &amp;&amp; below-&gt;<span class="pl-smi">count</span> != <span class="pl-c1">3</span>) )
        <span class="pl-k">goto</span> finalize;

    cur-&gt;<span class="pl-smi">row</span> = <span class="pl-c1">0</span>;
    <span class="pl-c"><span class="pl-c">//</span>cvCircle( debug_img, cvPointFrom32f(cur-&gt;pt), 3, cvScalar(0,255,0), -1, 8, 0 );</span>

    first = below; <span class="pl-c"><span class="pl-c">//</span> remember the first corner in the next row</span>
    <span class="pl-c"><span class="pl-c">//</span> find and store the first row (or column)</span>
    <span class="pl-k">for</span>(j=<span class="pl-c1">1</span>;;j++)
    {
        right-&gt;<span class="pl-smi">row</span> = <span class="pl-c1">0</span>;
        out_corners[out_corner_count++] = right;
        <span class="pl-c"><span class="pl-c">//</span>cvCircle( debug_img, cvPointFrom32f(right-&gt;pt), 3, cvScalar(0,255-j*10,0), -1, 8, 0 );</span>
        <span class="pl-k">if</span>( right-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">2</span> )
            <span class="pl-k">break</span>;
        <span class="pl-k">if</span>( right-&gt;<span class="pl-smi">count</span> != <span class="pl-c1">3</span> || out_corner_count &gt;= <span class="pl-c1">MAX</span>(pattern_size.<span class="pl-smi">width</span>,pattern_size.<span class="pl-smi">height</span>) )
            <span class="pl-k">goto</span> finalize;
        cur = right;
        <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">4</span>; k++ )
        {
            c = cur-&gt;<span class="pl-smi">neighbors</span>[k];
            <span class="pl-k">if</span>( c &amp;&amp; c-&gt;<span class="pl-smi">row</span> &gt; <span class="pl-c1">0</span> )
            {
                <span class="pl-k">for</span>( kk = <span class="pl-c1">0</span>; kk &lt; <span class="pl-c1">4</span>; kk++ )
                {
                    <span class="pl-k">if</span>( c-&gt;<span class="pl-smi">neighbors</span>[kk] == below )
                        <span class="pl-k">break</span>;
                }
                <span class="pl-k">if</span>( kk &lt; <span class="pl-c1">4</span> )
                    below = c;
                <span class="pl-k">else</span>
                    right = c;
            }
        }
    }

    width = out_corner_count;
    <span class="pl-k">if</span>( width == pattern_size.<span class="pl-smi">width</span> )
        height = pattern_size.<span class="pl-smi">height</span>;
    <span class="pl-k">else</span> <span class="pl-k">if</span>( width == pattern_size.<span class="pl-smi">height</span> )
        height = pattern_size.<span class="pl-smi">width</span>;
    <span class="pl-k">else</span>
        <span class="pl-k">goto</span> finalize;

    <span class="pl-c"><span class="pl-c">//</span> find and store all the other rows</span>
    <span class="pl-k">for</span>( i = <span class="pl-c1">1</span>; ; i++ )
    {
        <span class="pl-k">if</span>( !first )
            <span class="pl-k">break</span>;
        cur = first;
        first = <span class="pl-c1">0</span>;
        <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>;; j++ )
        {
            cur-&gt;<span class="pl-smi">row</span> = i;
            out_corners[out_corner_count++] = cur;
            <span class="pl-c"><span class="pl-c">//</span>cvCircle( debug_img, cvPointFrom32f(cur-&gt;pt), 3, cvScalar(0,0,255-j*10), -1, 8, 0 );</span>
            <span class="pl-k">if</span>( cur-&gt;<span class="pl-smi">count</span> == <span class="pl-c1">2</span> + (i &lt; height-<span class="pl-c1">1</span>) &amp;&amp; j &gt; <span class="pl-c1">0</span> )
                <span class="pl-k">break</span>;

            right = <span class="pl-c1">0</span>;

            <span class="pl-c"><span class="pl-c">//</span> find a neighbor that has not been processed yet</span>
            <span class="pl-c"><span class="pl-c">//</span> and that has a neighbor from the previous row</span>
            <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; <span class="pl-c1">4</span>; k++ )
            {
                c = cur-&gt;<span class="pl-smi">neighbors</span>[k];
                <span class="pl-k">if</span>( c &amp;&amp; c-&gt;<span class="pl-smi">row</span> &gt; i )
                {
                    <span class="pl-k">for</span>( kk = <span class="pl-c1">0</span>; kk &lt; <span class="pl-c1">4</span>; kk++ )
                    {
                        <span class="pl-k">if</span>( c-&gt;<span class="pl-smi">neighbors</span>[kk] &amp;&amp; c-&gt;<span class="pl-smi">neighbors</span>[kk]-&gt;<span class="pl-smi">row</span> == i-<span class="pl-c1">1</span> )
                            <span class="pl-k">break</span>;
                    }
                    <span class="pl-k">if</span>( kk &lt; <span class="pl-c1">4</span> )
                    {
                        right = c;
                        <span class="pl-k">if</span>( j &gt; <span class="pl-c1">0</span> )
                            <span class="pl-k">break</span>;
                    }
                    <span class="pl-k">else</span> <span class="pl-k">if</span>( j == <span class="pl-c1">0</span> )
                        first = c;
                }
            }
            <span class="pl-k">if</span>( !right )
                <span class="pl-k">goto</span> finalize;
            cur = right;
        }

        <span class="pl-k">if</span>( j != width - <span class="pl-c1">1</span> )
            <span class="pl-k">goto</span> finalize;
    }

    <span class="pl-k">if</span>( out_corner_count != corner_count )
        <span class="pl-k">goto</span> finalize;

    <span class="pl-c"><span class="pl-c">//</span> check if we need to transpose the board</span>
    <span class="pl-k">if</span>( width != pattern_size.<span class="pl-smi">width</span> )
    {
        <span class="pl-c1">CV_SWAP</span>( width, height, k );

        <span class="pl-c1">memcpy</span>( &amp;corners[<span class="pl-c1">0</span>], out_corners, corner_count*<span class="pl-k">sizeof</span>(corners[<span class="pl-c1">0</span>]) );
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; height; i++ )
            <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; width; j++ )
                out_corners[i*width + j] = corners[j*height + i];
    }

    <span class="pl-c"><span class="pl-c">//</span> check if we need to revert the order in each row</span>
    {
        CvPoint2D32f p0 = out_corners[<span class="pl-c1">0</span>]-&gt;<span class="pl-smi">pt</span>, p1 = out_corners[pattern_size.<span class="pl-smi">width</span>-<span class="pl-c1">1</span>]-&gt;<span class="pl-smi">pt</span>,
                     p2 = out_corners[pattern_size.<span class="pl-smi">width</span>]-&gt;<span class="pl-smi">pt</span>;
        <span class="pl-k">if</span>( (p1.<span class="pl-smi">x</span> - p0.<span class="pl-smi">x</span>)*(p2.<span class="pl-smi">y</span> - p1.<span class="pl-smi">y</span>) - (p1.<span class="pl-smi">y</span> - p0.<span class="pl-smi">y</span>)*(p2.<span class="pl-smi">x</span> - p1.<span class="pl-smi">x</span>) &lt; <span class="pl-c1">0</span> )
        {
            <span class="pl-k">if</span>( width % <span class="pl-c1">2</span> == <span class="pl-c1">0</span> )
            {
                <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; height; i++ )
                    <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; width/<span class="pl-c1">2</span>; j++ )
                        <span class="pl-c1">CV_SWAP</span>( out_corners[i*width+j], out_corners[i*width+width-j-<span class="pl-c1">1</span>], c );
            }
            <span class="pl-k">else</span>
            {
                <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; width; j++ )
                    <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; height/<span class="pl-c1">2</span>; i++ )
                        <span class="pl-c1">CV_SWAP</span>( out_corners[i*width+j], out_corners[(height - i - <span class="pl-c1">1</span>)*width+j], c );
            }
        }
    }

    result = corner_count;

finalize:

    <span class="pl-k">if</span>( result &lt;= <span class="pl-c1">0</span> )
    {
        corner_count = <span class="pl-c1">MIN</span>( corner_count, pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span> );
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; corner_count; i++ )
            out_corners[i] = corners[i];
        result = -corner_count;

        <span class="pl-k">if</span> (result == -pattern_size.<span class="pl-smi">width</span>*pattern_size.<span class="pl-smi">height</span>)
            result = -result;
    }

    <span class="pl-k">return</span> result;
}




<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

<span class="pl-k">static</span> <span class="pl-k">void</span> <span class="pl-en">icvFindQuadNeighbors</span>( CvCBQuad *quads, <span class="pl-k">int</span> quad_count )
{
    <span class="pl-k">const</span> <span class="pl-k">float</span> thresh_scale = <span class="pl-c1">1</span>.<span class="pl-smi">f</span>;
    <span class="pl-k">int</span> idx, i, k, j;
    <span class="pl-k">float</span> dx, dy, dist;

    <span class="pl-c"><span class="pl-c">//</span> find quad neighbors</span>
    <span class="pl-k">for</span>( idx = <span class="pl-c1">0</span>; idx &lt; quad_count; idx++ )
    {
        CvCBQuad* cur_quad = &amp;quads[idx];

        <span class="pl-c"><span class="pl-c">//</span> choose the points of the current quadrangle that are close to</span>
        <span class="pl-c"><span class="pl-c">//</span> some points of the other quadrangles</span>
        <span class="pl-c"><span class="pl-c">//</span> (it can happen for split corners (due to dilation) of the</span>
        <span class="pl-c"><span class="pl-c">//</span> checker board). Search only in other quadrangles!</span>

        <span class="pl-c"><span class="pl-c">//</span> for each corner of this quadrangle</span>
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
        {
            CvPoint2D32f pt;
            <span class="pl-k">float</span> min_dist = FLT_MAX;
            <span class="pl-k">int</span> closest_corner_idx = -<span class="pl-c1">1</span>;
            CvCBQuad *closest_quad = <span class="pl-c1">0</span>;
            CvCBCorner *closest_corner = <span class="pl-c1">0</span>;

            <span class="pl-k">if</span>( cur_quad-&gt;<span class="pl-smi">neighbors</span>[i] )
                <span class="pl-k">continue</span>;

            pt = cur_quad-&gt;<span class="pl-smi">corners</span>[i]-&gt;<span class="pl-smi">pt</span>;

            <span class="pl-c"><span class="pl-c">//</span> find the closest corner in all other quadrangles</span>
            <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; quad_count; k++ )
            {
                <span class="pl-k">if</span>( k == idx )
                    <span class="pl-k">continue</span>;

                <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
                {
                    <span class="pl-k">if</span>( quads[k].<span class="pl-smi">neighbors</span>[j] )
                        <span class="pl-k">continue</span>;

                    dx = pt.<span class="pl-smi">x</span> - quads[k].<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span>;
                    dy = pt.<span class="pl-smi">y</span> - quads[k].<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>;
                    dist = dx * dx + dy * dy;

                    <span class="pl-k">if</span>( dist &lt; min_dist &amp;&amp;
                        dist &lt;= cur_quad-&gt;<span class="pl-smi">edge_len</span>*thresh_scale &amp;&amp;
                        dist &lt;= quads[k].<span class="pl-smi">edge_len</span>*thresh_scale )
                    {
                        <span class="pl-c"><span class="pl-c">//</span> check edge lengths, make sure they're compatible</span>
                        <span class="pl-c"><span class="pl-c">//</span> edges that are different by more than 1:4 are rejected</span>
                        <span class="pl-k">float</span> ediff = cur_quad-&gt;<span class="pl-smi">edge_len</span> - quads[k].<span class="pl-smi">edge_len</span>;
                        <span class="pl-k">if</span> (ediff &gt; <span class="pl-c1">32</span>*cur_quad-&gt;<span class="pl-smi">edge_len</span> ||
                            ediff &gt; <span class="pl-c1">32</span>*quads[k].<span class="pl-smi">edge_len</span>)
                        {
                            <span class="pl-c1">PRINTF</span>(<span class="pl-s"><span class="pl-pds">"</span>Incompatible edge lengths<span class="pl-cce">\n</span><span class="pl-pds">"</span></span>);
                            <span class="pl-k">continue</span>;
                        }
                        closest_corner_idx = j;
                        closest_quad = &amp;quads[k];
                        min_dist = dist;
                    }
                }
            }

            <span class="pl-c"><span class="pl-c">//</span> we found a matching corner point?</span>
            <span class="pl-k">if</span>( closest_corner_idx &gt;= <span class="pl-c1">0</span> &amp;&amp; min_dist &lt; FLT_MAX )
            {
                <span class="pl-c"><span class="pl-c">//</span> If another point from our current quad is closer to the found corner</span>
                <span class="pl-c"><span class="pl-c">//</span> than the current one, then we don't count this one after all.</span>
                <span class="pl-c"><span class="pl-c">//</span> This is necessary to support small squares where otherwise the wrong</span>
                <span class="pl-c"><span class="pl-c">//</span> corner will get matched to closest_quad;</span>
                closest_corner = closest_quad-&gt;<span class="pl-smi">corners</span>[closest_corner_idx];

                <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
                {
                    <span class="pl-k">if</span>( cur_quad-&gt;<span class="pl-smi">neighbors</span>[j] == closest_quad )
                        <span class="pl-k">break</span>;

                    dx = closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> - cur_quad-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span>;
                    dy = closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> - cur_quad-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>;

                    <span class="pl-k">if</span>( dx * dx + dy * dy &lt; min_dist )
                        <span class="pl-k">break</span>;
                }

                <span class="pl-k">if</span>( j &lt; <span class="pl-c1">4</span> || cur_quad-&gt;<span class="pl-smi">count</span> &gt;= <span class="pl-c1">4</span> || closest_quad-&gt;<span class="pl-smi">count</span> &gt;= <span class="pl-c1">4</span> )
                    <span class="pl-k">continue</span>;

                <span class="pl-c"><span class="pl-c">//</span> Check that each corner is a neighbor of different quads</span>
                <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; closest_quad-&gt;<span class="pl-smi">count</span>; j++ )
                {
                    <span class="pl-k">if</span>( closest_quad-&gt;<span class="pl-smi">neighbors</span>[j] == cur_quad )
                        <span class="pl-k">break</span>;
                }
                <span class="pl-k">if</span>( j &lt; closest_quad-&gt;<span class="pl-smi">count</span> )
                    <span class="pl-k">continue</span>;

                <span class="pl-c"><span class="pl-c">//</span> check whether the closest corner to closest_corner</span>
                <span class="pl-c"><span class="pl-c">//</span> is different from cur_quad-&gt;corners[i]-&gt;pt</span>
                <span class="pl-k">for</span>( k = <span class="pl-c1">0</span>; k &lt; quad_count; k++ )
                {
                    CvCBQuad* q = &amp;quads[k];
                    <span class="pl-k">if</span>( k == idx || q == closest_quad )
                        <span class="pl-k">continue</span>;

                    <span class="pl-k">for</span>( j = <span class="pl-c1">0</span>; j &lt; <span class="pl-c1">4</span>; j++ )
                        <span class="pl-k">if</span>( !q-&gt;<span class="pl-smi">neighbors</span>[j] )
                        {
                            dx = closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> - q-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span>;
                            dy = closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> - q-&gt;<span class="pl-smi">corners</span>[j]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>;
                            dist = dx*dx + dy*dy;
                            <span class="pl-k">if</span>( dist &lt; min_dist )
                                <span class="pl-k">break</span>;
                        }
                    <span class="pl-k">if</span>( j &lt; <span class="pl-c1">4</span> )
                        <span class="pl-k">break</span>;
                }

                <span class="pl-k">if</span>( k &lt; quad_count )
                    <span class="pl-k">continue</span>;

                closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> = (pt.<span class="pl-smi">x</span> + closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span>) * <span class="pl-c1">0</span>.<span class="pl-c1">5f</span>;
                closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> = (pt.<span class="pl-smi">y</span> + closest_corner-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>) * <span class="pl-c1">0</span>.<span class="pl-c1">5f</span>;

                <span class="pl-c"><span class="pl-c">//</span> We've found one more corner - remember it</span>
                cur_quad-&gt;<span class="pl-smi">count</span>++;
                cur_quad-&gt;<span class="pl-smi">neighbors</span>[i] = closest_quad;
                cur_quad-&gt;<span class="pl-smi">corners</span>[i] = closest_corner;

                closest_quad-&gt;<span class="pl-smi">count</span>++;
                closest_quad-&gt;<span class="pl-smi">neighbors</span>[closest_corner_idx] = cur_quad;
            }
        }
    }
}

<span class="pl-c"><span class="pl-c">//</span>=====================================================================================</span>

<span class="pl-c"><span class="pl-c">//</span> returns corners in clockwise order</span>
<span class="pl-c"><span class="pl-c">//</span> corners don't necessarily start at same position on quad (e.g.,</span>
<span class="pl-c"><span class="pl-c">//</span>   top left corner)</span>

<span class="pl-k">static</span> <span class="pl-k">int</span>
<span class="pl-en">icvGenerateQuads</span>( CvCBQuad **out_quads, CvCBCorner **out_corners,
                  CvMemStorage *storage, CvMat *image, <span class="pl-k">int</span> flags, <span class="pl-k">int</span> *max_quad_buf_size )
{
    <span class="pl-k">int</span> quad_count = <span class="pl-c1">0</span>;
    cv::<span class="pl-c1">Ptr</span>&lt;CvMemStorage&gt; temp_storage;

    <span class="pl-k">if</span>( out_quads )
        *out_quads = <span class="pl-c1">0</span>;

    <span class="pl-k">if</span>( out_corners )
        *out_corners = <span class="pl-c1">0</span>;

    CvSeq *src_contour = <span class="pl-c1">0</span>;
    CvSeq *root;
    CvContourEx* board = <span class="pl-c1">0</span>;
    CvContourScanner scanner;
    <span class="pl-k">int</span> i, idx, min_size;

    <span class="pl-c1">CV_Assert</span>( out_corners &amp;&amp; out_quads );

    <span class="pl-c"><span class="pl-c">//</span> empiric bound for minimal allowed perimeter for squares</span>
    min_size = <span class="pl-c1">25</span>; <span class="pl-c"><span class="pl-c">//</span>cvRound( image-&gt;cols * image-&gt;rows * .03 * 0.01 * 0.92 );</span>

    <span class="pl-c"><span class="pl-c">//</span> create temporary storage for contours and the sequence of pointers to found quadrangles</span>
    temp_storage = <span class="pl-c1">cvCreateChildMemStorage</span>( storage );
    root = <span class="pl-c1">cvCreateSeq</span>( <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(CvSeq), <span class="pl-k">sizeof</span>(CvSeq*), temp_storage );

    <span class="pl-c"><span class="pl-c">//</span> initialize contour retrieving routine</span>
    scanner = <span class="pl-c1">cvStartFindContours</span>( image, temp_storage, <span class="pl-k">sizeof</span>(CvContourEx),
                                   CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

    <span class="pl-c"><span class="pl-c">//</span> get all the contours one by one</span>
    <span class="pl-k">while</span>( (src_contour = <span class="pl-c1">cvFindNextContour</span>( scanner )) != <span class="pl-c1">0</span> )
    {
        CvSeq *dst_contour = <span class="pl-c1">0</span>;
        CvRect rect = ((CvContour*)src_contour)-&gt;<span class="pl-smi">rect</span>;

        <span class="pl-c"><span class="pl-c">//</span> reject contours with too small perimeter</span>
        <span class="pl-k">if</span>( <span class="pl-c1">CV_IS_SEQ_HOLE</span>(src_contour) &amp;&amp; rect.<span class="pl-smi">width</span>*rect.<span class="pl-smi">height</span> &gt;= min_size )
        {
            <span class="pl-k">const</span> <span class="pl-k">int</span> min_approx_level = <span class="pl-c1">1</span>, max_approx_level = MAX_CONTOUR_APPROX;
            <span class="pl-k">int</span> approx_level;
            <span class="pl-k">for</span>( approx_level = min_approx_level; approx_level &lt;= max_approx_level; approx_level++ )
            {
                dst_contour = <span class="pl-c1">cvApproxPoly</span>( src_contour, <span class="pl-k">sizeof</span>(CvContour), temp_storage,
                                            CV_POLY_APPROX_DP, (<span class="pl-k">float</span>)approx_level );
                <span class="pl-k">if</span>( dst_contour-&gt;<span class="pl-smi">total</span> == <span class="pl-c1">4</span> )
                    <span class="pl-k">break</span>;

                <span class="pl-c"><span class="pl-c">//</span> we call this again on its own output, because sometimes</span>
                <span class="pl-c"><span class="pl-c">//</span> cvApproxPoly() does not simplify as much as it should.</span>
                dst_contour = <span class="pl-c1">cvApproxPoly</span>( dst_contour, <span class="pl-k">sizeof</span>(CvContour), temp_storage,
                                            CV_POLY_APPROX_DP, (<span class="pl-k">float</span>)approx_level );

                <span class="pl-k">if</span>( dst_contour-&gt;<span class="pl-smi">total</span> == <span class="pl-c1">4</span> )
                    <span class="pl-k">break</span>;
            }

            <span class="pl-c"><span class="pl-c">//</span> reject non-quadrangles</span>
            <span class="pl-k">if</span>( dst_contour-&gt;<span class="pl-smi">total</span> == <span class="pl-c1">4</span> &amp;&amp; <span class="pl-c1">cvCheckContourConvexity</span>(dst_contour) )
            {
                CvPoint pt[<span class="pl-c1">4</span>];
                <span class="pl-k">double</span> d1, d2, p = <span class="pl-c1">cvContourPerimeter</span>(dst_contour);
                <span class="pl-k">double</span> area = <span class="pl-c1">fabs</span>(<span class="pl-c1">cvContourArea</span>(dst_contour, CV_WHOLE_SEQ));
                <span class="pl-k">double</span> dx, dy;

                <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
                    pt[i] = *(CvPoint*)<span class="pl-c1">cvGetSeqElem</span>(dst_contour, i);

                dx = pt[<span class="pl-c1">0</span>].<span class="pl-smi">x</span> - pt[<span class="pl-c1">2</span>].<span class="pl-smi">x</span>;
                dy = pt[<span class="pl-c1">0</span>].<span class="pl-smi">y</span> - pt[<span class="pl-c1">2</span>].<span class="pl-smi">y</span>;
                d1 = <span class="pl-c1">sqrt</span>(dx*dx + dy*dy);

                dx = pt[<span class="pl-c1">1</span>].<span class="pl-smi">x</span> - pt[<span class="pl-c1">3</span>].<span class="pl-smi">x</span>;
                dy = pt[<span class="pl-c1">1</span>].<span class="pl-smi">y</span> - pt[<span class="pl-c1">3</span>].<span class="pl-smi">y</span>;
                d2 = <span class="pl-c1">sqrt</span>(dx*dx + dy*dy);

                <span class="pl-c"><span class="pl-c">//</span> philipg.  Only accept those quadrangles which are more square</span>
                <span class="pl-c"><span class="pl-c">//</span> than rectangular and which are big enough</span>
                <span class="pl-k">double</span> d3, d4;
                dx = pt[<span class="pl-c1">0</span>].<span class="pl-smi">x</span> - pt[<span class="pl-c1">1</span>].<span class="pl-smi">x</span>;
                dy = pt[<span class="pl-c1">0</span>].<span class="pl-smi">y</span> - pt[<span class="pl-c1">1</span>].<span class="pl-smi">y</span>;
                d3 = <span class="pl-c1">sqrt</span>(dx*dx + dy*dy);
                dx = pt[<span class="pl-c1">1</span>].<span class="pl-smi">x</span> - pt[<span class="pl-c1">2</span>].<span class="pl-smi">x</span>;
                dy = pt[<span class="pl-c1">1</span>].<span class="pl-smi">y</span> - pt[<span class="pl-c1">2</span>].<span class="pl-smi">y</span>;
                d4 = <span class="pl-c1">sqrt</span>(dx*dx + dy*dy);
                <span class="pl-k">if</span>( !(flags &amp; CV_CALIB_CB_FILTER_QUADS) ||
                    (d3*<span class="pl-c1">4</span> &gt; d4 &amp;&amp; d4*<span class="pl-c1">4</span> &gt; d3 &amp;&amp; d3*d4 &lt; area*<span class="pl-c1">1.5</span> &amp;&amp; area &gt; min_size &amp;&amp;
                    d1 &gt;= <span class="pl-c1">0.15</span> * p &amp;&amp; d2 &gt;= <span class="pl-c1">0.15</span> * p) )
                {
                    CvContourEx* parent = (CvContourEx*)(src_contour-&gt;<span class="pl-smi">v_prev</span>);
                    parent-&gt;<span class="pl-smi">counter</span>++;
                    <span class="pl-k">if</span>( !board || board-&gt;<span class="pl-smi">counter</span> &lt; parent-&gt;<span class="pl-smi">counter</span> )
                        board = parent;
                    dst_contour-&gt;<span class="pl-smi">v_prev</span> = (CvSeq*)parent;
                    <span class="pl-c"><span class="pl-c">//</span>for( i = 0; i &lt; 4; i++ ) cvLine( debug_img, pt[i], pt[(i+1)&amp;3], cvScalar(200,255,255), 1, CV_AA, 0 );</span>
                    <span class="pl-c1">cvSeqPush</span>( root, &amp;dst_contour );
                }
            }
        }
    }

    <span class="pl-c"><span class="pl-c">//</span> finish contour retrieving</span>
    <span class="pl-c1">cvEndFindContours</span>( &amp;scanner );

    <span class="pl-c"><span class="pl-c">//</span> allocate quad &amp; corner buffers</span>
    *max_quad_buf_size = <span class="pl-c1">MAX</span>(<span class="pl-c1">1</span>, (root-&gt;<span class="pl-smi">total</span>+root-&gt;<span class="pl-smi">total</span> / <span class="pl-c1">2</span>)) * <span class="pl-c1">2</span>; 
    *out_quads = (CvCBQuad*)<span class="pl-c1">cvAlloc</span>(*max_quad_buf_size * <span class="pl-k">sizeof</span>((*out_quads)[<span class="pl-c1">0</span>]));
    *out_corners = (CvCBCorner*)<span class="pl-c1">cvAlloc</span>(*max_quad_buf_size * <span class="pl-c1">4</span> * <span class="pl-k">sizeof</span>((*out_corners)[<span class="pl-c1">0</span>]));

    <span class="pl-c"><span class="pl-c">//</span> Create array of quads structures</span>
    <span class="pl-k">for</span>( idx = <span class="pl-c1">0</span>; idx &lt; root-&gt;<span class="pl-smi">total</span>; idx++ )
    {
        CvCBQuad* q = &amp;(*out_quads)[quad_count];
        src_contour = *(CvSeq**)<span class="pl-c1">cvGetSeqElem</span>( root, idx );
        <span class="pl-k">if</span>( (flags &amp; CV_CALIB_CB_FILTER_QUADS) &amp;&amp; src_contour-&gt;<span class="pl-smi">v_prev</span> != (CvSeq*)board )
            <span class="pl-k">continue</span>;

        <span class="pl-c"><span class="pl-c">//</span> reset group ID</span>
        <span class="pl-c1">memset</span>( q, <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(*q) );
        q-&gt;<span class="pl-smi">group_idx</span> = -<span class="pl-c1">1</span>;
        <span class="pl-c1">assert</span>( src_contour-&gt;<span class="pl-smi">total</span> == <span class="pl-c1">4</span> );
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
        {
            CvPoint2D32f pt = <span class="pl-c1">cvPointTo32f</span>(*(CvPoint*)<span class="pl-c1">cvGetSeqElem</span>(src_contour, i));
            CvCBCorner* corner = &amp;(*out_corners)[quad_count*<span class="pl-c1">4</span> + i];

            <span class="pl-c1">memset</span>( corner, <span class="pl-c1">0</span>, <span class="pl-k">sizeof</span>(*corner) );
            corner-&gt;<span class="pl-smi">pt</span> = pt;
            q-&gt;<span class="pl-smi">corners</span>[i] = corner;
        }
        q-&gt;<span class="pl-smi">edge_len</span> = FLT_MAX;
        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; <span class="pl-c1">4</span>; i++ )
        {
            <span class="pl-k">float</span> dx = q-&gt;<span class="pl-smi">corners</span>[i]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span> - q-&gt;<span class="pl-smi">corners</span>[(i+<span class="pl-c1">1</span>)&amp;<span class="pl-c1">3</span>]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">x</span>;
            <span class="pl-k">float</span> dy = q-&gt;<span class="pl-smi">corners</span>[i]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span> - q-&gt;<span class="pl-smi">corners</span>[(i+<span class="pl-c1">1</span>)&amp;<span class="pl-c1">3</span>]-&gt;<span class="pl-smi">pt</span>.<span class="pl-smi">y</span>;
            <span class="pl-k">float</span> d = dx*dx + dy*dy;
            <span class="pl-k">if</span>( q-&gt;<span class="pl-smi">edge_len</span> &gt; d )
                q-&gt;<span class="pl-smi">edge_len</span> = d;
        }
        quad_count++;
    }

    <span class="pl-k">return</span> quad_count;
}


CV_IMPL <span class="pl-k">void</span>
<span class="pl-en">cvDrawChessboardCorners</span>( CvArr* _image, CvSize pattern_size,
                         CvPoint2D32f* corners, <span class="pl-k">int</span> count, <span class="pl-k">int</span> found )
{
    <span class="pl-k">const</span> <span class="pl-k">int</span> shift = <span class="pl-c1">0</span>;
    <span class="pl-k">const</span> <span class="pl-k">int</span> radius = <span class="pl-c1">4</span>;
    <span class="pl-k">const</span> <span class="pl-k">int</span> r = radius*(<span class="pl-c1">1</span> &lt;&lt; shift);
    <span class="pl-k">int</span> i;
    CvMat stub, *image;
    <span class="pl-k">double</span> scale = <span class="pl-c1">1</span>;
    <span class="pl-k">int</span> type, cn, line_type;

    image = <span class="pl-c1">cvGetMat</span>( _image, &amp;stub );

    type = <span class="pl-c1">CV_MAT_TYPE</span>(image-&gt;<span class="pl-smi">type</span>);
    cn = <span class="pl-c1">CV_MAT_CN</span>(type);
    <span class="pl-k">if</span>( cn != <span class="pl-c1">1</span> &amp;&amp; cn != <span class="pl-c1">3</span> &amp;&amp; cn != <span class="pl-c1">4</span> )
        <span class="pl-c1">CV_Error</span>( CV_StsUnsupportedFormat, <span class="pl-s"><span class="pl-pds">"</span>Number of channels must be 1, 3 or 4<span class="pl-pds">"</span></span> );

    <span class="pl-k">switch</span>( <span class="pl-c1">CV_MAT_DEPTH</span>(image-&gt;<span class="pl-smi">type</span>) )
    {
    <span class="pl-k">case</span> CV_8U:
        scale = <span class="pl-c1">1</span>;
        <span class="pl-k">break</span>;
    <span class="pl-k">case</span> CV_16U:
        scale = <span class="pl-c1">256</span>;
        <span class="pl-k">break</span>;
    <span class="pl-k">case</span> CV_32F:
        scale = <span class="pl-c1">1</span>./<span class="pl-c1">255</span>;
        <span class="pl-k">break</span>;
    <span class="pl-k">default</span>:
        <span class="pl-c1">CV_Error</span>( CV_StsUnsupportedFormat,
            <span class="pl-s"><span class="pl-pds">"</span>Only 8-bit, 16-bit or floating-point 32-bit images are supported<span class="pl-pds">"</span></span> );
    }

    line_type = type == CV_8UC1 || type == CV_8UC3 ? CV_AA : <span class="pl-c1">8</span>;

    <span class="pl-k">if</span>( !found )
    {
        CvScalar color = {{<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">255</span>}};
        <span class="pl-k">if</span>( cn == <span class="pl-c1">1</span> )
            color = <span class="pl-c1">cvScalarAll</span>(<span class="pl-c1">200</span>);
        color.<span class="pl-smi">val</span>[<span class="pl-c1">0</span>] *= scale;
        color.<span class="pl-smi">val</span>[<span class="pl-c1">1</span>] *= scale;
        color.<span class="pl-smi">val</span>[<span class="pl-c1">2</span>] *= scale;
        color.<span class="pl-smi">val</span>[<span class="pl-c1">3</span>] *= scale;

        <span class="pl-k">for</span>( i = <span class="pl-c1">0</span>; i &lt; count; i++ )
        {
            CvPoint pt;
            pt.<span class="pl-smi">x</span> = <span class="pl-c1">cvRound</span>(corners[i].<span class="pl-smi">x</span>*(<span class="pl-c1">1</span> &lt;&lt; shift));
            pt.<span class="pl-smi">y</span> = <span class="pl-c1">cvRound</span>(corners[i].<span class="pl-smi">y</span>*(<span class="pl-c1">1</span> &lt;&lt; shift));
            <span class="pl-c1">cvLine</span>( image, <span class="pl-c1">cvPoint</span>( pt.<span class="pl-smi">x</span> - r, pt.<span class="pl-smi">y</span> - r ),
                    <span class="pl-c1">cvPoint</span>( pt.<span class="pl-smi">x</span> + r, pt.<span class="pl-smi">y</span> + r ), color, <span class="pl-c1">1</span>, line_type, shift );
            <span class="pl-c1">cvLine</span>( image, <span class="pl-c1">cvPoint</span>( pt.<span class="pl-smi">x</span> - r, pt.<span class="pl-smi">y</span> + r),
                    <span class="pl-c1">cvPoint</span>( pt.<span class="pl-smi">x</span> + r, pt.<span class="pl-smi">y</span> - r), color, <span class="pl-c1">1</span>, line_type, shift );
            <span class="pl-c1">cvCircle</span>( image, pt, r+(<span class="pl-c1">1</span>&lt;&lt;shift), color, <span class="pl-c1">1</span>, line_type, shift );
        }
    }
    <span class="pl-k">else</span>
    {
        <span class="pl-k">int</span> x, y;
        CvPoint prev_pt = {<span class="pl-c1">0</span>, <span class="pl-c1">0</span>};
        <span class="pl-k">const</span> <span class="pl-k">int</span> line_max = <span class="pl-c1">7</span>;
        <span class="pl-k">static</span> <span class="pl-k">const</span> CvScalar line_colors[line_max] =
        {
            {{<span class="pl-c1">0</span>,<span class="pl-c1">0</span>,<span class="pl-c1">255</span>}},
            {{<span class="pl-c1">0</span>,<span class="pl-c1">128</span>,<span class="pl-c1">255</span>}},
            {{<span class="pl-c1">0</span>,<span class="pl-c1">200</span>,<span class="pl-c1">200</span>}},
            {{<span class="pl-c1">0</span>,<span class="pl-c1">255</span>,<span class="pl-c1">0</span>}},
            {{<span class="pl-c1">200</span>,<span class="pl-c1">200</span>,<span class="pl-c1">0</span>}},
            {{<span class="pl-c1">255</span>,<span class="pl-c1">0</span>,<span class="pl-c1">0</span>}},
            {{<span class="pl-c1">255</span>,<span class="pl-c1">0</span>,<span class="pl-c1">255</span>}}
        };

        <span class="pl-k">for</span>( y = <span class="pl-c1">0</span>, i = <span class="pl-c1">0</span>; y &lt; pattern_size.<span class="pl-smi">height</span>; y++ )
        {
            CvScalar color = line_colors[y % line_max];
            <span class="pl-k">if</span>( cn == <span class="pl-c1">1</span> )
                color = <span class="pl-c1">cvScalarAll</span>(<span class="pl-c1">200</span>);
            color.<span class="pl-smi">val</span>[<span class="pl-c1">0</span>] *= scale;
            color.<span class="pl-smi">val</span>[<span class="pl-c1">1</span>] *= scale;
            color.<span class="pl-smi">val</span>[<span class="pl-c1">2</span>] *= scale;
            color.<span class="pl-smi">val</span>[<span class="pl-c1">3</span>] *= scale;

            <span class="pl-k">for</span>( x = <span class="pl-c1">0</span>; x &lt; pattern_size.<span class="pl-smi">width</span>; x++, i++ )
            {
                CvPoint pt;
                pt.<span class="pl-smi">x</span> = <span class="pl-c1">cvRound</span>(corners[i].<span class="pl-smi">x</span>*(<span class="pl-c1">1</span> &lt;&lt; shift));
                pt.<span class="pl-smi">y</span> = <span class="pl-c1">cvRound</span>(corners[i].<span class="pl-smi">y</span>*(<span class="pl-c1">1</span> &lt;&lt; shift));

                <span class="pl-k">if</span>( i != <span class="pl-c1">0</span> )
                    <span class="pl-c1">cvLine</span>( image, prev_pt, pt, color, <span class="pl-c1">1</span>, line_type, shift );

                <span class="pl-c1">cvLine</span>( image, <span class="pl-c1">cvPoint</span>(pt.<span class="pl-smi">x</span> - r, pt.<span class="pl-smi">y</span> - r),
                        <span class="pl-c1">cvPoint</span>(pt.<span class="pl-smi">x</span> + r, pt.<span class="pl-smi">y</span> + r), color, <span class="pl-c1">1</span>, line_type, shift );
                <span class="pl-c1">cvLine</span>( image, <span class="pl-c1">cvPoint</span>(pt.<span class="pl-smi">x</span> - r, pt.<span class="pl-smi">y</span> + r),
                        <span class="pl-c1">cvPoint</span>(pt.<span class="pl-smi">x</span> + r, pt.<span class="pl-smi">y</span> - r), color, <span class="pl-c1">1</span>, line_type, shift );
                <span class="pl-c1">cvCircle</span>( image, pt, r+(<span class="pl-c1">1</span>&lt;&lt;shift), color, <span class="pl-c1">1</span>, line_type, shift );
                prev_pt = pt;
            }
        }
    }
}

<span class="pl-k">bool</span> <span class="pl-en">cv::findChessboardCorners</span>( InputArray _image, <span class="pl-c1">Size</span> patternSize,
                            OutputArray corners, <span class="pl-k">int</span> flags )
{
    <span class="pl-k">int</span> count = patternSize.<span class="pl-c1">area</span>()*<span class="pl-c1">2</span>;
    vector&lt;Point2f&gt; <span class="pl-c1">tmpcorners</span>(count+<span class="pl-c1">1</span>);
    Mat image = _image.<span class="pl-c1">getMat</span>(); CvMat c_image = image;
    <span class="pl-k">bool</span> ok = <span class="pl-c1">cvFindChessboardCorners</span>(&amp;c_image, patternSize,
        (CvPoint2D32f*)&amp;tmpcorners[<span class="pl-c1">0</span>], &amp;count, flags ) &gt; <span class="pl-c1">0</span>;
    <span class="pl-k">if</span>( count &gt; <span class="pl-c1">0</span> )
    {
        tmpcorners.<span class="pl-c1">resize</span>(count);
        <span class="pl-c1">Mat</span>(tmpcorners).<span class="pl-c1">copyTo</span>(corners);
    }
    <span class="pl-k">else</span>
        corners.<span class="pl-c1">release</span>();
    <span class="pl-k">return</span> ok;
}

<span class="pl-k">namespace</span>
{
<span class="pl-k">int</span> <span class="pl-en">quiet_error</span>(<span class="pl-k">int</span> <span class="pl-c"><span class="pl-c">/*</span>status<span class="pl-c">*/</span></span>, <span class="pl-k">const</span> <span class="pl-k">char</span>* <span class="pl-c"><span class="pl-c">/*</span>func_name<span class="pl-c">*/</span></span>,
                                       <span class="pl-k">const</span> <span class="pl-k">char</span>* <span class="pl-c"><span class="pl-c">/*</span>err_msg<span class="pl-c">*/</span></span>, <span class="pl-k">const</span> <span class="pl-k">char</span>* <span class="pl-c"><span class="pl-c">/*</span>file_name<span class="pl-c">*/</span></span>,
                                       <span class="pl-k">int</span> <span class="pl-c"><span class="pl-c">/*</span>line<span class="pl-c">*/</span></span>, <span class="pl-k">void</span>* <span class="pl-c"><span class="pl-c">/*</span>userdata<span class="pl-c">*/</span></span> )
{
  <span class="pl-k">return</span> <span class="pl-c1">0</span>;
}
}

<span class="pl-k">void</span> <span class="pl-en">cv::drawChessboardCorners</span>( InputOutputArray _image, <span class="pl-c1">Size</span> patternSize,
                            InputArray _corners,
                            <span class="pl-k">bool</span> patternWasFound )
{
    Mat corners = _corners.<span class="pl-c1">getMat</span>();
    <span class="pl-k">if</span>( corners.<span class="pl-c1">empty</span>() )
        <span class="pl-k">return</span>;
    Mat image = _image.<span class="pl-c1">getMat</span>(); CvMat c_image = _image.<span class="pl-c1">getMat</span>();
    <span class="pl-k">int</span> nelems = corners.<span class="pl-c1">checkVector</span>(<span class="pl-c1">2</span>, CV_32F, <span class="pl-c1">true</span>);
    <span class="pl-c1">CV_Assert</span>(nelems &gt;= <span class="pl-c1">0</span>);
    <span class="pl-c1">cvDrawChessboardCorners</span>( &amp;c_image, patternSize, (CvPoint2D32f*)corners.<span class="pl-smi">data</span>,
                             nelems, patternWasFound );
}

<span class="pl-k">bool</span> <span class="pl-en">cv::findCirclesGrid</span>( InputArray _image, <span class="pl-c1">Size</span> patternSize,
                          OutputArray _centers, <span class="pl-k">int</span> flags, <span class="pl-k">const</span> <span class="pl-c1">Ptr</span>&lt;FeatureDetector&gt; &amp;blobDetector )
{
    <span class="pl-k">bool</span> isAsymmetricGrid = (flags &amp; CALIB_CB_ASYMMETRIC_GRID) ? <span class="pl-c1">true</span> : <span class="pl-c1">false</span>;
    <span class="pl-k">bool</span> isSymmetricGrid  = (flags &amp; CALIB_CB_SYMMETRIC_GRID ) ? <span class="pl-c1">true</span> : <span class="pl-c1">false</span>;
    <span class="pl-c1">CV_Assert</span>(isAsymmetricGrid ^ isSymmetricGrid);

    Mat image = _image.<span class="pl-c1">getMat</span>();
    vector&lt;Point2f&gt; centers;

    vector&lt;KeyPoint&gt; keypoints;
    blobDetector-&gt;<span class="pl-c1">detect</span>(image, keypoints);
    vector&lt;Point2f&gt; points;
    <span class="pl-k">for</span> (<span class="pl-c1">size_t</span> i = <span class="pl-c1">0</span>; i &lt; keypoints.<span class="pl-c1">size</span>(); i++)
    {
      points.<span class="pl-c1">push_back</span> (keypoints[i].<span class="pl-smi">pt</span>);
    }

    <span class="pl-k">if</span>(flags &amp; CALIB_CB_CLUSTERING)
    {
      CirclesGridClusterFinder <span class="pl-smi">circlesGridClusterFinder</span>(isAsymmetricGrid);
      circlesGridClusterFinder.<span class="pl-c1">findGrid</span>(points, patternSize, centers);
      <span class="pl-c1">Mat</span>(centers).<span class="pl-c1">copyTo</span>(_centers);
      <span class="pl-k">return</span> !centers.<span class="pl-c1">empty</span>();
    }

    CirclesGridFinderParameters parameters;
    parameters.<span class="pl-smi">vertexPenalty</span> = -<span class="pl-c1">0</span>.<span class="pl-c1">6f</span>;
    parameters.<span class="pl-smi">vertexGain</span> = <span class="pl-c1">1</span>;
    parameters.<span class="pl-smi">existingVertexGain</span> = <span class="pl-c1">10000</span>;
    parameters.<span class="pl-smi">edgeGain</span> = <span class="pl-c1">1</span>;
    parameters.<span class="pl-smi">edgePenalty</span> = -<span class="pl-c1">0</span>.<span class="pl-c1">6f</span>;

    <span class="pl-k">if</span>(flags &amp; CALIB_CB_ASYMMETRIC_GRID)
      parameters.<span class="pl-smi">gridType</span> = CirclesGridFinderParameters::ASYMMETRIC_GRID;
    <span class="pl-k">if</span>(flags &amp; CALIB_CB_SYMMETRIC_GRID)
      parameters.<span class="pl-smi">gridType</span> = CirclesGridFinderParameters::SYMMETRIC_GRID;

    <span class="pl-k">const</span> <span class="pl-k">int</span> attempts = <span class="pl-c1">2</span>;
    <span class="pl-k">const</span> <span class="pl-c1">size_t</span> minHomographyPoints = <span class="pl-c1">4</span>;
    Mat H;
    <span class="pl-k">for</span> (<span class="pl-k">int</span> i = <span class="pl-c1">0</span>; i &lt; attempts; i++)
    {
      centers.<span class="pl-c1">clear</span>();
      CirclesGridFinder <span class="pl-smi">boxFinder</span>(patternSize, points, parameters);
      <span class="pl-k">bool</span> isFound = <span class="pl-c1">false</span>;
#<span class="pl-k">define</span> <span class="pl-en">BE_QUIET</span> <span class="pl-c1">1</span>
#<span class="pl-k">if</span> BE_QUIET
      <span class="pl-k">void</span>* oldCbkData;
      ErrorCallback oldCbk = <span class="pl-c1">redirectError</span>(quiet_error, <span class="pl-c1">0</span>, &amp;oldCbkData);
#<span class="pl-k">endif</span>
      <span class="pl-k">try</span>
      {
        isFound = boxFinder.<span class="pl-c1">findHoles</span>();
      }
      <span class="pl-k">catch</span> (cv::Exception)
      {

      }
#<span class="pl-k">if</span> BE_QUIET
      <span class="pl-c1">redirectError</span>(oldCbk, oldCbkData);
#<span class="pl-k">endif</span>
      <span class="pl-k">if</span> (isFound)
      {
        <span class="pl-k">switch</span>(parameters.<span class="pl-smi">gridType</span>)
        {
          <span class="pl-k">case</span> CirclesGridFinderParameters::SYMMETRIC_GRID:
            boxFinder.<span class="pl-c1">getHoles</span>(centers);
            <span class="pl-k">break</span>;
          <span class="pl-k">case</span> CirclesGridFinderParameters::ASYMMETRIC_GRID:
        boxFinder.<span class="pl-c1">getAsymmetricHoles</span>(centers);
        <span class="pl-k">break</span>;
          <span class="pl-k">default</span>:
            <span class="pl-c1">CV_Error</span>(CV_StsBadArg, <span class="pl-s"><span class="pl-pds">"</span>Unkown pattern type<span class="pl-pds">"</span></span>);
        }

        <span class="pl-k">if</span> (i != <span class="pl-c1">0</span>)
        {
          Mat orgPointsMat;
          <span class="pl-c1">transform</span>(centers, orgPointsMat, H.<span class="pl-c1">inv</span>());
          <span class="pl-c1">convertPointsFromHomogeneous</span>(orgPointsMat, centers);
        }
        <span class="pl-c1">Mat</span>(centers).<span class="pl-c1">copyTo</span>(_centers);
        <span class="pl-k">return</span> <span class="pl-c1">true</span>;
      }

      boxFinder.<span class="pl-c1">getHoles</span>(centers);
      <span class="pl-k">if</span> (i != attempts - <span class="pl-c1">1</span>)
      {
        <span class="pl-k">if</span> (centers.<span class="pl-c1">size</span>() &lt; minHomographyPoints)
          <span class="pl-k">break</span>;
        H = <span class="pl-c1">CirclesGridFinder::rectifyGrid</span>(boxFinder.<span class="pl-c1">getDetectedGridSize</span>(), centers, points, points);
      }
    }
    <span class="pl-c1">Mat</span>(centers).<span class="pl-c1">copyTo</span>(_centers);
    <span class="pl-k">return</span> <span class="pl-c1">false</span>;
}

<span class="pl-c"><span class="pl-c">/*</span> End of file. <span class="pl-c">*/</span></span></pre></div>