📄 cvapprox.cpp
字号:
if( current->next == 0 || current->next - current != 1 )
{
if( count >= 2 )
{
if( count == 2 )
{
int s1 = prev_current->s;
int s2 = current->s;
if( s1 > s2 || s1 == s2 && prev_current->k <= current->k )
/* remove second */
prev_current->next = current->next;
else
/* remove first */
first->next = current;
}
else
first->next->next = current;
}
first = current;
count = 1;
}
else
count++;
prev_current = current;
current = current->next;
}
while( current != 0 );
copy_vect:
/* gather points */
current = temp.next;
assert( current );
do
{
CV_WRITE_SEQ_ELEM( current->pt, writer );
current = current->next;
}
while( current != 0 );
exit_function:
*contour = cvEndWriteSeq( &writer );
assert( writer.seq->total > 0 );
if( buffer != local_buffer )
cvFree( &buffer );
return CV_OK;
}
/*Applies some approximation algorithm to chain-coded contour(s) and
converts it/them to polygonal representation */
CV_IMPL CvSeq*
cvApproxChains( CvSeq* src_seq,
CvMemStorage* storage,
int method,
double /*parameter*/,
int minimal_perimeter,
int recursive )
{
CvSeq *prev_contour = 0, *parent = 0;
CvSeq *dst_seq = 0;
CV_FUNCNAME( "cvApproxChains" );
__BEGIN__;
if( !src_seq || !storage )
CV_ERROR( CV_StsNullPtr, "" );
if( method > CV_CHAIN_APPROX_TC89_KCOS || method <= 0 || minimal_perimeter < 0 )
CV_ERROR( CV_StsOutOfRange, "" );
while( src_seq != 0 )
{
int len = src_seq->total;
if( len >= minimal_perimeter )
{
CvSeq *contour;
switch( method )
{
case CV_CHAIN_APPROX_NONE:
case CV_CHAIN_APPROX_SIMPLE:
case CV_CHAIN_APPROX_TC89_L1:
case CV_CHAIN_APPROX_TC89_KCOS:
IPPI_CALL( icvApproximateChainTC89( (CvChain *) src_seq,
sizeof( CvContour ), storage,
(CvSeq**)&contour, method ));
break;
default:
assert(0);
CV_ERROR( CV_StsOutOfRange, "" );
}
assert( contour );
if( contour->total > 0 )
{
cvBoundingRect( contour, 1 );
contour->v_prev = parent;
contour->h_prev = prev_contour;
if( prev_contour )
prev_contour->h_next = contour;
else if( parent )
parent->v_next = contour;
prev_contour = contour;
if( !dst_seq )
dst_seq = prev_contour;
}
else /* if resultant contour has zero length, skip it */
{
len = -1;
}
}
if( !recursive )
break;
if( src_seq->v_next && len >= minimal_perimeter )
{
assert( prev_contour != 0 );
parent = prev_contour;
prev_contour = 0;
src_seq = src_seq->v_next;
}
else
{
while( src_seq->h_next == 0 )
{
src_seq = src_seq->v_prev;
if( src_seq == 0 )
break;
prev_contour = parent;
if( parent )
parent = parent->v_prev;
}
if( src_seq )
src_seq = src_seq->h_next;
}
}
__END__;
return dst_seq;
}
/****************************************************************************************\
* Polygonal Approximation *
\****************************************************************************************/
/* Ramer-Douglas-Peucker algorithm for polygon simplification */
/* the version for integer point coordinates */
static CvStatus
icvApproxPolyDP_32s( CvSeq* src_contour, int header_size,
CvMemStorage* storage,
CvSeq** dst_contour, float eps )
{
int init_iters = 3;
CvSlice slice = {0, 0}, right_slice = {0, 0};
CvSeqReader reader, reader2;
CvSeqWriter writer;
CvPoint start_pt = {INT_MIN, INT_MIN}, end_pt = {0, 0}, pt = {0,0};
int i = 0, j, count = src_contour->total, new_count;
int is_closed = CV_IS_SEQ_CLOSED( src_contour );
int le_eps = 0;
CvMemStorage* temp_storage = 0;
CvSeq* stack = 0;
assert( CV_SEQ_ELTYPE(src_contour) == CV_32SC2 );
cvStartWriteSeq( src_contour->flags, header_size, sizeof(pt), storage, &writer );
if( src_contour->total == 0 )
{
*dst_contour = cvEndWriteSeq( &writer );
return CV_OK;
}
temp_storage = cvCreateChildMemStorage( storage );
assert( src_contour->first != 0 );
stack = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvSlice), temp_storage );
eps *= eps;
cvStartReadSeq( src_contour, &reader, 0 );
if( !is_closed )
{
right_slice.start_index = count;
end_pt = *(CvPoint*)(reader.ptr);
start_pt = *(CvPoint*)cvGetSeqElem( src_contour, -1 );
if( start_pt.x != end_pt.x || start_pt.y != end_pt.y )
{
slice.start_index = 0;
slice.end_index = count - 1;
cvSeqPush( stack, &slice );
}
else
{
is_closed = 1;
init_iters = 1;
}
}
if( is_closed )
{
/* 1. Find approximately two farthest points of the contour */
right_slice.start_index = 0;
for( i = 0; i < init_iters; i++ )
{
int max_dist = 0;
cvSetSeqReaderPos( &reader, right_slice.start_index, 1 );
CV_READ_SEQ_ELEM( start_pt, reader ); /* read the first point */
for( j = 1; j < count; j++ )
{
int dx, dy, dist;
CV_READ_SEQ_ELEM( pt, reader );
dx = pt.x - start_pt.x;
dy = pt.y - start_pt.y;
dist = dx * dx + dy * dy;
if( dist > max_dist )
{
max_dist = dist;
right_slice.start_index = j;
}
}
le_eps = max_dist <= eps;
}
/* 2. initialize the stack */
if( !le_eps )
{
slice.start_index = cvGetSeqReaderPos( &reader );
slice.end_index = right_slice.start_index += slice.start_index;
right_slice.start_index -= right_slice.start_index >= count ? count : 0;
right_slice.end_index = slice.start_index;
if( right_slice.end_index < right_slice.start_index )
right_slice.end_index += count;
cvSeqPush( stack, &right_slice );
cvSeqPush( stack, &slice );
}
else
CV_WRITE_SEQ_ELEM( start_pt, writer );
}
/* 3. run recursive process */
while( stack->total != 0 )
{
cvSeqPop( stack, &slice );
if( slice.end_index > slice.start_index + 1 )
{
int dx, dy, dist, max_dist = 0;
cvSetSeqReaderPos( &reader, slice.end_index );
CV_READ_SEQ_ELEM( end_pt, reader );
cvSetSeqReaderPos( &reader, slice.start_index );
CV_READ_SEQ_ELEM( start_pt, reader );
dx = end_pt.x - start_pt.x;
dy = end_pt.y - start_pt.y;
assert( dx != 0 || dy != 0 );
for( i = slice.start_index + 1; i < slice.end_index; i++ )
{
CV_READ_SEQ_ELEM( pt, reader );
dist = abs((pt.y - start_pt.y) * dx - (pt.x - start_pt.x) * dy);
if( dist > max_dist )
{
max_dist = dist;
right_slice.start_index = i;
}
}
le_eps = (double)max_dist * max_dist <= eps * ((double)dx * dx + (double)dy * dy);
}
else
{
assert( slice.end_index > slice.start_index );
le_eps = 1;
/* read starting point */
cvSetSeqReaderPos( &reader, slice.start_index );
CV_READ_SEQ_ELEM( start_pt, reader );
}
if( le_eps )
{
CV_WRITE_SEQ_ELEM( start_pt, writer );
}
else
{
right_slice.end_index = slice.end_index;
slice.end_index = right_slice.start_index;
cvSeqPush( stack, &right_slice );
cvSeqPush( stack, &slice );
}
}
is_closed = CV_IS_SEQ_CLOSED( src_contour );
if( !is_closed )
CV_WRITE_SEQ_ELEM( end_pt, writer );
*dst_contour = cvEndWriteSeq( &writer );
cvStartReadSeq( *dst_contour, &reader, is_closed );
CV_READ_SEQ_ELEM( start_pt, reader );
reader2 = reader;
CV_READ_SEQ_ELEM( pt, reader );
new_count = count = (*dst_contour)->total;
for( i = !is_closed; i < count - !is_closed && new_count > 2; i++ )
{
int dx, dy, dist;
CV_READ_SEQ_ELEM( end_pt, reader );
dx = end_pt.x - start_pt.x;
dy = end_pt.y - start_pt.y;
dist = abs((pt.x - start_pt.x)*dy - (pt.y - start_pt.y)*dx);
if( (double)dist * dist <= 0.5*eps*((double)dx*dx + (double)dy*dy) && dx != 0 && dy != 0 )
{
new_count--;
*((CvPoint*)reader2.ptr) = start_pt = end_pt;
CV_NEXT_SEQ_ELEM( sizeof(pt), reader2 );
CV_READ_SEQ_ELEM( pt, reader );
i++;
continue;
}
*((CvPoint*)reader2.ptr) = start_pt = pt;
CV_NEXT_SEQ_ELEM( sizeof(pt), reader2 );
pt = end_pt;
}
if( !is_closed )
*((CvPoint*)reader2.ptr) = pt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -