📄 cvapprox.cpp.svn-base
字号:
//////////////////////////////////////////////////////////////////////////////////////////// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.//// By downloading, copying, installing or using the software you agree to this license.// If you do not agree to this license, do not download, install,// copy or use the software.////// License For Embedded Computer Vision Library//// Copyright (c) 2008, EMCV Project,// Copyright (c) 2000-2007, Intel Corporation,// All rights reserved.// Third party copyrights are property of their respective owners.//// Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met://// * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution.// * Neither the name of the copyright holders nor the names of their contributors // may be used to endorse or promote products derived from this software // without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY // OF SUCH DAMAGE.//// Contributors:// * Shiqi Yu (Shenzhen Institute of Advanced Technology, Chinese Academy of Sciences)#include "_cv.h"/****************************************************************************************\* Chain Approximation *\****************************************************************************************/typedef struct _CvPtInfo{ CvPoint pt; int k; /* support region */ int s; /* curvature value */ struct _CvPtInfo *next;}_CvPtInfo;/* curvature: 0 - 1-curvature, 1 - k-cosine curvature. */CvStatusicvApproximateChainTC89( CvChain* chain, int header_size, CvMemStorage* storage, CvSeq** contour, int method ){ static const int abs_diff[] = { 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 3, 2, 1 }; char local_buffer[1 << 16]; char* buffer = local_buffer; int buffer_size; _CvPtInfo temp; _CvPtInfo *array, *first = 0, *current = 0, *prev_current = 0; int i, j, i1, i2, s, len; int count; CvChainPtReader reader; CvSeqWriter writer; CvPoint pt = chain->origin; assert( chain && contour && buffer ); buffer_size = (chain->total + 8) * sizeof( _CvPtInfo ); *contour = 0; if( !CV_IS_SEQ_CHAIN_CONTOUR( chain )) return CV_BADFLAG_ERR; if( header_size < (int)sizeof(CvContour) ) return CV_BADSIZE_ERR; cvStartWriteSeq( (chain->flags & ~CV_SEQ_ELTYPE_MASK) | CV_SEQ_ELTYPE_POINT, header_size, sizeof( CvPoint ), storage, &writer ); if( chain->total == 0 ) { CV_WRITE_SEQ_ELEM( pt, writer ); goto exit_function; } cvStartReadChainPoints( chain, &reader ); if( method > CV_CHAIN_APPROX_SIMPLE && buffer_size > (int)sizeof(local_buffer)) { buffer = (char *) cvAlloc( buffer_size ); if( !buffer ) return CV_OUTOFMEM_ERR; } array = (_CvPtInfo *) buffer; count = chain->total; temp.next = 0; current = &temp; /* Pass 0. Restores all the digital curve points from the chain code. Removes the points (from the resultant polygon) that have zero 1-curvature */ for( i = 0; i < count; i++ ) { int prev_code = *reader.prev_elem; reader.prev_elem = reader.ptr; CV_READ_CHAIN_POINT( pt, reader ); /* calc 1-curvature */ s = abs_diff[reader.code - prev_code + 7]; if( method <= CV_CHAIN_APPROX_SIMPLE ) { if( method == CV_CHAIN_APPROX_NONE || s != 0 ) { CV_WRITE_SEQ_ELEM( pt, writer ); } } else { if( s != 0 ) current = current->next = array + i; array[i].s = s; array[i].pt = pt; } } //assert( pt.x == chain->origin.x && pt.y == chain->origin.y ); if( method <= CV_CHAIN_APPROX_SIMPLE ) goto exit_function; current->next = 0; len = i; current = temp.next; assert( current ); /* Pass 1. Determines support region for all the remained points */ do { CvPoint pt0; int k, l = 0, d_num = 0; i = (int)(current - array); pt0 = array[i].pt; /* determine support region */ for( k = 1;; k++ ) { int lk, dk_num; int dx, dy; Cv32suf d; assert( k <= len ); /* calc indices */ i1 = i - k; i1 += i1 < 0 ? len : 0; i2 = i + k; i2 -= i2 >= len ? len : 0; dx = array[i2].pt.x - array[i1].pt.x; dy = array[i2].pt.y - array[i1].pt.y; /* distance between p_(i - k) and p_(i + k) */ lk = dx * dx + dy * dy; /* distance between p_i and the line (p_(i-k), p_(i+k)) */ dk_num = (pt0.x - array[i1].pt.x) * dy - (pt0.y - array[i1].pt.y) * dx; d.f = (float) (((double) d_num) * lk - ((double) dk_num) * l); if( k > 1 && (l >= lk || (d_num > 0 && d.i <= 0 || d_num < 0 && d.i >= 0))) break; d_num = dk_num; l = lk; } current->k = --k; /* determine cosine curvature if it should be used */ if( method == CV_CHAIN_APPROX_TC89_KCOS ) { /* calc k-cosine curvature */ for( j = k, s = 0; j > 0; j-- ) { double temp_num; int dx1, dy1, dx2, dy2; Cv32suf sk; i1 = i - j; i1 += i1 < 0 ? len : 0; i2 = i + j; i2 -= i2 >= len ? len : 0; dx1 = array[i1].pt.x - pt0.x; dy1 = array[i1].pt.y - pt0.y; dx2 = array[i2].pt.x - pt0.x; dy2 = array[i2].pt.y - pt0.y; if( (dx1 | dy1) == 0 || (dx2 | dy2) == 0 ) break; temp_num = dx1 * dx2 + dy1 * dy2; temp_num = (float) (temp_num / sqrt( ((double)dx1 * dx1 + (double)dy1 * dy1) * ((double)dx2 * dx2 + (double)dy2 * dy2) )); sk.f = (float) (temp_num + 1.1); assert( 0 <= sk.f && sk.f <= 2.2 ); if( j < k && sk.i <= s ) break; s = sk.i; } current->s = s; } current = current->next; } while( current != 0 ); prev_current = &temp; current = temp.next; /* Pass 2. Performs non-maxima supression */ do { int k2 = current->k >> 1; s = current->s; i = (int)(current - array); for( j = 1; j <= k2; j++ ) { i2 = i - j; i2 += i2 < 0 ? len : 0; if( array[i2].s > s ) break; i2 = i + j; i2 -= i2 >= len ? len : 0; if( array[i2].s > s ) break; } if( j <= k2 ) /* exclude point */ { prev_current->next = current->next; current->s = 0; /* "clear" point */ } else prev_current = current; current = current->next; } while( current != 0 ); /* Pass 3. Removes non-dominant points with 1-length support region */ current = temp.next; assert( current ); prev_current = &temp; do { if( current->k == 1 ) { s = current->s; i = (int)(current - array); i1 = i - 1; i1 += i1 < 0 ? len : 0; i2 = i + 1; i2 -= i2 >= len ? len : 0; if( s <= array[i1].s || s <= array[i2].s ) { prev_current->next = current->next; current->s = 0; } else prev_current = current; } else prev_current = current; current = current->next; } while( current != 0 ); if( method == CV_CHAIN_APPROX_TC89_KCOS ) goto copy_vect; /* Pass 4. Cleans remained couples of points */ assert( temp.next ); if( array[0].s != 0 && array[len - 1].s != 0 ) /* specific case */ { for( i1 = 1; i1 < len && array[i1].s != 0; i1++ ) { array[i1 - 1].s = 0; } if( i1 == len ) goto copy_vect; /* all points survived */ i1--; for( i2 = len - 2; i2 > 0 && array[i2].s != 0; i2-- ) { array[i2].next = 0; array[i2 + 1].s = 0; } i2++; if( i1 == 0 && i2 == len - 1 ) /* only two points */ { i1 = (int)(array[0].next - array); array[len] = array[0]; /* move to the end */ array[len].next = 0; array[len - 1].next = array + len; } temp.next = array + i1; } current = temp.next; first = prev_current = &temp; count = 1; /* do last pass */ do { 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;}/* End of file. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -