コード例 #1
0
/* 
   trace contour until certain point is met.
   returns 1 if met, 0 else.
*/
static int
icvTraceContour( char *ptr, int step, char *stop_ptr, int is_hole )
{
    int deltas[16];
    char *i0 = ptr, *i1, *i3, *i4;
    int s, s_end;

    /* initialize local state */
    CV_INIT_3X3_DELTAS( deltas, step, 1 );
    memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] ));

    assert( (*i0 & -2) != 0 );

    s_end = s = is_hole ? 0 : 4;

    do
    {
        s = (s - 1) & 7;
        i1 = i0 + deltas[s];
        if( *i1 != 0 )
            break;
    }
    while( s != s_end );

    i3 = i0;

    /* check single pixel domain */
    if( s != s_end )
    {
        /* follow border */
        for( ;; )
        {
            s_end = s;

            for( ;; )
            {
                i4 = i3 + deltas[++s];
                if( *i4 != 0 )
                    break;
            }

            if( i3 == stop_ptr || (i4 == i0 && i3 == i1) )
                break;

            i3 = i4;
            s = (s + 4) & 7;
        }                       /* end of border following loop */
    }
    return i3 == stop_ptr;
}
コード例 #2
0
ファイル: segment.cpp プロジェクト: 353/viewercv
static CvSeq*
icvGetComponent(uchar* img, int step, CvRect rect,
CvMemStorage* storage) {
    const char nbd = 4;
    int  deltas[16];
    int  x, y;
    CvSeq* exterior = 0;
    char* ptr;

    /* initialize local state */
    CV_INIT_3X3_DELTAS(deltas, step, 1);
    memcpy(deltas + 8, deltas, 8 * sizeof(deltas[0]));

    ptr = (char*)(img + step * rect.y);
    rect.width += rect.x;
    rect.height += rect.y;

    for (y = rect.y; y < rect.height; y++, ptr += step) {
        int prev = ptr[rect.x - 1] & -2;

        for (x = rect.x; x < rect.width; x++) {
            int p = ptr[x] & -2;

            //assert( exterior || ((p | prev) & -4) == 0 );

            if (p != prev) {
                CvSeq* seq = 0;
                int is_hole = 0;
                CvSeqWriter  writer;
                char*  i0, *i1, *i3, *i4 = 0;
                int  prev_s = -1, s, s_end;
                CvPoint pt = { x, y };

                if (!(prev == 0 && p == 2)) {   /* if not external contour */
                    /* check hole */
                    if (p != 0 || prev < 1) {
                        prev = p;
                        continue;
                    }

                    is_hole = 1;
                    if (!exterior) {
                        assert(0);
                        return 0;
                    }
                }

                cvStartWriteSeq(CV_SEQ_CONTOUR | (is_hole ? CV_SEQ_FLAG_HOLE : 0),
                sizeof(CvContour), sizeof(CvPoint), storage, &writer);
                s_end = s = is_hole ? 0 : 4;
                i0 = ptr + x - is_hole;

                do {
                    s = (s - 1) & 7;
                    i1 = i0 + deltas[s];
                    if ((*i1 & -2) != 0) {
                        break;
                    }
                } while (s != s_end);

                if (s == s_end) {           /* single pixel domain */
                    *i0 = (char)(nbd | -128);
                    CV_WRITE_SEQ_ELEM(pt, writer);
                } else {
                    i3 = i0;
                    prev_s = s ^ 4;

                    /* follow border */
                    for (;;) {
                        s_end = s;

                        for (;;) {
                            i4 = i3 + deltas[++s];
                            if ((*i4 & -2) != 0) {
                                break;
                            }
                        }
                        s &= 7;

                        /* check "right" bound */
                        if ((unsigned)(s - 1) < (unsigned) s_end) {
                            *i3 = (char)(nbd | -128);
                        } else if (*i3 > 0) {
                            *i3 = nbd;
                        }

                        if (s != prev_s) {
                            CV_WRITE_SEQ_ELEM(pt, writer);
                            prev_s = s;
                        }

                        pt.x += icvCodeDeltas[s].x;
                        pt.y += icvCodeDeltas[s].y;

                        if (i4 == i0 && i3 == i1) {
                            break;
                        }

                        i3 = i4;
                        s = (s + 4) & 7;
                    }                       /* end of border following loop */
                }

                seq = cvEndWriteSeq(&writer);
                cvContourBoundingRect(seq, 1);

                if (!is_hole) {
                    exterior = seq;
                } else {
                    seq->v_prev = exterior;
                    seq->h_next = exterior->v_next;
                    if (seq->h_next) {
                        seq->h_next->h_prev = seq;
                    }
                    exterior->v_next = seq;
                }

                prev = ptr[x] & -2;
            }
        }
    }

    return exterior;
}
コード例 #3
0
static CvStatus
icvFetchContourEx( char*                ptr, 
                   int                  step,
                   CvPoint              pt, 
                   CvSeq*               contour,
                   int  _method, 
                   int                  nbd,
                   CvRect*              _rect )
{
    int         deltas[16];
    CvSeqWriter writer;
    char        *i0 = ptr, *i1, *i3, *i4;
    CvRect      rect;
    int         prev_s = -1, s, s_end;
    int         method = _method - 1;

    assert( (unsigned) _method <= CV_CHAIN_APPROX_SIMPLE );
    assert( 1 < nbd && nbd < 128 );

    /* initialize local state */
    CV_INIT_3X3_DELTAS( deltas, step, 1 );
    memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] ));

    /* initialize writer */
    cvStartAppendToSeq( contour, &writer );

    if( method < 0 )
        ((CvChain *)contour)->origin = pt;

    rect.x = rect.width = pt.x;
    rect.y = rect.height = pt.y;

    s_end = s = CV_IS_SEQ_HOLE( contour ) ? 0 : 4;

    do
    {
        s = (s - 1) & 7;
        i1 = i0 + deltas[s];
        if( *i1 != 0 )
            break;
    }
    while( s != s_end );

    if( s == s_end )            /* single pixel domain */
    {
        *i0 = (char) (nbd | 0x80);
        if( method >= 0 )
        {
            CV_WRITE_SEQ_ELEM( pt, writer );
        }
    }
    else
    {
        i3 = i0;

        prev_s = s ^ 4;

        /* follow border */
        for( ;; )
        {
            s_end = s;

            for( ;; )
            {
                i4 = i3 + deltas[++s];
                if( *i4 != 0 )
                    break;
            }
            s &= 7;

            /* check "right" bound */
            if( (unsigned) (s - 1) < (unsigned) s_end )
            {
                *i3 = (char) (nbd | 0x80);
            }
            else if( *i3 == 1 )
            {
                *i3 = (char) nbd;
            }

            if( method < 0 )
            {
                char _s = (char) s;
                CV_WRITE_SEQ_ELEM( _s, writer );
            }
            else if( s != prev_s || method == 0 )
            {
                CV_WRITE_SEQ_ELEM( pt, writer );
            }

            if( s != prev_s )
            {
                /* update bounds */
                if( pt.x < rect.x )
                    rect.x = pt.x;
                else if( pt.x > rect.width )
                    rect.width = pt.x;

                if( pt.y < rect.y )
                    rect.y = pt.y;
                else if( pt.y > rect.height )
                    rect.height = pt.y;
            }

            prev_s = s;
            pt.x += icvCodeDeltas[s].x;
            pt.y += icvCodeDeltas[s].y;

            if( i4 == i0 && i3 == i1 )  break;

            i3 = i4;
            s = (s + 4) & 7;
        }                       /* end of border following loop */
    }

    rect.width -= rect.x - 1;
    rect.height -= rect.y - 1;

    cvEndWriteSeq( &writer );

    if( _method != CV_CHAIN_CODE )
        ((CvContour*)contour)->rect = rect;

    assert( writer.seq->total == 0 && writer.seq->first == 0 ||
            writer.seq->total > writer.seq->first->count ||
            (writer.seq->first->prev == writer.seq->first &&
             writer.seq->first->next == writer.seq->first) );

    if( _rect )  *_rect = rect;

    return CV_OK;
}