/* external contour area function */ CV_IMPL double cvContourArea( const void *array, CvSlice slice, int oriented ) { double area = 0; CvContour contour_header; CvSeq* contour = 0; CvSeqBlock block; if( CV_IS_SEQ( array )) { contour = (CvSeq*)array; if( !CV_IS_SEQ_POLYLINE( contour )) CV_Error( CV_StsBadArg, "Unsupported sequence type" ); } else { contour = cvPointSeqFromMat( CV_SEQ_KIND_CURVE, array, &contour_header, &block ); } if( cvSliceLength( slice, contour ) == contour->total ) { cv::AutoBuffer<double> abuf; cv::Mat points = cv::cvarrToMat(contour, false, false, 0, &abuf); return cv::contourArea( points, oriented !=0 ); } if( CV_SEQ_ELTYPE( contour ) != CV_32SC2 ) CV_Error( CV_StsUnsupportedFormat, "Only curves with integer coordinates are supported in case of contour slice" ); area = icvContourSecArea( contour, slice ); return oriented ? area : fabs(area); }
/* external contour area function */ CV_IMPL double cvContourArea( const void *array, CvSlice slice, int oriented ) { double area = 0; CvContour contour_header; CvSeq* contour = 0; CvSeqBlock block; if( CV_IS_SEQ( array )) { contour = (CvSeq*)array; if( !CV_IS_SEQ_POLYLINE( contour )) CV_Error( CV_StsBadArg, "Unsupported sequence type" ); } else { contour = cvPointSeqFromMat( CV_SEQ_KIND_CURVE, array, &contour_header, &block ); } if( cvSliceLength( slice, contour ) == contour->total ) { IPPI_CALL( icvContourArea( contour, &area )); } else { if( CV_SEQ_ELTYPE( contour ) != CV_32SC2 ) CV_Error( CV_StsUnsupportedFormat, "Only curves with integer coordinates are supported in case of contour slice" ); IPPI_CALL( icvContourSecArea( contour, slice, &area )); } return oriented ? area : fabs(area); }
CV_IMPL double cvContourPerimeter( CvSeq *contour, CvSlice slice ) { double perimeter = 0; int i, j = 0, count; const int N = 16; float buffer[N]; CvSeqReader reader; CV_FUNCNAME("cvCalcContourPerimeter"); __BEGIN__; if( !contour ) CV_ERROR_FROM_STATUS( CV_NULLPTR_ERR ); if( !CV_IS_SEQ_POLYLINE( contour )) CV_ERROR_FROM_STATUS( CV_BADFLAG_ERR ); if( contour->total > 1 ) { CvPoint pt1, pt2; cvStartReadSeq( contour, &reader, 0 ); cvSetSeqReaderPos( &reader, slice.startIndex ); count = icvSliceLength( slice, contour ); CV_ADJUST_EDGE_COUNT( count, contour ); /* scroll the reader by 1 point */ CV_READ_EDGE( pt1, pt2, reader ); for( i = 0; i < count; i++ ) { int dx, dy; int edge_length; CV_READ_EDGE( pt1, pt2, reader ); dx = pt2.x - pt1.x; dy = pt2.y - pt1.y; edge_length = dx * dx + dy * dy; buffer[j] = (float)edge_length; if( ++j == N || i == count - 1 ) { cvbSqrt( buffer, buffer, j ); for( ; j > 0; j-- ) perimeter += buffer[j-1]; } } } __CLEANUP__ __END__ return perimeter; }
/* calculates length of a curve (e.g. contour perimeter) */ CV_IMPL double cvArcLength( const void *array, CvSlice slice, int is_closed ) { double perimeter = 0; int i, j = 0, count; const int N = 16; float buf[N]; CvMat buffer = cvMat( 1, N, CV_32F, buf ); CvSeqReader reader; CvContour contour_header; CvSeq* contour = 0; CvSeqBlock block; if( CV_IS_SEQ( array )) { contour = (CvSeq*)array; if( !CV_IS_SEQ_POLYLINE( contour )) CV_Error( CV_StsBadArg, "Unsupported sequence type" ); if( is_closed < 0 ) is_closed = CV_IS_SEQ_CLOSED( contour ); } else { is_closed = is_closed > 0; contour = cvPointSeqFromMat( CV_SEQ_KIND_CURVE | (is_closed ? CV_SEQ_FLAG_CLOSED : 0), array, &contour_header, &block ); } if( contour->total > 1 ) { int is_float = CV_SEQ_ELTYPE( contour ) == CV_32FC2; cvStartReadSeq( contour, &reader, 0 ); cvSetSeqReaderPos( &reader, slice.start_index ); count = cvSliceLength( slice, contour ); count -= !is_closed && count == contour->total; // scroll the reader by 1 point reader.prev_elem = reader.ptr; CV_NEXT_SEQ_ELEM( sizeof(CvPoint), reader ); for( i = 0; i < count; i++ ) { float dx, dy; if( !is_float ) { CvPoint* pt = (CvPoint*)reader.ptr; CvPoint* prev_pt = (CvPoint*)reader.prev_elem; dx = (float)pt->x - (float)prev_pt->x; dy = (float)pt->y - (float)prev_pt->y; } else { CvPoint2D32f* pt = (CvPoint2D32f*)reader.ptr; CvPoint2D32f* prev_pt = (CvPoint2D32f*)reader.prev_elem; dx = pt->x - prev_pt->x; dy = pt->y - prev_pt->y; } reader.prev_elem = reader.ptr; CV_NEXT_SEQ_ELEM( contour->elem_size, reader ); // Bugfix by Axel at rubico.com 2010-03-22, affects closed slices only // wraparound not handled by CV_NEXT_SEQ_ELEM if( is_closed && i == count - 2 ) cvSetSeqReaderPos( &reader, slice.start_index ); buffer.data.fl[j] = dx * dx + dy * dy; if( ++j == N || i == count - 1 ) { buffer.cols = j; cvPow( &buffer, &buffer, 0.5 ); for( ; j > 0; j-- ) perimeter += buffer.data.fl[j-1]; } } } return perimeter; }