Example #1
0
/*F///////////////////////////////////////////////////////////////////////////////////////
//    Name: icvCalcPGH
//    Purpose:
//      Calculates PGH(pairwise geometric histogram) for contour given.
//    Context:
//    Parameters:
//      contour  - pointer to input contour object.
//      pgh      - output histogram
//      ang_dim  - number of angle bins (vertical size of histogram)
//      dist_dim - number of distance bins (horizontal size of histogram)
//    Returns:
//      CV_OK or error code
//    Notes:
//F*/
CvStatus
icvCalcPGH( CvSeq * contour, float *pgh, int angle_dim, int dist_dim )
{
    char local_buffer[(1 << 14) + 32];
    float *local_buffer_ptr = (float *)icvAlignPtr(local_buffer,32);
    float *buffer = local_buffer_ptr;
    double angle_scale = (angle_dim - 0.51) / icv_acos_table[0];
    double dist_scale = DBL_EPSILON;
    int buffer_size;
    int i, count, pass;
    int *pghi = (int *) pgh;
    int hist_size = angle_dim * dist_dim;
    CvSeqReader reader1, reader2;       /* external and internal readers */

    if( !contour || !pgh )
        return CV_NULLPTR_ERR;

    if( angle_dim <= 0 || angle_dim > 180 || dist_dim <= 0 )
        return CV_BADRANGE_ERR;

    if( !CV_IS_SEQ_POLYGON( contour ))
        return CV_BADFLAG_ERR;

    memset( pgh, 0, hist_size * sizeof( pgh[0] ));

    count = contour->total;

    /* allocate buffer for distances */
    buffer_size = count * sizeof( float );

    if( buffer_size > (int)sizeof(local_buffer) - 32 )
    {
        buffer = (float *) icvAlloc( buffer_size );
        if( !buffer )
            return CV_OUTOFMEM_ERR;
    }

    cvStartReadSeq( contour, &reader1, 0 );
    cvStartReadSeq( contour, &reader2, 0 );

    /* calc & store squared edge lengths, calculate maximal distance between edges */
    for( i = 0; i < count; i++ )
    {
        CvPoint pt1, pt2;
        int dx, dy;

        CV_READ_EDGE( pt1, pt2, reader1 );

        dx = pt2.x - pt1.x;
        dy = pt2.y - pt1.y;
        buffer[i] = (float) (dx * dx + dy * dy);
    }

    icvbInvSqrt_32f( buffer, buffer, i );

    /* 
       do 2 passes. 
       First calculates maximal distance.
       Second calculates histogram itself.
     */
    for( pass = 1; pass <= 2; pass++ )
    {
        double dist_coeff = 0, angle_coeff = 0;

        /* run external loop */
        for( i = 0; i < count; i++ )
        {
            CvPoint pt1, pt2;
            int dx, dy;
            int dist = 0;

            CV_READ_EDGE( pt1, pt2, reader1 );

            dx = pt2.x - pt1.x;
            dy = pt2.y - pt1.y;

            if( (dx | dy) != 0 )
            {
                int j;

                if( pass == 2 )
                {
                    dist_coeff = buffer[i] * dist_scale;
                    angle_coeff = buffer[i] * (_CV_ACOS_TABLE_SIZE / 2);
                }

                /* run internal loop (for current edge) */
                for( j = 0; j < count; j++ )
                {
                    CvPoint pt3, pt4;

                    CV_READ_EDGE( pt3, pt4, reader2 );

                    if( i != j )        /* process edge pair */
                    {
                        int d1 = (pt3.y - pt1.y) * dx - (pt3.x - pt1.x) * dy;
                        int d2 = (pt4.y - pt1.y) * dx - (pt2.x - pt1.x) * dy;
                        int cross_flag;
                        int *hist_row = 0;

                        if( pass == 2 )
                        {
                            int dp = (pt4.x - pt3.x) * dx + (pt4.y - pt3.y) * dy;

                            dp = cvRound( dp * angle_coeff * buffer[j] ) +
                                (_CV_ACOS_TABLE_SIZE / 2);
                            dp = MAX( dp, 0 );
                            dp = MIN( dp, _CV_ACOS_TABLE_SIZE - 1 );
                            hist_row = pghi + dist_dim *
                                cvRound( icv_acos_table[dp] * angle_scale );

                            d1 = cvRound( d1 * dist_coeff );
                            d2 = cvRound( d2 * dist_coeff );
                        }

                        cross_flag = (d1 ^ d2) < 0;

                        d1 = CV_IABS( d1 );
                        d2 = CV_IABS( d2 );

                        if( pass == 2 )
                        {
                            if( d1 >= dist_dim )
                                d1 = dist_dim - 1;
                            if( d2 >= dist_dim )
                                d2 = dist_dim - 1;

                            if( !cross_flag )
                            {
                                if( d1 > d2 )   /* make d1 <= d2 */
                                {
                                    d1 ^= d2;
                                    d2 ^= d1;
                                    d1 ^= d2;
                                }

                                for( ; d1 <= d2; d1++ )
                                    hist_row[d1]++;
                            }
                            else
                            {
                                for( ; d1 >= 0; d1-- )
                                    hist_row[d1]++;
                                for( ; d2 >= 0; d2-- )
                                    hist_row[d2]++;
                            }
                        }
                        else    /* 1st pass */
                        {
                            d1 = CV_IMAX( d1, d2 );
                            dist = CV_IMAX( dist, d1 );
                        }
                    }           /* end of processing of edge pair */

                }               /* end of internal loop */

                if( pass == 1 )
                {
                    double scale = dist * buffer[i];

                    dist_scale = MAX( dist_scale, scale );
                }
            }
        }                       /* end of external loop */

        if( pass == 1 )
        {
            dist_scale = (dist_dim - 0.51) / dist_scale;
        }

    }                           /* end of pass on loops */


    /* convert hist to floats */
    for( i = 0; i < hist_size; i++ )
    {
        ((float *) pghi)[i] = (float) pghi[i];
    }

    if( buffer != local_buffer_ptr )
        icvFree( &buffer );

    return CV_OK;
}
CV_IMPL double
cvPointPolygonTest( const CvArr* _contour, CvPoint2D32f pt, int measure_dist )
{
    double result = 0;
    CV_FUNCNAME( "cvCheckPointPolygon" );

    __BEGIN__;
    
    CvSeqBlock block;
    CvContour header;
    CvSeq* contour = (CvSeq*)_contour;
    CvSeqReader reader;
    int i, total, counter = 0;
    int is_float;
    double min_dist_num = FLT_MAX, min_dist_denom = 1;
    CvPoint ip = {0,0};

    if( !CV_IS_SEQ(contour) )
    {
        CV_CALL( contour = cvPointSeqFromMat( CV_SEQ_KIND_CURVE + CV_SEQ_FLAG_CLOSED,
                                              _contour, &header, &block ));
    }
    else if( CV_IS_SEQ_POLYGON(contour) )
    {
        if( contour->header_size == sizeof(CvContour) && !measure_dist )
        {
            CvRect r = ((CvContour*)contour)->rect;
            if( pt.x < r.x || pt.y < r.y ||
                pt.x >= r.x + r.width || pt.y >= r.y + r.height )
                return -100;
        }
    }
    else if( CV_IS_SEQ_CHAIN(contour) )
    {
        CV_ERROR( CV_StsBadArg,
            "Chains are not supported. Convert them to polygonal representation using cvApproxChains()" );
    }
    else
        CV_ERROR( CV_StsBadArg, "Input contour is neither a valid sequence nor a matrix" );

    total = contour->total;
    is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2;
    cvStartReadSeq( contour, &reader, -1 );

    if( !is_float && !measure_dist && (ip.x = cvRound(pt.x)) == pt.x && (ip.y = cvRound(pt.y)) == pt.y )
    {
        // the fastest "pure integer" branch
        CvPoint v0, v;
        CV_READ_SEQ_ELEM( v, reader );

        for( i = 0; i < total; i++ )
        {
            int dist;
            v0 = v;
            CV_READ_SEQ_ELEM( v, reader );

            if( (v0.y <= ip.y && v.y <= ip.y) ||
                (v0.y > ip.y && v.y > ip.y) ||
                (v0.x < ip.x && v.x < ip.x) )
            {
                if( ip.y == v.y && (ip.x == v.x || (ip.y == v0.y &&
                    ((v0.x <= ip.x && ip.x <= v.x) || (v.x <= ip.x && ip.x <= v0.x)))) )
                    EXIT;
                continue;
            }

            dist = (ip.y - v0.y)*(v.x - v0.x) - (ip.x - v0.x)*(v.y - v0.y);
            if( dist == 0 )
                EXIT;
            if( v.y < v0.y )
                dist = -dist;
            counter += dist > 0;
        }

        result = counter % 2 == 0 ? -100 : 100;
    }
    else
    {
        CvPoint2D32f v0, v;
        CvPoint iv;

        if( is_float )
        {
            CV_READ_SEQ_ELEM( v, reader );
        }
        else
        {
            CV_READ_SEQ_ELEM( iv, reader );
            v = cvPointTo32f( iv );
        }

        if( !measure_dist )
        {
            for( i = 0; i < total; i++ )
            {
                double dist;
                v0 = v;
                if( is_float )
                {
                    CV_READ_SEQ_ELEM( v, reader );
                }
                else
                {
                    CV_READ_SEQ_ELEM( iv, reader );
                    v = cvPointTo32f( iv );
                }

                if( (v0.y <= pt.y && v.y <= pt.y) ||
                    (v0.y > pt.y && v.y > pt.y) ||
                    (v0.x < pt.x && v.x < pt.x) )
                {
                    if( pt.y == v.y && (pt.x == v.x || (pt.y == v0.y &&
                        ((v0.x <= pt.x && pt.x <= v.x) || (v.x <= pt.x && pt.x <= v0.x)))) )
                        EXIT;
                    continue;
                }

                dist = (double)(pt.y - v0.y)*(v.x - v0.x) - (double)(pt.x - v0.x)*(v.y - v0.y);
                if( dist == 0 )
                    EXIT;
                if( v.y < v0.y )
                    dist = -dist;
                counter += dist > 0;
            }

            result = counter % 2 == 0 ? -100 : 100;
        }
        else
        {
            for( i = 0; i < total; i++ )
            {
                double dx, dy, dx1, dy1, dx2, dy2, dist_num, dist_denom = 1;
        
                v0 = v;
                if( is_float )
                {
                    CV_READ_SEQ_ELEM( v, reader );
                }
                else
                {
                    CV_READ_SEQ_ELEM( iv, reader );
                    v = cvPointTo32f( iv );
                }
        
                dx = v.x - v0.x; dy = v.y - v0.y;
                dx1 = pt.x - v0.x; dy1 = pt.y - v0.y;
                dx2 = pt.x - v.x; dy2 = pt.y - v.y;
        
                if( dx1*dx + dy1*dy <= 0 )
                    dist_num = dx1*dx1 + dy1*dy1;
                else if( dx2*dx + dy2*dy >= 0 )
                    dist_num = dx2*dx2 + dy2*dy2;
                else
                {
                    dist_num = (dy1*dx - dx1*dy);
                    dist_num *= dist_num;
                    dist_denom = dx*dx + dy*dy;
                }

                if( dist_num*min_dist_denom < min_dist_num*dist_denom )
                {
                    min_dist_num = dist_num;
                    min_dist_denom = dist_denom;
                    if( min_dist_num == 0 )
                        break;
                }

                if( (v0.y <= pt.y && v.y <= pt.y) ||
                    (v0.y > pt.y && v.y > pt.y) ||
                    (v0.x < pt.x && v.x < pt.x) )
                    continue;

                dist_num = dy1*dx - dx1*dy;
                if( dy < 0 )
                    dist_num = -dist_num;
                counter += dist_num > 0;
            }

            result = sqrt(min_dist_num/min_dist_denom);
            if( counter % 2 == 0 )
                result = -result;
        }
    }

    __END__;

    return result;
}
Example #3
0
/* area of a contour sector */
static CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area )
{
    CvPoint pt;                 /*  pointer to points   */
    CvPoint pt_s, pt_e;         /*  first and last points  */
    CvSeqReader reader;         /*  points reader of contour   */

    int p_max = 2, p_ind;
    int lpt, flag, i;
    double a00;                 /* unnormalized moments m00    */
    double xi, yi, xi_1, yi_1, x0, y0, dxy, sk, sk1, t;
    double x_s, y_s, nx, ny, dx, dy, du, dv;
    double eps = 1.e-5;
    double *p_are1, *p_are2, *p_are;

    assert( contour != NULL );

    if( contour == NULL )
        return CV_NULLPTR_ERR;

    if( !CV_IS_SEQ_POLYGON( contour ))
        return CV_BADFLAG_ERR;

    lpt = cvSliceLength( slice, contour );
    /*if( n2 >= n1 )
        lpt = n2 - n1 + 1;
    else
        lpt = contour->total - n1 + n2 + 1;*/

    if( contour->total && lpt > 2 )
    {
        a00 = x0 = y0 = xi_1 = yi_1 = 0;
        sk1 = 0;
        flag = 0;
        dxy = 0;
        p_are1 = (double *) cvAlloc( p_max * sizeof( double ));

        if( p_are1 == NULL )
            return CV_OUTOFMEM_ERR;

        p_are = p_are1;
        p_are2 = NULL;

        cvStartReadSeq( contour, &reader, 0 );
        cvSetSeqReaderPos( &reader, slice.start_index );
        CV_READ_SEQ_ELEM( pt_s, reader );
        p_ind = 0;
        cvSetSeqReaderPos( &reader, slice.end_index );
        CV_READ_SEQ_ELEM( pt_e, reader );

/*    normal coefficients    */
        nx = pt_s.y - pt_e.y;
        ny = pt_e.x - pt_s.x;
        cvSetSeqReaderPos( &reader, slice.start_index );

        while( lpt-- > 0 )
        {
            CV_READ_SEQ_ELEM( pt, reader );

            if( flag == 0 )
            {
                xi_1 = (double) pt.x;
                yi_1 = (double) pt.y;
                x0 = xi_1;
                y0 = yi_1;
                sk1 = 0;
                flag = 1;
            }
            else
            {
                xi = (double) pt.x;
                yi = (double) pt.y;

/****************   edges intersection examination   **************************/
                sk = nx * (xi - pt_s.x) + ny * (yi - pt_s.y);
                if( fabs( sk ) < eps && lpt > 0 || sk * sk1 < -eps )
                {
                    if( fabs( sk ) < eps )
                    {
                        dxy = xi_1 * yi - xi * yi_1;
                        a00 = a00 + dxy;
                        dxy = xi * y0 - x0 * yi;
                        a00 = a00 + dxy;

                        if( p_ind >= p_max )
                            icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );

                        p_are[p_ind] = a00 / 2.;
                        p_ind++;
                        a00 = 0;
                        sk1 = 0;
                        x0 = xi;
                        y0 = yi;
                        dxy = 0;
                    }
                    else
                    {
/*  define intersection point    */
                        dv = yi - yi_1;
                        du = xi - xi_1;
                        dx = ny;
                        dy = -nx;
                        if( fabs( du ) > eps )
                            t = ((yi_1 - pt_s.y) * du + dv * (pt_s.x - xi_1)) /
                                (du * dy - dx * dv);
                        else
                            t = (xi_1 - pt_s.x) / dx;
                        if( t > eps && t < 1 - eps )
                        {
                            x_s = pt_s.x + t * dx;
                            y_s = pt_s.y + t * dy;
                            dxy = xi_1 * y_s - x_s * yi_1;
                            a00 += dxy;
                            dxy = x_s * y0 - x0 * y_s;
                            a00 += dxy;
                            if( p_ind >= p_max )
                                icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );

                            p_are[p_ind] = a00 / 2.;
                            p_ind++;

                            a00 = 0;
                            sk1 = 0;
                            x0 = x_s;
                            y0 = y_s;
                            dxy = x_s * yi - xi * y_s;
                        }
                    }
                }
                else
                    dxy = xi_1 * yi - xi * yi_1;

                a00 += dxy;
                xi_1 = xi;
                yi_1 = yi;
                sk1 = sk;

            }
        }

        xi = x0;
        yi = y0;
        dxy = xi_1 * yi - xi * yi_1;

        a00 += dxy;

        if( p_ind >= p_max )
            icvMemCopy( &p_are1, &p_are2, &p_are, &p_max );

        p_are[p_ind] = a00 / 2.;
        p_ind++;

/*     common area calculation    */
        *area = 0;
        for( i = 0; i < p_ind; i++ )
            (*area) += fabs( p_are[i] );

        if( p_are1 != NULL )
            cvFree( &p_are1 );
        else if( p_are2 != NULL )
            cvFree( &p_are2 );

        return CV_OK;
    }
    else
        return CV_BADSIZE_ERR;
}
Example #4
0
/*F///////////////////////////////////////////////////////////////////////////////////////
//    Name: icvCreateContourTree
//    Purpose:
//    Create binary tree representation for the contour 
//    Context:
//    Parameters:
//      contour - pointer to input contour object.
//      storage - pointer to the current storage block
//      tree   -  output pointer to the binary tree representation 
//      threshold - threshold for the binary tree building 
//
//F*/
static CvStatus
icvCreateContourTree( const CvSeq * contour, CvMemStorage * storage,
                      CvContourTree ** tree, double threshold )
{
    CvPoint *pt_p;              /*  pointer to previos points   */
    CvPoint *pt_n;              /*  pointer to next points      */
    CvPoint *pt1, *pt2;         /*  pointer to current points   */

    CvPoint t, tp1, tp2, tp3, tn1, tn2, tn3;
    int lpt, flag, i, j, i_tree, j_1, j_3, i_buf;
    double s, sp1, sp2, sn1, sn2, s_c, sp1_c, sp2_c, sn1_c, sn2_c, h, hp1, hp2, hn1, hn2,
        a, ap1, ap2, an1, an2, b, bp1, bp2, bn1, bn2;
    double a_s_c, a_sp1_c;

    _CvTrianAttr **ptr_p, **ptr_n, **ptr1, **ptr2;      /*  pointers to pointers of triangles  */
    _CvTrianAttr *cur_adr;

    int *num_p, *num_n, *num1, *num2;   /*   numbers of input contour points   */
    int nm, nmp1, nmp2, nmp3, nmn1, nmn2, nmn3;
    int seq_flags = 1, i_end, prev_null, prev2_null;
    double koef = 1.5;
    double eps = 1.e-7;
    double e;
    CvStatus status;
    int hearder_size;
    _CvTrianAttr tree_one, tree_two, *tree_end, *tree_root;

    CvSeqWriter writer;

    assert( contour != NULL && contour->total >= 4 );
    status = CV_OK;

    if( contour == NULL )
        return CV_NULLPTR_ERR;
    if( contour->total < 4 )
        return CV_BADSIZE_ERR;

    if( !CV_IS_SEQ_POLYGON( contour ))
        return CV_BADFLAG_ERR;


/*   Convert Sequence to array    */
    lpt = contour->total;
    pt_p = pt_n = NULL;
    num_p = num_n = NULL;
    ptr_p = ptr_n = ptr1 = ptr2 = NULL;
    tree_end = NULL;

    pt_p = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
    pt_n = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));

    num_p = (int *) cvAlloc( lpt * sizeof( int ));
    num_n = (int *) cvAlloc( lpt * sizeof( int ));

    hearder_size = sizeof( CvContourTree );
    seq_flags = CV_SEQ_POLYGON_TREE;
    cvStartWriteSeq( seq_flags, hearder_size, sizeof( _CvTrianAttr ), storage, &writer );

    ptr_p = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
    ptr_n = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));

    memset( ptr_p, 0, lpt * sizeof( _CvTrianAttr * ));
    memset( ptr_n, 0, lpt * sizeof( _CvTrianAttr * ));

    if( pt_p == NULL || pt_n == NULL )
        return CV_OUTOFMEM_ERR;
    if( ptr_p == NULL || ptr_n == NULL )
        return CV_OUTOFMEM_ERR;

/*     write fild for the binary tree root   */
/*  start_writer = writer;   */

    tree_one.pt.x = tree_one.pt.y = 0;
    tree_one.sign = 0;
    tree_one.area = 0;
    tree_one.r1 = tree_one.r2 = 0;
    tree_one.next_v1 = tree_one.next_v2 = tree_one.prev_v = NULL;

    CV_WRITE_SEQ_ELEM( tree_one, writer );
    tree_root = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

    if( cvCvtSeqToArray( contour, (char *) pt_p ) == (char *) contour )
        return CV_BADPOINT_ERR;

    for( i = 0; i < lpt; i++ )
        num_p[i] = i;

    i = lpt;
    flag = 0;
    i_tree = 0;
    e = 20.;                    /*  initial threshold value   */
    ptr1 = ptr_p;
    ptr2 = ptr_n;
    pt1 = pt_p;
    pt2 = pt_n;
    num1 = num_p;
    num2 = num_n;
/*  binary tree constraction    */
    while( i > 4 )
    {
        if( flag == 0 )
        {
            ptr1 = ptr_p;
            ptr2 = ptr_n;
            pt1 = pt_p;
            pt2 = pt_n;
            num1 = num_p;
            num2 = num_n;
            flag = 1;
        }
        else
        {
            ptr1 = ptr_n;
            ptr2 = ptr_p;
            pt1 = pt_n;
            pt2 = pt_p;
            num1 = num_n;
            num2 = num_p;
            flag = 0;
        }
        t = pt1[0];
        nm = num1[0];
        tp1 = pt1[i - 1];
        nmp1 = num1[i - 1];
        tp2 = pt1[i - 2];
        nmp2 = num1[i - 2];
        tp3 = pt1[i - 3];
        nmp3 = num1[i - 3];
        tn1 = pt1[1];
        nmn1 = num1[1];
        tn2 = pt1[2];
        nmn2 = num1[2];

        i_buf = 0;
        i_end = -1;
        CV_MATCH_CHECK( status,
                        icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a,
                                        &b ));
        CV_MATCH_CHECK( status,
                        icvCalcTriAttr( contour, tp1, tp2, nmp2, t, nm, &sp1, &sp1_c, &hp1,
                                        &ap1, &bp1 ));
        CV_MATCH_CHECK( status,
                        icvCalcTriAttr( contour, tp2, tp3, nmp3, tp1, nmp1, &sp2, &sp2_c, &hp2,
                                        &ap2, &bp2 ));
        CV_MATCH_CHECK( status,
                        icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1,
                                        &an1, &bn1 ));


        j_3 = 3;
        prev_null = prev2_null = 0;
        for( j = 0; j < i; j++ )
        {
            tn3 = pt1[j_3];
            nmn3 = num1[j_3];
            if( j == 0 )
                j_1 = i - 1;
            else
                j_1 = j - 1;

            CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn2, tn1, nmn1, tn3, nmn3,
                                                    &sn2, &sn2_c, &hn2, &an2, &bn2 ));

            if( (s_c < sp1_c && s_c < sp2_c && s_c <= sn1_c && s_c <= sn2_c && s_c < e) ||
                (s_c == sp1_c && s_c <= sp2_c || s_c == sp2_c && s_c <= sp1_c) && s_c <= sn1_c
                && s_c <= sn2_c && s_c < e && j > 1 && prev2_null == 0 || (s_c < eps && j > 0
                                                                           && prev_null == 0) )

            {
                prev_null = prev2_null = 1;
                if( s_c < threshold )
                {
                    if( ptr1[j_1] == NULL && ptr1[j] == NULL )
                    {
                        if( i_buf > 0 )
                            ptr2[i_buf - 1] = NULL;
                        else
                            i_end = 0;
                    }
                    else
                    {
/*   form next vertex  */
                        tree_one.pt = t;
                        tree_one.sign = (char) (CV_SIGN( s ));
                        tree_one.r1 = h / a;
                        tree_one.r2 = b / a;
                        tree_one.area = fabs( s );
                        tree_one.next_v1 = ptr1[j_1];
                        tree_one.next_v2 = ptr1[j];

                        CV_WRITE_SEQ_ELEM( tree_one, writer );
                        cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

                        if( ptr1[j_1] != NULL )
                            ptr1[j_1]->prev_v = cur_adr;
                        if( ptr1[j] != NULL )
                            ptr1[j]->prev_v = cur_adr;

                        if( i_buf > 0 )
                            ptr2[i_buf - 1] = cur_adr;
                        else
                        {
                            tree_end = (_CvTrianAttr *) writer.ptr;
                            i_end = 1;
                        }
                        i_tree++;
                    }
                }
                else
/*   form next vertex    */
                {
                    tree_one.pt = t;
                    tree_one.sign = (char) (CV_SIGN( s ));
                    tree_one.area = fabs( s );
                    tree_one.r1 = h / a;
                    tree_one.r2 = b / a;
                    tree_one.next_v1 = ptr1[j_1];
                    tree_one.next_v2 = ptr1[j];

                    CV_WRITE_SEQ_ELEM( tree_one, writer );
                    cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

                    if( ptr1[j_1] != NULL )
                        ptr1[j_1]->prev_v = cur_adr;
                    if( ptr1[j] != NULL )
                        ptr1[j]->prev_v = cur_adr;

                    if( i_buf > 0 )
                        ptr2[i_buf - 1] = cur_adr;
                    else
                    {
                        tree_end = cur_adr;
                        i_end = 1;
                    }
                    i_tree++;
                }
            }
            else
/*   the current triangle is'not LMIAT    */
            {
                prev_null = 0;
                switch (prev2_null)
                {
                case 0:
                    break;
                case 1:
                    {
                        prev2_null = 2;
                        break;
                    }
                case 2:
                    {
                        prev2_null = 0;
                        break;
                    }
                }
                if( j != i - 1 || i_end == -1 )
                    ptr2[i_buf] = ptr1[j];
                else if( i_end == 0 )
                    ptr2[i_buf] = NULL;
                else
                    ptr2[i_buf] = tree_end;
                pt2[i_buf] = t;
                num2[i_buf] = num1[j];
                i_buf++;
            }
/*    go to next vertex    */
            tp3 = tp2;
            tp2 = tp1;
            tp1 = t;
            t = tn1;
            tn1 = tn2;
            tn2 = tn3;
            nmp3 = nmp2;
            nmp2 = nmp1;
            nmp1 = nm;
            nm = nmn1;
            nmn1 = nmn2;
            nmn2 = nmn3;

            sp2 = sp1;
            sp1 = s;
            s = sn1;
            sn1 = sn2;
            sp2_c = sp1_c;
            sp1_c = s_c;
            s_c = sn1_c;
            sn1_c = sn2_c;

            ap2 = ap1;
            ap1 = a;
            a = an1;
            an1 = an2;
            bp2 = bp1;
            bp1 = b;
            b = bn1;
            bn1 = bn2;
            hp2 = hp1;
            hp1 = h;
            h = hn1;
            hn1 = hn2;
            j_3++;
            if( j_3 >= i )
                j_3 = 0;
        }

        i = i_buf;
        e = e * koef;
    }

/*  constract tree root  */
    if( i != 4 )
        return CV_BADFACTOR_ERR;

    t = pt2[0];
    tn1 = pt2[1];
    tn2 = pt2[2];
    tp1 = pt2[3];
    nm = num2[0];
    nmn1 = num2[1];
    nmn2 = num2[2];
    nmp1 = num2[3];
/*   first pair of the triangles   */
    CV_MATCH_CHECK( status,
                    icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b ));
    CV_MATCH_CHECK( status,
                    icvCalcTriAttr( contour, tn2, tn1, nmn1, tp1, nmp1, &sn2, &sn2_c, &hn2,
                                    &an2, &bn2 ));
/*   second pair of the triangles   */
    CV_MATCH_CHECK( status,
                    icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1,
                                    &bn1 ));
    CV_MATCH_CHECK( status,
                    icvCalcTriAttr( contour, tp1, tn2, nmn2, t, nm, &sp1, &sp1_c, &hp1, &ap1,
                                    &bp1 ));

    a_s_c = fabs( s_c - sn2_c );
    a_sp1_c = fabs( sp1_c - sn1_c );

    if( a_s_c > a_sp1_c )
/*   form child vertexs for the root     */
    {
        tree_one.pt = t;
        tree_one.sign = (char) (CV_SIGN( s ));
        tree_one.area = fabs( s );
        tree_one.r1 = h / a;
        tree_one.r2 = b / a;
        tree_one.next_v1 = ptr2[3];
        tree_one.next_v2 = ptr2[0];

        tree_two.pt = tn2;
        tree_two.sign = (char) (CV_SIGN( sn2 ));
        tree_two.area = fabs( sn2 );
        tree_two.r1 = hn2 / an2;
        tree_two.r2 = bn2 / an2;
        tree_two.next_v1 = ptr2[1];
        tree_two.next_v2 = ptr2[2];

        CV_WRITE_SEQ_ELEM( tree_one, writer );
        cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

        if( s_c > sn2_c )
        {
            if( ptr2[3] != NULL )
                ptr2[3]->prev_v = cur_adr;
            if( ptr2[0] != NULL )
                ptr2[0]->prev_v = cur_adr;
            ptr1[0] = cur_adr;

            i_tree++;

            CV_WRITE_SEQ_ELEM( tree_two, writer );
            cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

            if( ptr2[1] != NULL )
                ptr2[1]->prev_v = cur_adr;
            if( ptr2[2] != NULL )
                ptr2[2]->prev_v = cur_adr;
            ptr1[1] = cur_adr;

            i_tree++;

            pt1[0] = tp1;
            pt1[1] = tn1;
        }
        else
        {
            CV_WRITE_SEQ_ELEM( tree_two, writer );
            cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

            if( ptr2[1] != NULL )
                ptr2[1]->prev_v = cur_adr;
            if( ptr2[2] != NULL )
                ptr2[2]->prev_v = cur_adr;
            ptr1[0] = cur_adr;

            i_tree++;

            CV_WRITE_SEQ_ELEM( tree_one, writer );
            cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

            if( ptr2[3] != NULL )
                ptr2[3]->prev_v = cur_adr;
            if( ptr2[0] != NULL )
                ptr2[0]->prev_v = cur_adr;
            ptr1[1] = cur_adr;

            i_tree++;

            pt1[0] = tn1;
            pt1[1] = tp1;
        }
    }
    else
    {
        tree_one.pt = tp1;
        tree_one.sign = (char) (CV_SIGN( sp1 ));
        tree_one.area = fabs( sp1 );
        tree_one.r1 = hp1 / ap1;
        tree_one.r2 = bp1 / ap1;
        tree_one.next_v1 = ptr2[2];
        tree_one.next_v2 = ptr2[3];

        tree_two.pt = tn1;
        tree_two.sign = (char) (CV_SIGN( sn1 ));
        tree_two.area = fabs( sn1 );
        tree_two.r1 = hn1 / an1;
        tree_two.r2 = bn1 / an1;
        tree_two.next_v1 = ptr2[0];
        tree_two.next_v2 = ptr2[1];

        CV_WRITE_SEQ_ELEM( tree_one, writer );
        cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

        if( sp1_c > sn1_c )
        {
            if( ptr2[2] != NULL )
                ptr2[2]->prev_v = cur_adr;
            if( ptr2[3] != NULL )
                ptr2[3]->prev_v = cur_adr;
            ptr1[0] = cur_adr;

            i_tree++;

            CV_WRITE_SEQ_ELEM( tree_two, writer );
            cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

            if( ptr2[0] != NULL )
                ptr2[0]->prev_v = cur_adr;
            if( ptr2[1] != NULL )
                ptr2[1]->prev_v = cur_adr;
            ptr1[1] = cur_adr;

            i_tree++;

            pt1[0] = tn2;
            pt1[1] = t;
        }
        else
        {
            CV_WRITE_SEQ_ELEM( tree_two, writer );
            cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

            if( ptr2[0] != NULL )
                ptr2[0]->prev_v = cur_adr;
            if( ptr2[1] != NULL )
                ptr2[1]->prev_v = cur_adr;
            ptr1[0] = cur_adr;

            i_tree++;

            CV_WRITE_SEQ_ELEM( tree_one, writer );
            cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);

            if( ptr2[2] != NULL )
                ptr2[2]->prev_v = cur_adr;
            if( ptr2[3] != NULL )
                ptr2[3]->prev_v = cur_adr;
            ptr1[1] = cur_adr;

            i_tree++;

            pt1[0] = t;
            pt1[1] = tn2;

        }
    }

/*    form root   */
    s = cvContourArea( contour );

    tree_root->pt = pt1[1];
    tree_root->sign = 0;
    tree_root->area = fabs( s );
    tree_root->r1 = 0;
    tree_root->r2 = 0;
    tree_root->next_v1 = ptr1[0];
    tree_root->next_v2 = ptr1[1];
    tree_root->prev_v = NULL;

    ptr1[0]->prev_v = (_CvTrianAttr *) tree_root;
    ptr1[1]->prev_v = (_CvTrianAttr *) tree_root;

/*     write binary tree root   */
/*    CV_WRITE_SEQ_ELEM (tree_one, start_writer);   */
    i_tree++;
/*  create Sequence hearder     */
    *((CvSeq **) tree) = cvEndWriteSeq( &writer );
/*   write points for the main segment into sequence header   */
    (*tree)->p1 = pt1[0];

  M_END:

    cvFree( &ptr_n );
    cvFree( &ptr_p );
    cvFree( &num_n );
    cvFree( &num_p );
    cvFree( &pt_n );
    cvFree( &pt_p );

    return status;
}
Example #5
0
static CvStatus
icvFindDominantPointsIPAN( CvSeq * contour,
                           CvMemStorage * storage,
                           CvSeq ** corners, int dmin2, int dmax2, int dneigh2, float amax )
{
    CvStatus status = CV_OK;

    /* variables */
    int n = contour->total;

    float *sharpness;
    float *distance;
    icvPointInfo *ptInf;

    int i, j, k;

    CvSeqWriter writer;

    float mincos = (float) cos( 3.14159265359 * amax / 180 );

    /* check bad arguments */
    if( contour == NULL )
        return CV_NULLPTR_ERR;
    if( storage == NULL )
        return CV_NULLPTR_ERR;
    if( corners == NULL )
        return CV_NULLPTR_ERR;
    if( dmin2 < 0 )
        return CV_BADSIZE_ERR;
    if( dmax2 < dmin2 )
        return CV_BADSIZE_ERR;
    if( (dneigh2 > dmax2) || (dneigh2 < 0) )
        return CV_BADSIZE_ERR;
    if( (amax < 0) || (amax > 180) )
        return CV_BADSIZE_ERR;

    sharpness = (float *) cvAlloc( n * sizeof( float ));
    distance = (float *) cvAlloc( n * sizeof( float ));

    ptInf = (icvPointInfo *) cvAlloc( n * sizeof( icvPointInfo ));

/*****************************************************************************************/
/*                                 First pass                                            */
/*****************************************************************************************/

    if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
    {
        CvChainPtReader reader;

        cvStartReadChainPoints( (CvChain *) contour, &reader );

        for( i = 0; i < n; i++ )
        {
            CV_READ_CHAIN_POINT( ptInf[i].pt, reader );
        }
    }
    else if( CV_IS_SEQ_POLYGON( contour ))
    {
        CvSeqReader reader;

        cvStartReadSeq( contour, &reader, 0 );

        for( i = 0; i < n; i++ )
        {
            CV_READ_SEQ_ELEM( ptInf[i].pt, reader );
        }
    }
    else
    {
        return CV_BADFLAG_ERR;
    }

    for( i = 0; i < n; i++ )
    {
        /* find nearest suitable points
           which satisfy distance constraint >dmin */
        int left_near = 0;
        int right_near = 0;
        int left_far, right_far;

        float dist_l = 0;
        float dist_r = 0;

        int i_plus = 0;
        int i_minus = 0;

        float max_cos_alpha;

        /* find  right minimum */
        while( dist_r < dmin2 )
        {
            float dx, dy;
            int ind;

            if( i_plus >= n )
                goto error;

            right_near = i_plus;

            if( dist_r < dneigh2 )
                ptInf[i].right_neigh = i_plus;

            i_plus++;

            ind = (i + i_plus) % n;
            dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
            dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
            dist_r = dx * dx + dy * dy;
        }
        /* find right maximum */
        while( dist_r <= dmax2 )
        {
            float dx, dy;
            int ind;

            if( i_plus >= n )
                goto error;

            distance[(i + i_plus) % n] = cvSqrt( dist_r );

            if( dist_r < dneigh2 )
                ptInf[i].right_neigh = i_plus;

            i_plus++;

            right_far = i_plus;

            ind = (i + i_plus) % n;

            dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
            dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
            dist_r = dx * dx + dy * dy;
        }
        right_far = i_plus;

        /* left minimum */
        while( dist_l < dmin2 )
        {
            float dx, dy;
            int ind;

            if( i_minus <= -n )
                goto error;

            left_near = i_minus;

            if( dist_l < dneigh2 )
                ptInf[i].left_neigh = i_minus;

            i_minus--;

            ind = i + i_minus;
            ind = (ind < 0) ? (n + ind) : ind;

            dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
            dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
            dist_l = dx * dx + dy * dy;
        }

        /* find left maximum */
        while( dist_l <= dmax2 )
        {
            float dx, dy;
            int ind;

            if( i_minus <= -n )
                goto error;

            ind = i + i_minus;
            ind = (ind < 0) ? (n + ind) : ind;

            distance[ind] = cvSqrt( dist_l );

            if( dist_l < dneigh2 )
                ptInf[i].left_neigh = i_minus;

            i_minus--;

            left_far = i_minus;

            ind = i + i_minus;
            ind = (ind < 0) ? (n + ind) : ind;

            dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
            dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
            dist_l = dx * dx + dy * dy;
        }
        left_far = i_minus;

        if( (i_plus - i_minus) > n + 2 )
            goto error;

        max_cos_alpha = -1;
        for( j = left_far + 1; j < left_near; j++ )
        {
            float dx, dy;
            float a, a2;
            int leftind = i + j;

            leftind = (leftind < 0) ? (n + leftind) : leftind;

            a = distance[leftind];
            a2 = a * a;

            for( k = right_near + 1; k < right_far; k++ )
            {
                int ind = (i + k) % n;
                float c2, cosalpha;
                float b = distance[ind];
                float b2 = b * b;

                /* compute cosinus */
                dx = (float) (ptInf[leftind].pt.x - ptInf[ind].pt.x);
                dy = (float) (ptInf[leftind].pt.y - ptInf[ind].pt.y);

                c2 = dx * dx + dy * dy;
                cosalpha = (a2 + b2 - c2) / (2 * a * b);

                max_cos_alpha = MAX( max_cos_alpha, cosalpha );

                if( max_cos_alpha < mincos )
                    max_cos_alpha = -1;

                sharpness[i] = max_cos_alpha;
            }
        }
    }
/*****************************************************************************************/
/*                                 Second pass                                           */
/*****************************************************************************************/

    cvStartWriteSeq( (contour->flags & ~CV_SEQ_ELTYPE_MASK) | CV_SEQ_ELTYPE_INDEX,
                     sizeof( CvSeq ), sizeof( int ), storage, &writer );

    /* second pass - nonmaxima suppression */
    /* neighborhood of point < dneigh2 */
    for( i = 0; i < n; i++ )
    {
        int suppressed = 0;
        if( sharpness[i] == -1 )
            continue;

        for( j = 1; (j <= ptInf[i].right_neigh) && (suppressed == 0); j++ )
        {
            if( sharpness[i] < sharpness[(i + j) % n] )
                suppressed = 1;
        }

        for( j = -1; (j >= ptInf[i].left_neigh) && (suppressed == 0); j-- )
        {
            int ind = i + j;

            ind = (ind < 0) ? (n + ind) : ind;
            if( sharpness[i] < sharpness[ind] )
                suppressed = 1;
        }

        if( !suppressed )
            CV_WRITE_SEQ_ELEM( i, writer );
    }

    *corners = cvEndWriteSeq( &writer );

    cvFree( &sharpness );
    cvFree( &distance );
    cvFree( &ptInf );

    return status;

  error:
    /* dmax is so big (more than contour diameter)
       that algorithm could become infinite cycle */
    cvFree( &sharpness );
    cvFree( &distance );
    cvFree( &ptInf );

    return CV_BADRANGE_ERR;
}