?? cvcontours.cpp
字號:
cvEndFindContours( &scanner, &first_contour ); ... ----------------------------------------------------------------- Second variant is more complex and can be used when someone wants store not the retrieved contours but transformed ones. (e.g. approximated with some non-default algorithm ). The scheme can be the as following: icvContourScanner scanner; CvMemStorage* contour_storage; CvMemStorage* temp_storage; CvSeq* first_contour; CvStatus result; ... icvCreateMemStorage( &contour_storage, block_size/0 ); icvCreateMemStorage( &temp_storage, block_size/0 ); ... icvStartFindContours8uC1R ( <img_params>, temp_storage, header_size, approx_method, [retrival_mode], &scanner ); for(;;) { CvSeq* temp_contour; CvSeq* new_contour; result = icvFindNextContour( scanner, &temp_contour ); if( result != CV_OK ) break; <approximation_function>( temp_contour, contour_storage, &new_contour, <parameters...> ); icvSubstituteContour( scanner, new_contour ); ... } if( result < 0 ) goto error_processing; cvEndFindContours( &scanner, &first_contour ); ... ---------------------------------------------------------------------------- Third method to retrieve contours may be applied if contours are irrelevant themselves but some characteristics of them are used only. The usage is similar to second except slightly different internal loop for(;;) { CvSeq* temp_contour; result = icvFindNextContour( &scanner, &temp_contour ); if( result != CV_OK ) break; // calculate some characteristics of temp_contour icvSubstituteContour( scanner, 0 ); ... } new_storage variable is not needed here. Two notes. 1. Second and third method can interleave. I.e. it is possible to remain contours that satisfy with some criteria and reject others. In hierarchic case the resulting tree is the part of original tree with some nodes absent. But in the resulting tree the contour1 is a child (may be indirect) of contour2 iff in the original tree the contour1 is a child (may be indirect) of contour2.*/static voidicvEndProcessContour( CvContourScanner scanner ){ _CvContourInfo *l_cinfo = scanner->l_cinfo; if( l_cinfo ) { if( scanner->subst_flag ) { CvMemStoragePos temp; cvSaveMemStoragePos( scanner->storage2, &temp ); if( temp.top == scanner->backup_pos2.top && temp.free_space == scanner->backup_pos2.free_space ) { cvRestoreMemStoragePos( scanner->storage2, &scanner->backup_pos ); } scanner->subst_flag = 0; } if( l_cinfo->contour ) { cvInsertNodeIntoTree( l_cinfo->contour, l_cinfo->parent->contour, &(scanner->frame) ); } scanner->l_cinfo = 0; }}/* replaces one contour with another */CV_IMPL voidcvSubstituteContour( CvContourScanner scanner, CvSeq * new_contour ){ _CvContourInfo *l_cinfo; CV_FUNCNAME( "cvSubstituteContour" ); __BEGIN__; if( !scanner ) CV_ERROR( CV_StsNullPtr, "" ); l_cinfo = scanner->l_cinfo; if( l_cinfo && l_cinfo->contour && l_cinfo->contour != new_contour ) { l_cinfo->contour = new_contour; scanner->subst_flag = 1; } __END__;}/* marks domain border with +/-<constant> and stores the contour into CvSeq. method: <0 - chain ==0 - direct >0 - simple approximation*/static CvStatusicvFetchContour( char *ptr, int step, CvPoint pt, CvSeq* contour, int _method ){ const char nbd = 2; int deltas[16]; CvSeqWriter writer; char *i0 = ptr, *i1, *i3, *i4 = 0; int prev_s = -1, s, s_end; int method = _method - 1; assert( (unsigned) _method <= CV_CHAIN_APPROX_SIMPLE ); /* 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; 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 | -128); 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 | -128); } else if( *i3 == 1 ) { *i3 = 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 ); 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 */ } cvEndWriteSeq( &writer ); if( _method != CV_CHAIN_CODE ) cvBoundingRect( contour, 1 ); 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) ); return CV_OK;}/* trace contour until certain point is met. returns 1 if met, 0 else.*/static inticvTraceContour( 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;}static CvStatusicvFetchContourEx( 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; }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -