cheesboard.patch

Patch for everything above - Mitar M, 2010-08-27 12:47 am

Download (22 kB)

 
calibinit.cpp 2010-08-26 17:09:10.000000000 +0200
61 61

  
62 62
#include "precomp.hpp"
63 63
#include <stdarg.h>
64
#include <limits.h>
64 65

  
65 66
//#define ENABLE_TRIM_COL_ROW
66 67

  
67 68
//#pragma comment(lib, "highgui200d.lib")
68 69
//#define DEBUG_CHESSBOARD
70
//#define DEBUG_CHESSBOARD_EVERY_CORNER
69 71
#ifdef DEBUG_CHESSBOARD
70 72
static int PRINTF( const char* fmt, ... )
71 73
{
......
151 153
icvGenerateQuadsEx( CvCBQuad **out_quads, CvCBCorner **out_corners,
152 154
    CvMemStorage *storage, CvMat *image, CvMat *thresh_img, int dilation, int flags );*/
153 155

  
154
static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count );
156
static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count, cv::Ptr<IplImage> );
155 157

  
156 158
static int icvFindConnectedQuads( CvCBQuad *quads, int quad_count,
157 159
                                  CvCBQuad **quad_group, int group_idx,
......
234 236
    cv::Ptr<IplImage> dbg_img;
235 237
    cv::Ptr<IplImage> dbg1_img;
236 238
    cv::Ptr<IplImage> dbg2_img;
239
    cv::Ptr<IplImage> dbg3_img;
237 240
#endif
238 241
    cv::Ptr<CvMemStorage> storage;
239 242

  
240 243
    CvMat stub, *img = (CvMat*)arr;
241 244

  
242
    int expected_corners_num = (pattern_size.width/2+1)*(pattern_size.height/2+1);
245
    int expected_quad_num = ((pattern_size.width+1)*(pattern_size.height+1)+1)/2;
243 246

  
244 247
    int prev_sqr_size = 0;
245 248

  
......
269 272
    dbg_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
270 273
    dbg1_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
271 274
    dbg2_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
275
    dbg3_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
272 276
#endif
273 277

  
274 278
    if( CV_MAT_CN(img->type) != 1 || (flags & CV_CALIB_CB_NORMALIZE_IMAGE) )
......
320 324
                // Run multi-level quads extraction
321 325
                // In case one-level binarization did not give enough number of quads
322 326
                CV_CALL( quad_count = icvGenerateQuadsEx( &quads, &corners, storage, img, thresh_img, dilations, flags ));
323
                PRINTF("EX quad count: %d/%d\n", quad_count, expected_corners_num);
327
                PRINTF("EX quad count: %d/%d\n", quad_count, expected_quad_num);
324 328
            }
325 329
            else*/
326 330
            {
......
363 367

  
364 368
                quad_count = icvGenerateQuads( &quads, &corners, storage, thresh_img, flags );
365 369

  
366
                PRINTF("Quad count: %d/%d\n", quad_count, expected_corners_num);
370
                PRINTF("Quad count: %d/%d\n", quad_count, expected_quad_num);
367 371
            }
368 372

  
369 373

  
......
396 400
                continue;
397 401

  
398 402
            // Find quad's neighbors
399
            icvFindQuadNeighbors( quads, quad_count );
403
#ifdef DEBUG_CHESSBOARD
404
            icvFindQuadNeighbors( quads, quad_count, dbg_img );
405
#else
406
            icvFindQuadNeighbors( quads, quad_count, NULL );
407
#endif
408

  
409
#ifdef DEBUG_CHESSBOARD
410
			cvCopy(dbg_img, dbg3_img);
411
			cvNamedWindow("quads_neighbors", 1);
412
			for (i = 0; i < quad_count; i++) {
413
				for (int k=0; k<4; k++)
414
				{
415
					CvPoint2D32f pt1, pt2;
416
					CvScalar color = CV_RGB(30,255,30);
417
					pt1 = quads[i].corners[k]->pt;
418
					pt2 = quads[i].corners[(k+1)%4]->pt;
419
					if (k>0)
420
						color = CV_RGB(200,200,0);
421
					cvLine( dbg3_img, cvPointFrom32f(pt1), cvPointFrom32f(pt2), color, 2, 8);
422
					if (quads[i].neighbors[k] != NULL) {
423
						cvCircle(dbg3_img, cvPointFrom32f(pt1), 4, CV_RGB(255,0,0), 1, 8, 0);
424
					}
425
				}
426
			}
427
			cvShowImage("quads_neighbors", (IplImage*)dbg3_img);
428
			cvWaitKey();
429
#endif
400 430

  
401 431
            // allocate extra for adding in icvOrderFoundQuads
402 432
            cvFree(&quad_group);
......
1498 1542

  
1499 1543
//=====================================================================================
1500 1544

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

  
1507
    // find quad neighbors
1508
    for( idx = 0; idx < quad_count; idx++ )
1509
    {
1510
        CvCBQuad* cur_quad = &quads[idx];
1511

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

  
1517
        // for each corner of this quadrangle
1518
        for( i = 0; i < 4; i++ )
1519
        {
1520
            CvPoint2D32f pt;
1521
            float min_dist = FLT_MAX;
1522
            int closest_corner_idx = -1;
1523
            CvCBQuad *closest_quad = 0;
1524
            CvCBCorner *closest_corner = 0;
1545
typedef struct quadList {
1546
    CvCBQuad *quad;
1547
    struct quadList *next;
1548
    int length;
1549
} quadList;
1550

  
1551
static quadList *newQuadList(CvCBQuad *quad) {
1552
    quadList *list = (quadList *)cvAlloc(sizeof(quadList));
1553
    list->quad = quad;
1554
    list->next = NULL;
1555
    list->length = 1;
1556
    return list;
1557
}
1525 1558

  
1526
            if( cur_quad->neighbors[i] )
1527
                continue;
1559
static void deleteQuadList(quadList *list) {
1560
    quadList *next;
1561
    while (list != NULL) {
1562
        next = list->next;
1563
        cvFree(&list);
1564
        list = next;
1565
    }
1566
}
1528 1567

  
1529
            pt = cur_quad->corners[i]->pt;
1568
static void addToQuadList(quadList **list, CvCBQuad *quad) {
1569
    quadList *newList = newQuadList(quad);
1570
    if (*list != NULL) {
1571
        newList->next = *list;
1572
        newList->length += (*list)->length;
1573
    }
1574
    *list = newList;
1575
}
1530 1576

  
1531
            // find the closest corner in all other quadrangles
1532
            for( k = 0; k < quad_count; k++ )
1533
            {
1534
                if( k == idx )
1535
                    continue;
1577
static bool inQuadList(quadList *list, CvCBQuad *quad) {
1578
    while (list != NULL) {
1579
        if (list->quad == quad) {
1580
            return true;
1581
        }
1582
        list = list->next;
1583
    }
1584
    return false;
1585
}
1536 1586

  
1537
                for( j = 0; j < 4; j++ )
1538
                {
1539
                    if( quads[k].neighbors[j] )
1540
                        continue;
1587
static double itMean(double oldValue, double newValue, int it) {
1588
	// it is zero-based
1589
	if (it == 0) {
1590
		return newValue;
1591
	}
1592
	else {
1593
		return oldValue + (newValue - oldValue) / (it + 1);
1594
	}
1595
}
1541 1596

  
1542
                    dx = pt.x - quads[k].corners[j]->pt.x;
1543
                    dy = pt.y - quads[k].corners[j]->pt.y;
1544
                    dist = dx * dx + dy * dy;
1597
static double edgeMeanRec(double mean, CvCBQuad *quad, quadList **list) {
1598
    if (inQuadList(*list, quad)) {
1599
        return mean;
1600
    }
1545 1601

  
1546
                    if( dist < min_dist &&
1547
                        dist <= cur_quad->edge_len*thresh_scale &&
1548
                        dist <= quads[k].edge_len*thresh_scale )
1549
                    {
1550
                        // check edge lengths, make sure they're compatible
1551
                        // edges that are different by more than 1:4 are rejected
1552
                        float ediff = cur_quad->edge_len - quads[k].edge_len;
1553
                        if (ediff > 32*cur_quad->edge_len ||
1554
                            ediff > 32*quads[k].edge_len)
1555
                        {
1556
                            PRINTF("Incompatible edge lengths\n");
1557
                            continue;
1558
                        }
1559
                        closest_corner_idx = j;
1560
                        closest_quad = &quads[k];
1561
                        min_dist = dist;
1562
                    }
1563
                }
1564
            }
1602
    int i;
1603
    double dx, dy;
1565 1604

  
1566
            // we found a matching corner point?
1567
            if( closest_corner_idx >= 0 && min_dist < FLT_MAX )
1568
            {
1569
                // If another point from our current quad is closer to the found corner
1570
                // than the current one, then we don't count this one after all.
1571
                // This is necessary to support small squares where otherwise the wrong
1572
                // corner will get matched to closest_quad;
1573
                closest_corner = closest_quad->corners[closest_corner_idx];
1605
    int length = *list == NULL ? 0 : (*list)->length;
1606
    for (i = 0; i < 4; i++) {
1607
        dx = quad->corners[i]->pt.x - quad->corners[(i+1)%4]->pt.x;
1608
        dy = quad->corners[i]->pt.y - quad->corners[(i+1)%4]->pt.y;
1609
        mean = itMean(mean, dx * dx + dy * dy, 4 * length + i);
1610
    }
1611
    addToQuadList(list, quad);
1612
    
1613
    for (i = 0; i < 4; i++) {
1614
        if (quad->neighbors[i] != NULL) {
1615
            mean = edgeMeanRec(mean, quad->neighbors[i], list);
1616
        }
1617
    }
1618
    
1619
    return mean;
1620
}
1574 1621

  
1575
                for( j = 0; j < 4; j++ )
1576
                {
1577
                    if( cur_quad->neighbors[j] == closest_quad )
1578
                        break;
1622
static double edgeMean(CvCBQuad *cur_quad, CvCBQuad *other_quad) {
1623
    double mean = 0.0;
1624
    quadList *list = NULL;
1625
    mean = edgeMeanRec(mean, cur_quad, &list);
1626
    mean = edgeMeanRec(mean, other_quad, &list);
1627
    deleteQuadList(list);
1628
    return mean;
1629
}
1579 1630

  
1580
                    dx = closest_corner->pt.x - cur_quad->corners[j]->pt.x;
1581
                    dy = closest_corner->pt.y - cur_quad->corners[j]->pt.y;
1631
static int minNumerOfEdgesBetweenCorners(CvCBQuad *cur_quad, int cur_corner, CvCBCorner *target_corner, int max_limit) {
1632
    if (cur_quad->corners[cur_corner] == target_corner) {
1633
        return 0;
1634
    }
1635
    
1636
    if (max_limit == 0) {
1637
        return INT_MAX - 1; // Infinity, not reachable in zero edges, -1 to not overflow later on
1638
    }
1639
    
1640
    int cur_edges;
1641
    int min_edges = max_limit;
1642
    
1643
    cur_edges = minNumerOfEdgesBetweenCorners(cur_quad, (cur_corner+1)%4, target_corner, max_limit-1) + 1;
1644
    if (cur_edges < min_edges)
1645
        min_edges = cur_edges;
1646

  
1647
    cur_edges = minNumerOfEdgesBetweenCorners(cur_quad, (cur_corner-1+4)%4, target_corner, max_limit-1) + 1;
1648
    if (cur_edges < min_edges)
1649
        min_edges = cur_edges;
1650
    
1651
    CvCBQuad *neighbor_quad = cur_quad->neighbors[cur_corner];
1652
    if (neighbor_quad != NULL) {
1653
        int i;
1654
        for (i = 0; i < 4; i++) {
1655
            if (neighbor_quad->neighbors[i] == cur_quad)
1656
                break;
1657
        }
1658
        CV_Assert( i < 4 );
1659
    
1660
        cur_edges = minNumerOfEdgesBetweenCorners(neighbor_quad, (i+1)%4, target_corner, max_limit-1) + 1;
1661
        if (cur_edges < min_edges)
1662
            min_edges = cur_edges;
1663
    
1664
        cur_edges = minNumerOfEdgesBetweenCorners(neighbor_quad, (i-1+4)%4, target_corner, max_limit-1) + 1;
1665
        if (cur_edges < min_edges)
1666
            min_edges = cur_edges;
1667
    }
1668
    
1669
    return min_edges;
1670
}
1582 1671

  
1583
                    if( dx * dx + dy * dy < min_dist )
1584
                        break;
1585
                }
1672
static void icvFindQuadNeighbors( CvCBQuad *quads, int quad_count, cv::Ptr<IplImage> img )
1673
{
1674
    const double max_thresh_scale = 2.0; // Ratio of max diagonal in a x 2a quad, squared (max for all quads is 4.0, 2.0^2)
1675
    const double thresh_scale_step = 0.1;
1676
    double thresh_scale;
1677
    int idx, i, k, j;
1678
    float dx, dy, dist;
1679
    bool quad_added;
1680
    int check_other_closest;
1586 1681

  
1587
                if( j < 4 || cur_quad->count >= 4 || closest_quad->count >= 4 )
1588
                    continue;
1682
#ifdef DEBUG_CHESSBOARD
1683
    cv::Ptr<IplImage> dbg_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3 );
1684
#endif
1589 1685

  
1590
                // Check that each corner is a neighbor of different quads
1591
                for( j = 0; j < closest_quad->count; j++ )
1686
    check_other_closest = 1;
1687
    do {
1688
        for (thresh_scale = thresh_scale_step; thresh_scale <= max_thresh_scale; thresh_scale += thresh_scale_step) {
1689
            do {
1690
                quad_added = false;
1691
                
1692
                // find quad neighbors
1693
                for( idx = 0; idx < quad_count; idx++ )
1592 1694
                {
1593
                    if( closest_quad->neighbors[j] == cur_quad )
1594
                        break;
1595
                }
1596
                if( j < closest_quad->count )
1597
                    continue;
1598

  
1599
                // check whether the closest corner to closest_corner
1600
                // is different from cur_quad->corners[i]->pt
1601
                for( k = 0; k < quad_count; k++ )
1602
                {
1603
                    CvCBQuad* q = &quads[k];
1604
                    if( k == idx || q == closest_quad )
1605
                        continue;
1606

  
1607
                    for( j = 0; j < 4; j++ )
1608
                        if( !q->neighbors[j] )
1695
                    CvCBQuad* cur_quad = &quads[idx];
1696
            
1697
                    // choose the points of the current quadrangle that are close to
1698
                    // some points of the other quadrangles
1699
                    // (it can happen for split corners (due to dilation) of the
1700
                    // checker board). Search only in other quadrangles!
1701
            
1702
                    // for each corner of this quadrangle
1703
                    for( i = 0; i < 4; i++ )
1704
                    {
1705
                        CvPoint2D32f pt;
1706
                        float min_dist = FLT_MAX;
1707
                        int closest_corner_idx = -1;
1708
                        CvCBQuad *closest_quad = 0;
1709
                        CvCBCorner *closest_corner = 0;
1710
            
1711
                        if( cur_quad->neighbors[i] )
1712
                            continue;
1713
            
1714
                        pt = cur_quad->corners[i]->pt;
1715
            
1716
                        // find the closest corner in all other quadrangles
1717
                        for( k = 0; k < quad_count; k++ )
1609 1718
                        {
1610
                            dx = closest_corner->pt.x - q->corners[j]->pt.x;
1611
                            dy = closest_corner->pt.y - q->corners[j]->pt.y;
1612
                            dist = dx*dx + dy*dy;
1613
                            if( dist < min_dist )
1614
                                break;
1719
                            if( k == idx )
1720
                                continue;
1721
            
1722
                            for( j = 0; j < 4; j++ )
1723
                            {
1724
                                if( quads[k].neighbors[j] )
1725
                                    continue;
1726
            
1727
                                dx = pt.x - quads[k].corners[j]->pt.x;
1728
                                dy = pt.y - quads[k].corners[j]->pt.y;
1729
                                dist = dx * dx + dy * dy;
1730
                                
1731
                                if( dist < min_dist &&
1732
                                    dist <= edgeMean(cur_quad, &(quads[k]))*thresh_scale )
1733
                                {
1734
                                    // check edge lengths, make sure they're compatible
1735
                                    // edges that are different by more than 1:4 are rejected
1736
                                    float ediff = cur_quad->edge_len - quads[k].edge_len;
1737
                                    if (ediff > 32*cur_quad->edge_len ||
1738
                                        ediff > 32*quads[k].edge_len)
1739
                                    {
1740
                                        PRINTF("Incompatible edge lengths\n");
1741
                                        continue;
1742
                                    }
1743
                                    closest_corner_idx = j;
1744
                                    closest_quad = &quads[k];
1745
                                    min_dist = dist;
1746
                                }
1747
                            }
1615 1748
                        }
1616
                    if( j < 4 )
1617
                        break;
1749
            
1750
                        // we found a matching corner point?
1751
                        if( closest_corner_idx >= 0 && min_dist < FLT_MAX )
1752
                        {
1753
                            // If another point from our current quad is closer to the found corner
1754
                            // than the current one, then we don't count this one after all.
1755
                            // This is necessary to support small squares where otherwise the wrong
1756
                            // corner will get matched to closest_quad;
1757
                            closest_corner = closest_quad->corners[closest_corner_idx];
1758
            
1759
            #ifdef DEBUG_CHESSBOARD
1760
            #ifdef DEBUG_CHESSBOARD_EVERY_CORNER
1761
                            cvCopy(img,dbg_img);
1762
                            cvNamedWindow("closest_corner", 1);
1763
                            cvCircle(dbg_img, cvPointFrom32f(cur_quad->corners[i]->pt), 4, CV_RGB(0,255,0), 1, 8, 0);
1764
                            cvCircle(dbg_img, cvPointFrom32f(closest_corner->pt), 4, CV_RGB(255,0,0), 1, 8, 0);
1765
                            cvShowImage("closest_corner", (IplImage*)dbg_img);
1766
                            cvWaitKey();
1767
            #endif
1768
            #endif
1769
            
1770
                            for( j = 0; j < 4; j++ )
1771
                            {
1772
                                if( cur_quad->neighbors[j] == closest_quad )
1773
                                    break;
1774
            
1775
                                dx = closest_corner->pt.x - cur_quad->corners[j]->pt.x;
1776
                                dy = closest_corner->pt.y - cur_quad->corners[j]->pt.y;
1777
            
1778
                                if( dx * dx + dy * dy < min_dist )
1779
                                    break;
1780
                            }
1781
            
1782
                            if( j < 4 || cur_quad->count >= 4 || closest_quad->count >= 4 ) {
1783
                                PRINTF("Another corner of the current quad is closer.\n");
1784
                                continue;
1785
                            }
1786
            
1787
                            // Check that each corner is a neighbor of different quads
1788
                            for( j = 0; j < closest_quad->count; j++ )
1789
                            {
1790
                                if( closest_quad->neighbors[j] == cur_quad )
1791
                                    break;
1792
                            }
1793
                            if( j < closest_quad->count ) {
1794
                                PRINTF("Closest quad has already for neighbor current quad.\n");
1795
                                continue;
1796
                            }
1797
                            
1798
                            // Check if merging corners will make a triangle
1799
                            // This happens if two edges from opposite quads are merged together, then space (white quad) between
1800
                            // them becomes a triangle
1801
                            // As we increase thresh_scale incrementally we can be sure that better (closer) corners were already
1802
                            // merged if this was possible, so this one is probably not the right one to merge
1803
                            if (minNumerOfEdgesBetweenCorners(cur_quad, i, closest_corner, 4) < 4) {
1804
                                PRINTF("Merging corners would make a triangle.\n");
1805
                                continue;
1806
                            }
1807
                            
1808
                            // First time we check if there is some other quad which is closer to selected closest corner
1809
                            // Second time all useful corners in other quads are already used so we can use selected closest corner
1810
                            // even if there is some possible (but obviously not really useful) other quad closer
1811
                            if (check_other_closest > 0) {
1812
                                // check whether the closest corner to closest_corner
1813
                                // is different from cur_quad->corners[i]->pt
1814
                                for( k = 0; k < quad_count; k++ )
1815
                                {
1816
                                    CvCBQuad* q = &quads[k];
1817
                                    if( k == idx || q == closest_quad )
1818
                                        continue;
1819
                
1820
                                    for( j = 0; j < 4; j++ )
1821
                                        if( !q->neighbors[j] )
1822
                                        {
1823
                                            dx = closest_corner->pt.x - q->corners[j]->pt.x;
1824
                                            dy = closest_corner->pt.y - q->corners[j]->pt.y;
1825
                                            dist = dx*dx + dy*dy;
1826
                                            if( dist < min_dist )
1827
                                                break;
1828
                                        }
1829
                                    if( j < 4 )
1830
                                        break;
1831
                                }
1832
                
1833
                                if( k < quad_count ) {            
1834
                                    PRINTF("Another corner is closer than our closest one.\n");
1835
                                    continue;
1836
                                }
1837
                            }
1838
            
1839
                            PRINTF("Found closest corner.\n");
1840
            
1841
                            closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f;
1842
                            closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f;
1843
            
1844
                            // We've found one more corner - remember it
1845
                            cur_quad->count++;
1846
                            cur_quad->neighbors[i] = closest_quad;
1847
                            cur_quad->corners[i] = closest_corner;
1848
            
1849
                            closest_quad->count++;
1850
                            closest_quad->neighbors[closest_corner_idx] = cur_quad;
1851
                            
1852
                            quad_added = true;
1853
                        }
1854
                    }
1618 1855
                }
1619

  
1620
                if( k < quad_count )
1621
                    continue;
1622

  
1623
                closest_corner->pt.x = (pt.x + closest_corner->pt.x) * 0.5f;
1624
                closest_corner->pt.y = (pt.y + closest_corner->pt.y) * 0.5f;
1625

  
1626
                // We've found one more corner - remember it
1627
                cur_quad->count++;
1628
                cur_quad->neighbors[i] = closest_quad;
1629
                cur_quad->corners[i] = closest_corner;
1630

  
1631
                closest_quad->count++;
1632
                closest_quad->neighbors[closest_corner_idx] = cur_quad;
1633
            }
1856
            } while (quad_added);
1634 1857
        }
1635
    }
1858
        check_other_closest--;
1859
    } while (check_other_closest >= 0);
1636 1860
}
1637 1861

  
1638 1862
//=====================================================================================