📄 cvcontours.cpp
字号:
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;}CvSeq *cvFindNextContour( CvContourScanner scanner ){ char *img0; char *img; int step; int width, height; int x, y; int prev; CvPoint lnbd; CvSeq *contour = 0; int nbd; int mode; CvStatus result = (CvStatus) 1; CV_FUNCNAME( "cvFindNextContour" ); __BEGIN__; if( !scanner ) CV_ERROR( CV_StsNullPtr, "" ); icvEndProcessContour( scanner ); /* initialize local state */ img0 = scanner->img0; img = scanner->img; step = scanner->img_step; x = scanner->pt.x; y = scanner->pt.y; width = scanner->img_size.width; height = scanner->img_size.height; mode = scanner->mode; lnbd = scanner->lnbd; nbd = scanner->nbd; prev = img[x - 1]; for( ; y < height; y++, img += step ) { for( ; x < width; x++ ) { int p = img[x]; if( p != prev ) { _CvContourInfo *par_info = 0; _CvContourInfo *l_cinfo = 0; CvSeq *seq = 0; int is_hole = 0; CvPoint origin; if( !(prev == 0 && p == 1) ) /* if not external contour */ { /* check hole */ if( p != 0 || prev < 1 ) goto resume_scan; if( prev & -2 ) { lnbd.x = x - 1; } is_hole = 1; } if( mode == 0 && (is_hole || img0[lnbd.y * step + lnbd.x] > 0) ) goto resume_scan; origin.y = y; origin.x = x - is_hole; /* find contour parent */ if( mode <= 1 || (!is_hole && mode == 2) || lnbd.x <= 0 ) { par_info = &(scanner->frame_info); } else { int lval = img0[lnbd.y * step + lnbd.x] & 0x7f; _CvContourInfo *cur = scanner->cinfo_table[lval - 2]; assert( lval >= 2 ); /* find the first bounding contour */ while( cur ) { if( (unsigned) (lnbd.x - cur->rect.x) < (unsigned) cur->rect.width && (unsigned) (lnbd.y - cur->rect.y) < (unsigned) cur->rect.height ) { if( par_info ) { if( icvTraceContour( scanner->img0 + par_info->origin.y * step + par_info->origin.x, step, img + lnbd.x, par_info->is_hole ) > 0 ) break; } par_info = cur; } cur = cur->next; } assert( par_info != 0 ); /* if current contour is a hole and previous contour is a hole or current contour is external and previous contour is external then the parent of the contour is the parent of the previous contour else the parent is the previous contour itself. */ if( par_info->is_hole == is_hole ) { par_info = par_info->parent; /* every contour must have a parent (at least, the frame of the image) */ if( !par_info ) par_info = &(scanner->frame_info); } /* hole flag of the parent must differ from the flag of the contour */ assert( par_info->is_hole != is_hole ); if( par_info->contour == 0 ) /* removed contour */ goto resume_scan; } lnbd.x = x - is_hole; cvSaveMemStoragePos( scanner->storage2, &(scanner->backup_pos) ); seq = cvCreateSeq( scanner->seq_type1, scanner->header_size1, scanner->elem_size1, scanner->storage1 ); if( !seq ) { result = CV_OUTOFMEM_ERR; goto exit_func; } seq->flags |= is_hole ? CV_SEQ_FLAG_HOLE : 0; /* initialize header */ if( mode <= 1 ) { l_cinfo = &(scanner->cinfo_temp); result = icvFetchContour( img + x - is_hole, step, cvPoint( origin.x + scanner->offset.x, origin.y + scanner->offset.y), seq, scanner->approx_method1 ); if( result < 0 ) goto exit_func; } else { union { _CvContourInfo* ci; CvSetElem* se; } v; v.ci = l_cinfo; cvSetAdd( scanner->cinfo_set, 0, &v.se ); l_cinfo = v.ci; result = icvFetchContourEx( img + x - is_hole, step, cvPoint( origin.x + scanner->offset.x, origin.y + scanner->offset.y), seq, scanner->approx_method1, nbd, &(l_cinfo->rect) ); if( result < 0 ) goto exit_func; l_cinfo->rect.x -= scanner->offset.x; l_cinfo->rect.y -= scanner->offset.y; l_cinfo->next = scanner->cinfo_table[nbd - 2]; scanner->cinfo_table[nbd - 2] = l_cinfo; /* change nbd */ nbd = (nbd + 1) & 127; nbd += nbd == 0 ? 3 : 0; } l_cinfo->is_hole = is_hole; l_cinfo->contour = seq; l_cinfo->origin = origin; l_cinfo->parent = par_info; if( scanner->approx_method1 != scanner->approx_method2 ) { result = icvApproximateChainTC89( (CvChain *) seq, scanner->header_size2, scanner->storage2, &(l_cinfo->contour), scanner->approx_method2 ); if( result < 0 ) goto exit_func; cvClearMemStorage( scanner->storage1 ); } l_cinfo->contour->v_prev = l_cinfo->parent->contour; if( par_info->contour == 0 ) { l_cinfo->contour = 0; if( scanner->storage1 == scanner->storage2 ) { cvRestoreMemStoragePos( scanner->storage1, &(scanner->backup_pos) ); } else { cvClearMemStorage( scanner->storage1 ); } p = img[x]; goto resume_scan; } cvSaveMemStoragePos( scanner->storage2, &(scanner->backup_pos2) ); scanner->l_cinfo = l_cinfo; scanner->pt.x = x + 1; scanner->pt.y = y; scanner->lnbd = lnbd; scanner->img = (char *) img; scanner->nbd = nbd; contour = l_cinfo->contour; result = CV_OK; goto exit_func; resume_scan: prev = p; /* update lnbd */ if( prev & -2 ) { lnbd.x = x; } } /* end of prev != p */ } /* end of loop on x */ lnbd.x = 0; lnbd.y = y + 1; x = 1; prev = 0; } /* end of loop on y */ exit_func: if( result != 0 ) contour = 0; if( result < 0 ) CV_ERROR_FROM_STATUS( result ); __END__; return contour;}/* The function add to tree the last retrieved/substituted contour, releases temp_storage, restores state of dst_storage (if needed), and returns pointer to root of the contour tree */CV_IMPL CvSeq *cvEndFindContours( CvContourScanner * _scanner ){ CvContourScanner scanner; CvSeq *first = 0; CV_FUNCNAME( "cvFindNextContour" ); __BEGIN__; if( !_scanner ) CV_ERROR( CV_StsNullPtr, "" ); scanner = *_scanner; if( scanner ) { icvEndProcessContour( scanner ); if( scanner->storage1 != scanner->storage2 ) cvReleaseMemStorage( &(scanner->storage1) ); if( scanner->cinfo_storage ) cvReleaseMemStorage( &(scanner->cinfo_storage) ); first = scanner->frame.v_next; cvFree( _scanner ); } __END__; return first;}#define ICV_SINGLE 0#define ICV_CONNECTING_ABOVE 1#define ICV_CONNECTING_BELOW -1#define ICV_IS_COMPONENT_POINT(val) ((val) != 0)#define CV_GET_WRITTEN_ELEM( writer ) ((writer).ptr - (writer).seq->elem_size)typedef struct CvLinkedRunPoint{ struct CvLinkedRunPoint* link; struct CvLinkedRunPoint* next; CvPoint pt;}CvLinkedRunPoint;static inticvFindContoursInInterval( const CvArr* src, /*int minValue, int maxValue,*/ CvMemStorage* storage, CvSeq** result, int contourHeaderSize ){ int count = 0; CvMemStorage* storage00 = 0; CvMemStorage* storage01 = 0; CvSeq* first = 0; CV_FUNCNAME( "icvFindContoursInInterval" ); __BEGIN__; int i, j, k, n; uchar* src_data = 0; int img_step = 0; CvSize img_size; int connect_flag; int lower_total; int upper_total; int all_total; CvSeq* runs; CvLinkedRunPoint tmp; CvLinkedRunPoint* tmp_prev; CvLinkedRunPoint* upper_line = 0; CvLinkedRunPoint* lower_line = 0; CvLinkedRunPoint* last_elem; CvLinkedRunPoint* upper_run = 0; CvLinkedRunPoint* lower_run = 0; CvLinkedRunPoint* prev_point = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -