16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*M/////////////////////////////////////////////////////////////////////////////////////// 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// By downloading, copying, installing or using the software you agree to this license. 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// If you do not agree to this license, do not download, install, 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// copy or use the software. 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Intel License Agreement 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// For Open Source Computer Vision Library 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Copyright (C) 2000, Intel Corporation, all rights reserved. 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Third party copyrights are property of their respective owners. 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Redistribution and use in source and binary forms, with or without modification, 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// are permitted provided that the following conditions are met: 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * Redistribution's of source code must retain the above copyright notice, 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this list of conditions and the following disclaimer. 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * Redistribution's in binary form must reproduce the above copyright notice, 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// this list of conditions and the following disclaimer in the documentation 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and/or other materials provided with the distribution. 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// * The name of Intel Corporation may not be used to endorse or promote products 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// derived from this software without specific prior written permission. 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// This software is provided by the copyright holders and contributors "as is" and 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// any express or implied warranties, including, but not limited to, the implied 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// warranties of merchantability and fitness for a particular purpose are disclaimed. 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// In no event shall the Intel Corporation or contributors be liable for any direct, 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// indirect, incidental, special, exemplary, or consequential damages 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// (including, but not limited to, procurement of substitute goods or services; 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// loss of use, data, or profits; or business interruption) however caused 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// and on any theory of liability, whether in contract, strict liability, 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// or tort (including negligence or otherwise) arising in any way out of 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// the use of this software, even if advised of the possibility of such damage. 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//M*/ 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h" 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* calculates length of a curve (e.g. contour perimeter) */ 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL double 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvArcLength( const void *array, CvSlice slice, int is_closed ) 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double perimeter = 0; 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvArcLength" ); 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j = 0, count; 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int N = 16; 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float buf[N]; 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat buffer = cvMat( 1, N, CV_32F, buf ); 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour contour_header; 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* contour = 0; 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock block; 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_IS_SEQ( array )) 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn contour = (CvSeq*)array; 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_SEQ_POLYLINE( contour )) 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Unsupported sequence type" ); 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( is_closed < 0 ) 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn is_closed = CV_IS_SEQ_CLOSED( contour ); 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn is_closed = is_closed > 0; 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( contour = cvPointSeqFromMat( 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SEQ_KIND_CURVE | (is_closed ? CV_SEQ_FLAG_CLOSED : 0), 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn array, &contour_header, &block )); 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( contour->total > 1 ) 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_float = CV_SEQ_ELTYPE( contour ) == CV_32FC2; 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( contour, &reader, 0 ); 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSetSeqReaderPos( &reader, slice.start_index ); 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn count = cvSliceLength( slice, contour ); 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn count -= !is_closed && count == contour->total; 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* scroll the reader by 1 point */ 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn reader.prev_elem = reader.ptr; 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof(CvPoint), reader ); 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < count; i++ ) 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float dx, dy; 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint* pt = (CvPoint*)reader.ptr; 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint* prev_pt = (CvPoint*)reader.prev_elem; 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dx = (float)pt->x - (float)prev_pt->x; 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dy = (float)pt->y - (float)prev_pt->y; 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f* pt = (CvPoint2D32f*)reader.ptr; 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f* prev_pt = (CvPoint2D32f*)reader.prev_elem; 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dx = pt->x - prev_pt->x; 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dy = pt->y - prev_pt->y; 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn reader.prev_elem = reader.ptr; 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( contour->elem_size, reader ); 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn buffer.data.fl[j] = dx * dx + dy * dy; 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ++j == N || i == count - 1 ) 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn buffer.cols = j; 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvPow( &buffer, &buffer, 0.5 ); 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; j > 0; j-- ) 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn perimeter += buffer.data.fl[j-1]; 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return perimeter; 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFindCircle( CvPoint2D32f pt0, CvPoint2D32f pt1, 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f pt2, CvPoint2D32f * center, float *radius ) 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double x1 = (pt0.x + pt1.x) * 0.5; 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dy1 = pt0.x - pt1.x; 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double x2 = (pt1.x + pt2.x) * 0.5; 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dy2 = pt1.x - pt2.x; 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double y1 = (pt0.y + pt1.y) * 0.5; 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dx1 = pt1.y - pt0.y; 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double y2 = (pt1.y + pt2.y) * 0.5; 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dx2 = pt2.y - pt1.y; 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double t = 0; 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvStatus result = CV_OK; 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvIntersectLines( x1, dx1, y1, dy1, x2, dx2, y2, dy2, &t ) >= 0 ) 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn center->x = (float) (x2 + dx2 * t); 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn center->y = (float) (y2 + dy2 * t); 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *radius = (float) icvDistanceL2_32f( *center, pt0 ); 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn center->x = center->y = 0.f; 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = 0; 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = CV_NOTDEFINED_ERR; 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_INLINE double icvIsPtInCircle( CvPoint2D32f pt, CvPoint2D32f center, float radius ) 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dx = pt.x - center.x; 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dy = pt.y - center.y; 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return (double)radius*radius - dx*dx - dy*dy; 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic int 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFindEnslosingCicle4pts_32f( CvPoint2D32f * pts, CvPoint2D32f * _center, float *_radius ) 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int shuffles[4][4] = { {0, 1, 2, 3}, {0, 1, 3, 2}, {2, 3, 0, 1}, {2, 3, 1, 0} }; 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idxs[4] = { 0, 1, 2, 3 }; 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, k = 1, mi = 0; 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float max_dist = 0; 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f center; 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f min_center; 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float radius, min_radius = FLT_MAX; 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f res_pts[4]; 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn center = min_center = pts[0]; 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = 1.f; 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 4; i++ ) 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = i + 1; j < 4; j++ ) 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float dist = icvDistanceL2_32f( pts[i], pts[j] ); 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_dist < dist ) 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn max_dist = dist; 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idxs[0] = i; 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idxs[1] = j; 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( max_dist == 0 ) 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn goto function_exit; 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn k = 2; 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 4; i++ ) 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < k; j++ ) 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i == idxs[j] ) 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( j == k ) 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idxs[k++] = i; 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn center = cvPoint2D32f( (pts[idxs[0]].x + pts[idxs[1]].x)*0.5f, 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (pts[idxs[0]].y + pts[idxs[1]].y)*0.5f ); 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = (float)(icvDistanceL2_32f( pts[idxs[0]], center )*1.03); 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( radius < 1.f ) 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = 1.f; 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvIsPtInCircle( pts[idxs[2]], center, radius ) >= 0 && 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvIsPtInCircle( pts[idxs[3]], center, radius ) >= 0 ) 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn k = 2; //rand()%2+2; 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mi = -1; 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 4; i++ ) 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvFindCircle( pts[shuffles[i][0]], pts[shuffles[i][1]], 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[shuffles[i][2]], ¢er, &radius ) >= 0 ) 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius *= 1.03f; 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( radius < 2.f ) 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = 2.f; 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( icvIsPtInCircle( pts[shuffles[i][3]], center, radius ) >= 0 && 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_radius > radius ) 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_radius = radius; 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_center = center; 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mi = i; 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( mi >= 0 ); 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( mi < 0 ) 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mi = 0; 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn k = 3; 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn center = min_center; 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = min_radius; 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 4; i++ ) 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idxs[i] = shuffles[mi][i]; 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn function_exit: 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *_center = center; 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *_radius = radius; 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* reorder output points */ 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 4; i++ ) 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn res_pts[i] = pts[idxs[i]]; 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 4; i++ ) 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[i] = res_pts[i]; 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( icvIsPtInCircle( pts[i], center, radius ) >= 0 ); 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return k; 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvMinEnclosingCircle( const void* array, CvPoint2D32f * _center, float *_radius ) 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int max_iters = 100; 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const float eps = FLT_EPSILON*2; 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f center = { 0, 0 }; 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float radius = 0; 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int result = 0; 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _center ) 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _center->x = _center->y = 0.f; 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _radius ) 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *_radius = 0; 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvMinEnclosingCircle" ); 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, k, count; 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f pts[8]; 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour contour_header; 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock block; 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* sequence = 0; 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_float; 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !_center || !_radius ) 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsNullPtr, "Null center or radius pointers" ); 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_IS_SEQ(array) ) 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sequence = (CvSeq*)array; 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_SEQ_POINT_SET( sequence )) 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "The passed sequence is not a valid contour" ); 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( sequence = cvPointSeqFromMat( 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SEQ_KIND_GENERIC, array, &contour_header, &block )); 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( sequence->total <= 0 ) 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR_FROM_STATUS( CV_BADSIZE_ERR ); 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvStartReadSeq( sequence, &reader, 0 )); 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn count = sequence->total; 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn is_float = CV_SEQ_ELTYPE(sequence) == CV_32FC2; 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint *pt_left, *pt_right, *pt_top, *pt_bottom; 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt; 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_left = pt_right = pt_top = pt_bottom = (CvPoint *)(reader.ptr); 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < count; i++ ) 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint* pt_ptr = (CvPoint*)reader.ptr; 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.x < pt_left->x ) 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_left = pt_ptr; 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.x > pt_right->x ) 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_right = pt_ptr; 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.y < pt_top->y ) 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_top = pt_ptr; 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.y > pt_bottom->y ) 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_bottom = pt_ptr; 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[0] = cvPointTo32f( *pt_left ); 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[1] = cvPointTo32f( *pt_right ); 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[2] = cvPointTo32f( *pt_top ); 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[3] = cvPointTo32f( *pt_bottom ); 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f *pt_left, *pt_right, *pt_top, *pt_bottom; 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f pt; 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_left = pt_right = pt_top = pt_bottom = (CvPoint2D32f *) (reader.ptr); 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < count; i++ ) 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f* pt_ptr = (CvPoint2D32f*)reader.ptr; 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.x < pt_left->x ) 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_left = pt_ptr; 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.x > pt_right->x ) 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_right = pt_ptr; 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.y < pt_top->y ) 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_top = pt_ptr; 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( pt.y > pt_bottom->y ) 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt_bottom = pt_ptr; 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[0] = *pt_left; 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[1] = *pt_right; 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[2] = *pt_top; 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[3] = *pt_bottom; 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( k = 0; k < max_iters; k++ ) 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double min_delta = 0, delta; 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f ptfl; 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvFindEnslosingCicle4pts_32f( pts, ¢er, &radius ); 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( sequence, &reader, 0 ); 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < count; i++ ) 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptfl.x = (float)((CvPoint*)reader.ptr)->x; 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptfl.y = (float)((CvPoint*)reader.ptr)->y; 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptfl = *(CvPoint2D32f*)reader.ptr; 3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sequence->elem_size, reader ); 4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn delta = icvIsPtInCircle( ptfl, center, radius ); 4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( delta < min_delta ) 4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn min_delta = delta; 4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pts[3] = ptfl; 4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = min_delta >= 0; 4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( result ) 4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !result ) 4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( sequence, &reader, 0 ); 4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = 0.f; 4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < count; i++ ) 4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f ptfl; 4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float t, dx, dy; 4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptfl.x = (float)((CvPoint*)reader.ptr)->x; 4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptfl.y = (float)((CvPoint*)reader.ptr)->y; 4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptfl = *(CvPoint2D32f*)reader.ptr; 4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sequence->elem_size, reader ); 4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dx = center.x - ptfl.x; 4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dy = center.y - ptfl.y; 4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = dx*dx + dy*dy; 4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = MAX(radius,t); 4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn radius = (float)(sqrt(radius)*(1 + eps)); 4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn result = 1; 4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *_center = center; 4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *_radius = radius; 4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return result; 4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* area of a whole sequence */ 4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus 4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvContourArea( const CvSeq* contour, double *area ) 4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( contour->total ) 4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; 4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int lpt = contour->total; 4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double a00 = 0, xi_1, yi_1; 4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_float = CV_SEQ_ELTYPE(contour) == CV_32FC2; 4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( contour, &reader, 0 ); 4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi_1 = ((CvPoint*)(reader.ptr))->x; 4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi_1 = ((CvPoint*)(reader.ptr))->y; 4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi_1 = ((CvPoint2D32f*)(reader.ptr))->x; 4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi_1 = ((CvPoint2D32f*)(reader.ptr))->y; 4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( contour->elem_size, reader ); 4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while( lpt-- > 0 ) 4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double dxy, xi, yi; 4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi = ((CvPoint*)(reader.ptr))->x; 4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi = ((CvPoint*)(reader.ptr))->y; 4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi = ((CvPoint2D32f*)(reader.ptr))->x; 4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi = ((CvPoint2D32f*)(reader.ptr))->y; 4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( contour->elem_size, reader ); 4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = xi_1 * yi - xi * yi_1; 4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 += dxy; 4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi_1 = xi; 4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi_1 = yi; 4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *area = a00 * 0.5; 5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *area = 0; 5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_OK; 5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\ 5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn copy data from one buffer to other buffer 5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/ 5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus 5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvMemCopy( double **buf1, double **buf2, double **buf3, int *b_max ) 5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bb; 5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( (*buf1 == NULL && *buf2 == NULL) || *buf3 == NULL ) 5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_NULLPTR_ERR; 5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bb = *b_max; 5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *buf2 == NULL ) 5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *b_max = 2 * (*b_max); 5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *buf2 = (double *)cvAlloc( (*b_max) * sizeof( double )); 5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *buf2 == NULL ) 5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_OUTOFMEM_ERR; 5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memcpy( *buf2, *buf3, bb * sizeof( double )); 5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *buf3 = *buf2; 5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( buf1 ); 5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *buf1 = NULL; 5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *b_max = 2 * (*b_max); 5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *buf1 = (double *) cvAlloc( (*b_max) * sizeof( double )); 5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *buf1 == NULL ) 5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_OUTOFMEM_ERR; 5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memcpy( *buf1, *buf3, bb * sizeof( double )); 5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *buf3 = *buf1; 5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( buf2 ); 5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *buf2 = NULL; 5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_OK; 5546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* area of a contour sector */ 5586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvStatus icvContourSecArea( CvSeq * contour, CvSlice slice, double *area ) 5596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 5606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt; /* pointer to points */ 5616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt_s, pt_e; /* first and last points */ 5626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; /* points reader of contour */ 5636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int p_max = 2, p_ind; 5656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int lpt, flag, i; 5666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double a00; /* unnormalized moments m00 */ 5676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double xi, yi, xi_1, yi_1, x0, y0, dxy, sk, sk1, t; 5686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double x_s, y_s, nx, ny, dx, dy, du, dv; 5696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double eps = 1.e-5; 5706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double *p_are1, *p_are2, *p_are; 5716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( contour != NULL ); 5736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( contour == NULL ) 5756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_NULLPTR_ERR; 5766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_SEQ_POLYGON( contour )) 5786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_BADFLAG_ERR; 5796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn lpt = cvSliceLength( slice, contour ); 5816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /*if( n2 >= n1 ) 5826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn lpt = n2 - n1 + 1; 5836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 5846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn lpt = contour->total - n1 + n2 + 1;*/ 5856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( contour->total && lpt > 2 ) 5876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 = x0 = y0 = xi_1 = yi_1 = 0; 5896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sk1 = 0; 5906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flag = 0; 5916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = 0; 5926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_are1 = (double *) cvAlloc( p_max * sizeof( double )); 5936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( p_are1 == NULL ) 5956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_OUTOFMEM_ERR; 5966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_are = p_are1; 5986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_are2 = NULL; 5996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( contour, &reader, 0 ); 6016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSetSeqReaderPos( &reader, slice.start_index ); 6026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt_s, reader ); 6036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_ind = 0; 6046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSetSeqReaderPos( &reader, slice.end_index ); 6056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt_e, reader ); 6066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* normal coefficients */ 6086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn nx = pt_s.y - pt_e.y; 6096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ny = pt_e.x - pt_s.x; 6106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSetSeqReaderPos( &reader, slice.start_index ); 6116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn while( lpt-- > 0 ) 6136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 6156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( flag == 0 ) 6176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi_1 = (double) pt.x; 6196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi_1 = (double) pt.y; 6206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = xi_1; 6216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y0 = yi_1; 6226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sk1 = 0; 6236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn flag = 1; 6246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi = (double) pt.x; 6286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi = (double) pt.y; 6296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/**************** edges intersection examination **************************/ 6316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sk = nx * (xi - pt_s.x) + ny * (yi - pt_s.y); 6326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( (fabs( sk ) < eps && lpt > 0) || sk * sk1 < -eps ) 6336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs( sk ) < eps ) 6356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = xi_1 * yi - xi * yi_1; 6376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 = a00 + dxy; 6386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = xi * y0 - x0 * yi; 6396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 = a00 + dxy; 6406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( p_ind >= p_max ) 6426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvMemCopy( &p_are1, &p_are2, &p_are, &p_max ); 6436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_are[p_ind] = a00 / 2.; 6456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_ind++; 6466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 = 0; 6476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sk1 = 0; 6486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = xi; 6496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y0 = yi; 6506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = 0; 6516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* define intersection point */ 6556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dv = yi - yi_1; 6566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn du = xi - xi_1; 6576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dx = ny; 6586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dy = -nx; 6596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs( du ) > eps ) 6606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = ((yi_1 - pt_s.y) * du + dv * (pt_s.x - xi_1)) / 6616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (du * dy - dx * dv); 6626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = (xi_1 - pt_s.x) / dx; 6646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( t > eps && t < 1 - eps ) 6656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 6666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x_s = pt_s.x + t * dx; 6676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y_s = pt_s.y + t * dy; 6686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = xi_1 * y_s - x_s * yi_1; 6696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 += dxy; 6706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = x_s * y0 - x0 * y_s; 6716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 += dxy; 6726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( p_ind >= p_max ) 6736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvMemCopy( &p_are1, &p_are2, &p_are, &p_max ); 6746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_are[p_ind] = a00 / 2.; 6766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_ind++; 6776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 = 0; 6796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sk1 = 0; 6806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = x_s; 6816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y0 = y_s; 6826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = x_s * yi - xi * y_s; 6836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 6876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = xi_1 * yi - xi * yi_1; 6886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 += dxy; 6906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi_1 = xi; 6916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi_1 = yi; 6926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sk1 = sk; 6936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 6966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 6976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xi = x0; 6986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yi = y0; 6996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dxy = xi_1 * yi - xi * yi_1; 7006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a00 += dxy; 7026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( p_ind >= p_max ) 7046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvMemCopy( &p_are1, &p_are2, &p_are, &p_max ); 7056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_are[p_ind] = a00 / 2.; 7076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p_ind++; 7086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* common area calculation */ 7106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *area = 0; 7116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < p_ind; i++ ) 7126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (*area) += fabs( p_are[i] ); 7136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( p_are1 != NULL ) 7156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &p_are1 ); 7166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( p_are2 != NULL ) 7176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &p_are2 ); 7186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_OK; 7206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return CV_BADSIZE_ERR; 7236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 7246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* external contour area function */ 7276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL double 7286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvContourArea( const void *array, CvSlice slice ) 7296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 7306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double area = 0; 7316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvContourArea" ); 7336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 7356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour contour_header; 7376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* contour = 0; 7386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock block; 7396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_IS_SEQ( array )) 7416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn contour = (CvSeq*)array; 7436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_SEQ_POLYLINE( contour )) 7446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Unsupported sequence type" ); 7456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( contour = cvPointSeqFromMat( 7496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SEQ_KIND_CURVE, array, &contour_header, &block )); 7506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( cvSliceLength( slice, contour ) == contour->total ) 7536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn IPPI_CALL( icvContourArea( contour, &area )); 7556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 7576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 7586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_SEQ_ELTYPE( contour ) != CV_32SC2 ) 7596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 7606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Only curves with integer coordinates are supported in case of contour slice" ); 7616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn IPPI_CALL( icvContourSecArea( contour, slice, &area )); 7626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 7636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 7656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return area; 7676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 7686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* for now this function works bad with singular cases 7716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn You can see in the code, that when some troubles with 7726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn matrices or some variables occur - 7736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box filled with zero values is returned. 7746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn However in general function works fine. 7756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn*/ 7766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic void 7776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvFitEllipse_F( CvSeq* points, CvBox2D* box ) 7786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 7796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat* D = 0; 7806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvFitEllipse_F" ); 7826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 7846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double S[36], C[36], T[36]; 7866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j; 7886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double eigenvalues[6], eigenvectors[36]; 7896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double a, b, c, d, e, f; 7906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double x0, y0, idet, scale, offx = 0, offy = 0; 7916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n = points->total; 7936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; 7946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_float = CV_SEQ_ELTYPE(points) == CV_32FC2; 7956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat _S = cvMat(6,6,CV_64F,S), _C = cvMat(6,6,CV_64F,C), _T = cvMat(6,6,CV_64F,T); 7976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat _EIGVECS = cvMat(6,6,CV_64F,eigenvectors), _EIGVALS = cvMat(6,1,CV_64F,eigenvalues); 7986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 7996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* create matrix D of input points */ 8006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( D = cvCreateMat( n, 6, CV_64F )); 8016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( points, &reader ); 8036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* shift all points to zero */ 8056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; i++ ) 8066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 8086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offx += ((CvPoint*)reader.ptr)->x; 8106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offy += ((CvPoint*)reader.ptr)->y; 8116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 8136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offx += ((CvPoint2D32f*)reader.ptr)->x; 8156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offy += ((CvPoint2D32f*)reader.ptr)->y; 8166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( points->elem_size, reader ); 8186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offx /= n; 8216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offy /= n; 8226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // fill matrix rows as (x*x, x*y, y*y, x, y, 1 ) 8246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; i++ ) 8256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double x, y; 8276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double* Dptr = D->data.db + i*6; 8286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 8306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x = ((CvPoint*)reader.ptr)->x - offx; 8326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y = ((CvPoint*)reader.ptr)->y - offy; 8336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 8356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x = ((CvPoint2D32f*)reader.ptr)->x - offx; 8376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y = ((CvPoint2D32f*)reader.ptr)->y - offy; 8386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( points->elem_size, reader ); 8406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Dptr[0] = x * x; 8426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Dptr[1] = x * y; 8436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Dptr[2] = y * y; 8446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Dptr[3] = x; 8456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Dptr[4] = y; 8466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Dptr[5] = 1.; 8476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // S = D^t*D 8506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMulTransposed( D, &_S, 1 ); 8516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSVD( &_S, &_EIGVALS, &_EIGVECS, 0, CV_SVD_MODIFY_A + CV_SVD_U_T ); 8526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 6; i++ ) 8546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double a = eigenvalues[i]; 8566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a = a < DBL_EPSILON ? 0 : 1./sqrt(sqrt(a)); 8576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < 6; j++ ) 8586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn eigenvectors[i*6 + j] *= a; 8596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // C = Q^-1 = transp(INVEIGV) * INVEIGV 8626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMulTransposed( &_EIGVECS, &_C, 1 ); 8636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero( &_S ); 8656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn S[2] = 2.; 8666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn S[7] = -1.; 8676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn S[12] = 2.; 8686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // S = Q^-1*S*Q^-1 8706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMatMul( &_C, &_S, &_T ); 8716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMatMul( &_T, &_C, &_S ); 8726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // and find its eigenvalues and vectors too 8746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //cvSVD( &_S, &_EIGVALS, &_EIGVECS, 0, CV_SVD_MODIFY_A + CV_SVD_U_T ); 8756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvEigenVV( &_S, &_EIGVECS, &_EIGVALS, 0 ); 8766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 3; i++ ) 8786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( eigenvalues[i] > 0 ) 8796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 8806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i >= 3 /*eigenvalues[0] < DBL_EPSILON*/ ) 8826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 8836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->center.x = box->center.y = 8846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.width = box->size.height = 8856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->angle = 0.f; 8866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 8876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 8886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // now find truthful eigenvector 8906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _EIGVECS = cvMat( 6, 1, CV_64F, eigenvectors + 6*i ); 8916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _T = cvMat( 6, 1, CV_64F, T ); 8926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Q^-1*eigenvecs[0] 8936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvMatMul( &_C, &_EIGVECS, &_T ); 8946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // extract vector components 8966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a = T[0]; b = T[1]; c = T[2]; d = T[3]; e = T[4]; f = T[5]; 8976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ///////////////// extract ellipse axes from above values //////////////// 8996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* 9016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1) find center of ellipse 9026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn it satisfy equation 9036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn | a b/2 | * | x0 | + | d/2 | = |0 | 9046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn | b/2 c | | y0 | | e/2 | |0 | 9056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 9076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idet = a * c - b * b * 0.25; 9086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idet = idet > DBL_EPSILON ? 1./idet : 0; 9096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // we must normalize (a b c d e f ) to fit (4ac-b^2=1) 9116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scale = sqrt( 0.25 * idet ); 9126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( scale < DBL_EPSILON ) 9146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->center.x = (float)offx; 9166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->center.y = (float)offy; 9176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.width = box->size.height = box->angle = 0.f; 9186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 9196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a *= scale; 9226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b *= scale; 9236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c *= scale; 9246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn d *= scale; 9256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn e *= scale; 9266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn f *= scale; 9276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = (-d * c + e * b * 0.5) * 2.; 9296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y0 = (-a * e + d * b * 0.5) * 2.; 9306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // recover center 9326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->center.x = (float)(x0 + offx); 9336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->center.y = (float)(y0 + offy); 9346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // offset ellipse to (x0,y0) 9366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // new f == F(x0,y0) 9376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn f += a * x0 * x0 + b * x0 * y0 + c * y0 * y0 + d * x0 + e * y0; 9386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs(f) < DBL_EPSILON ) 9406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.width = box->size.height = box->angle = 0.f; 9426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 9436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn scale = -1. / f; 9466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // normalize to f = 1 9476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a *= scale; 9486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b *= scale; 9496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c *= scale; 9506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // extract axis of ellipse 9526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // one more eigenvalue operation 9536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn S[0] = a; 9546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn S[1] = S[2] = b * 0.5; 9556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn S[3] = c; 9566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _S = cvMat( 2, 2, CV_64F, S ); 9586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _EIGVECS = cvMat( 2, 2, CV_64F, eigenvectors ); 9596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn _EIGVALS = cvMat( 1, 2, CV_64F, eigenvalues ); 9606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSVD( &_S, &_EIGVALS, &_EIGVECS, 0, CV_SVD_MODIFY_A + CV_SVD_U_T ); 9616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // exteract axis length from eigenvectors 9636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.width = (float)(2./sqrt(eigenvalues[0])); 9646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.height = (float)(2./sqrt(eigenvalues[1])); 9656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // calc angle 9676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->angle = (float)(180 - atan2(eigenvectors[2], eigenvectors[3])*180/CV_PI); 9686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 9706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &D ); 9726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 9736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvBox2D 9766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvFitEllipse2( const CvArr* array ) 9776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 9786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBox2D box; 9796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double* Ad = 0, *bd = 0; 9806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvFitEllipse2" ); 9826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( &box, 0, sizeof(box)); 9846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 9866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour contour_header; 9886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* ptseq = 0; 9896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock block; 9906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int n; 9916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 9926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_IS_SEQ( array )) 9936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 9946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptseq = (CvSeq*)array; 9956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_SEQ_POINT_SET( ptseq )) 9966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Unsupported sequence type" ); 9976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 9986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 9996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ptseq = cvPointSeqFromMat( 10016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SEQ_KIND_GENERIC, array, &contour_header, &block )); 10026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n = ptseq->total; 10056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( n < 5 ) 10066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadSize, "Number of points should be >= 6" ); 10076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#if 1 10086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icvFitEllipse_F( ptseq, &box ); 10096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#else 10106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* 10116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * New fitellipse algorithm, contributed by Dr. Daniel Weiss 10126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 10136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double gfp[5], rp[5], t; 10156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat A, b, x; 10166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const double min_eps = 1e-6; 10176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, is_float; 10186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; 10196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( Ad = (double*)cvAlloc( n*5*sizeof(Ad[0]) )); 10216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( bd = (double*)cvAlloc( n*sizeof(bd[0]) )); 10226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // first fit for parameters A - E 10246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn A = cvMat( n, 5, CV_64F, Ad ); 10256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b = cvMat( n, 1, CV_64F, bd ); 10266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x = cvMat( 5, 1, CV_64F, gfp ); 10276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( ptseq, &reader ); 10296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn is_float = CV_SEQ_ELTYPE(ptseq) == CV_32FC2; 10306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; i++ ) 10326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f p; 10346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( is_float ) 10356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p = *(CvPoint2D32f*)(reader.ptr); 10366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 10376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p.x = (float)((int*)reader.ptr)[0]; 10396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p.y = (float)((int*)reader.ptr)[1]; 10406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof(p), reader ); 10426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bd[i] = 10000.0; // 1.0? 10446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i*5] = -(double)p.x * p.x; // A - C signs inverted as proposed by APP 10456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i*5 + 1] = -(double)p.y * p.y; 10466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i*5 + 2] = -(double)p.x * p.y; 10476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i*5 + 3] = p.x; 10486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i*5 + 4] = p.y; 10496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSolve( &A, &b, &x, CV_SVD ); 10526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // now use general-form parameters A - E to find the ellipse center: 10546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // differentiate general form wrt x/y to get two equations for cx and cy 10556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn A = cvMat( 2, 2, CV_64F, Ad ); 10566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b = cvMat( 2, 1, CV_64F, bd ); 10576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x = cvMat( 2, 1, CV_64F, rp ); 10586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[0] = 2 * gfp[0]; 10596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[1] = Ad[2] = gfp[2]; 10606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[3] = 2 * gfp[1]; 10616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bd[0] = gfp[3]; 10626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bd[1] = gfp[4]; 10636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSolve( &A, &b, &x, CV_SVD ); 10646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // re-fit for parameters A - C with those center coordinates 10666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn A = cvMat( n, 3, CV_64F, Ad ); 10676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b = cvMat( n, 1, CV_64F, bd ); 10686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x = cvMat( 3, 1, CV_64F, gfp ); 10696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < n; i++ ) 10706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint2D32f p; 10726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( is_float ) 10736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p = *(CvPoint2D32f*)(reader.ptr); 10746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 10756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 10766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p.x = (float)((int*)reader.ptr)[0]; 10776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn p.y = (float)((int*)reader.ptr)[1]; 10786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_NEXT_SEQ_ELEM( sizeof(p), reader ); 10806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bd[i] = 1.0; 10816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i * 3] = (p.x - rp[0]) * (p.x - rp[0]); 10826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i * 3 + 1] = (p.y - rp[1]) * (p.y - rp[1]); 10836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Ad[i * 3 + 2] = (p.x - rp[0]) * (p.y - rp[1]); 10846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 10856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvSolve(&A, &b, &x, CV_SVD); 10866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 10876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // store angle and radii 10886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rp[4] = -0.5 * atan2(gfp[2], gfp[1] - gfp[0]); // convert from APP angle usage 10896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = sin(-2.0 * rp[4]); 10906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs(t) > fabs(gfp[2])*min_eps ) 10916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = gfp[2]/t; 10926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 10936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = gfp[1] - gfp[0]; 10946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rp[2] = fabs(gfp[0] + gfp[1] - t); 10956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( rp[2] > min_eps ) 10966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rp[2] = sqrt(2.0 / rp[2]); 10976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rp[3] = fabs(gfp[0] + gfp[1] + t); 10986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( rp[3] > min_eps ) 10996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rp[3] = sqrt(2.0 / rp[3]); 11006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.center.x = (float)rp[0]; 11026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.center.y = (float)rp[1]; 11036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.size.width = (float)(rp[2]*2); 11046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.size.height = (float)(rp[3]*2); 11056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( box.size.width > box.size.height ) 11066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float tmp; 11086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SWAP( box.size.width, box.size.height, tmp ); 11096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.angle = (float)(90 + rp[4]*180/CV_PI); 11106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( box.angle < -180 ) 11126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.angle += 360; 11136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( box.angle > 360 ) 11146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box.angle -= 360; 11156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif 11176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 11186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &Ad ); 11206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFree( &bd ); 11216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return box; 11236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 11246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* Calculates bounding rectagnle of a point set or retrieves already calculated */ 11276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL CvRect 11286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvBoundingRect( CvArr* array, int update ) 11296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 11306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqReader reader; 11316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect rect = { 0, 0, 0, 0 }; 11326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvContour contour_header; 11336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeq* ptseq = 0; 11346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSeqBlock block; 11356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvBoundingRect" ); 11376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 11396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat stub, *mat = 0; 11416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int xmin = 0, ymin = 0, xmax = -1, ymax = -1, i, j, k; 11426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int calculate = update; 11436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_IS_SEQ( array )) 11456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptseq = (CvSeq*)array; 11476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_IS_SEQ_POINT_SET( ptseq )) 11486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Unsupported sequence type" ); 11496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ptseq->header_size < (int)sizeof(CvContour)) 11516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /*if( update == 1 ) 11536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "The header is too small to fit the rectangle, " 11546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "so it could not be updated" );*/ 11556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn update = 0; 11566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn calculate = 1; 11576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 11606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( mat = cvGetMat( array, &stub )); 11626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(mat->type) == CV_32SC2 || 11636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_MAT_TYPE(mat->type) == CV_32FC2 ) 11646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( ptseq = cvPointSeqFromMat( 11666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SEQ_KIND_GENERIC, mat, &contour_header, &block )); 11676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mat = 0; 11686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( CV_MAT_TYPE(mat->type) != CV_8UC1 && 11706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_MAT_TYPE(mat->type) != CV_8SC1 ) 11716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 11726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "The image/matrix format is not supported by the function" ); 11736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn update = 0; 11746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn calculate = 1; 11756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !calculate ) 11786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect = ((CvContour*)ptseq)->rect; 11806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 11816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 11826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( mat ) 11846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize size = cvGetMatSize(mat); 11866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = size.width; 11876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymin = -1; 11886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 11896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < size.height; i++ ) 11906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* _ptr = mat->data.ptr + i*mat->step; 11926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* ptr = (uchar*)cvAlignPtr(_ptr, 4); 11936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int have_nz = 0, k_min, offset = (int)(ptr - _ptr); 11946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn j = 0; 11956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn offset = MIN(offset, size.width); 11966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; j < offset; j++ ) 11976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _ptr[j] ) 11986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 11996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn have_nz = 1; 12006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( j < offset ) 12036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( j < xmin ) 12056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = j; 12066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( j > xmax ) 12076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax = j; 12086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( offset < size.width ) 12106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin -= offset; 12126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax -= offset; 12136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size.width -= offset; 12146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn j = 0; 12156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; j <= xmin - 4; j += 4 ) 12166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *((int*)(ptr+j)) ) 12176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; j < xmin; j++ ) 12196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ptr[j] ) 12206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = j; 12226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( j > xmax ) 12236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax = j; 12246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn have_nz = 1; 12256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn k_min = MAX(j-1, xmax); 12286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn k = size.width - 1; 12296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; k > k_min && (k&3) != 3; k-- ) 12306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ptr[k] ) 12316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( k > k_min && (k&3) == 3 ) 12336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; k > k_min+3; k -= 4 ) 12356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *((int*)(ptr+k-3)) ) 12366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; k > k_min; k-- ) 12396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ptr[k] ) 12406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax = k; 12426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn have_nz = 1; 12436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !have_nz ) 12466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn j &= ~3; 12486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; j <= k - 3; j += 4 ) 12496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( *((int*)(ptr+j)) ) 12506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; j <= k; j++ ) 12526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ptr[j] ) 12536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn have_nz = 1; 12556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 12566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin += offset; 12596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax += offset; 12606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size.width += offset; 12616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( have_nz ) 12636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ymin < 0 ) 12656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymin = i; 12666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymax = i; 12676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( xmin >= size.width ) 12716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = ymin = 0; 12726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 12736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( ptseq->total ) 12746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int is_float = CV_SEQ_ELTYPE(ptseq) == CV_32FC2; 12766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvStartReadSeq( ptseq, &reader, 0 ); 12776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !is_float ) 12796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt; 12816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* init values */ 12826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 12836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = xmax = pt.x; 12846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymin = ymax = pt.y; 12856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < ptseq->total; i++ ) 12876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 12886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 12896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( xmin > pt.x ) 12916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = pt.x; 12926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( xmax < pt.x ) 12946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax = pt.x; 12956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ymin > pt.y ) 12976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymin = pt.y; 12986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 12996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ymax < pt.y ) 13006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymax = pt.y; 13016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else 13046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvPoint pt; 13066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Cv32suf v; 13076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* init values */ 13086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 13096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = xmax = CV_TOGGLE_FLT(pt.x); 13106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymin = ymax = CV_TOGGLE_FLT(pt.y); 13116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < ptseq->total; i++ ) 13136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 13146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_READ_SEQ_ELEM( pt, reader ); 13156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt.x = CV_TOGGLE_FLT(pt.x); 13166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn pt.y = CV_TOGGLE_FLT(pt.y); 13176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( xmin > pt.x ) 13196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmin = pt.x; 13206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( xmax < pt.x ) 13226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xmax = pt.x; 13236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ymin > pt.y ) 13256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymin = pt.y; 13266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ymax < pt.y ) 13286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ymax = pt.y; 13296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn v.i = CV_TOGGLE_FLT(xmin); xmin = cvFloor(v.f); 13326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn v.i = CV_TOGGLE_FLT(ymin); ymin = cvFloor(v.f); 13336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* because right and bottom sides of 13346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn the bounding rectangle are not inclusive 13356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (note +1 in width and height calculation below), 13366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvFloor is used here instead of cvCeil */ 13376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn v.i = CV_TOGGLE_FLT(xmax); xmax = cvFloor(v.f); 13386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn v.i = CV_TOGGLE_FLT(ymax); ymax = cvFloor(v.f); 13396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 13416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect.x = xmin; 13436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect.y = ymin; 13446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect.width = xmax - xmin + 1; 13456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rect.height = ymax - ymin + 1; 13466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( update ) 13486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ((CvContour*)ptseq)->rect = rect; 13496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 13516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return rect; 13536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 13546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 13566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */ 1357