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 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F/////////////////////////////////////////////////////////////////////////////////////// 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Name: cvMeanShift 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Purpose: MeanShift algorithm 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Context: 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Parameters: 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// imgProb - 2D object probability distribution 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// windowIn - CvRect of CAMSHIFT Window intial size 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// numIters - If CAMSHIFT iterates this many times, stop 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// windowOut - Location, height and width of converged CAMSHIFT window 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// len - If != NULL, return equivalent len 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// width - If != NULL, return equivalent width 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// itersUsed - Returns number of iterations CAMSHIFT took to converge 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Returns: 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// The function itself returns the area found 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Notes: 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/ 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvMeanShift( const void* imgProb, CvRect windowIn, 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvTermCriteria criteria, CvConnectedComp* comp ) 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMoments moments; 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i = 0, eps; 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat stub, *mat = (CvMat*)imgProb; 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat cur_win; 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvRect cur_rect = windowIn; 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvMeanShift" ); 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( comp ) 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp->rect = windowIn; 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn moments.m00 = moments.m10 = moments.m01 = 0; 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( mat = cvGetMat( mat, &stub )); 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_CN( mat->type ) > 1 ) 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat ); 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( windowIn.height <= 0 || windowIn.width <= 0 ) 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Input window has non-positive sizes" ); 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( windowIn.x < 0 || windowIn.x + windowIn.width > mat->cols || 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.y < 0 || windowIn.y + windowIn.height > mat->rows ) 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsBadArg, "Initial window is not inside the image ROI" ); 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( criteria = cvCheckTermCriteria( criteria, 1., 100 )); 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn eps = cvRound( criteria.epsilon * criteria.epsilon ); 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < criteria.max_iter; i++ ) 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int dx, dy, nx, ny; 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double inv_m00; 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvGetSubRect( mat, &cur_win, cur_rect )); 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvMoments( &cur_win, &moments )); 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Calculating center of mass */ 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs(moments.m00) < DBL_EPSILON ) 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn inv_m00 = moments.inv_sqrt_m00*moments.inv_sqrt_m00; 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dx = cvRound( moments.m10 * inv_m00 - windowIn.width*0.5 ); 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dy = cvRound( moments.m01 * inv_m00 - windowIn.height*0.5 ); 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn nx = cur_rect.x + dx; 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ny = cur_rect.y + dy; 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( nx < 0 ) 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn nx = 0; 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( nx + cur_rect.width > mat->cols ) 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn nx = mat->cols - cur_rect.width; 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( ny < 0 ) 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ny = 0; 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( ny + cur_rect.height > mat->rows ) 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ny = mat->rows - cur_rect.height; 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dx = nx - cur_rect.x; 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dy = ny - cur_rect.y; 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cur_rect.x = nx; 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cur_rect.y = ny; 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Check for coverage centers mass & window */ 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( dx*dx + dy*dy < eps ) 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( comp ) 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp->rect = cur_rect; 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp->area = (float)moments.m00; 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return i; 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/*F/////////////////////////////////////////////////////////////////////////////////////// 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Name: cvCamShift 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Purpose: CAMSHIFT algorithm 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Context: 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Parameters: 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// imgProb - 2D object probability distribution 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// windowIn - CvRect of CAMSHIFT Window intial size 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// criteria - criteria of stop finding window 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// windowOut - Location, height and width of converged CAMSHIFT window 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// orientation - If != NULL, return distribution orientation 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// len - If != NULL, return equivalent len 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// width - If != NULL, return equivalent width 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// area - sum of all elements in result window 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// itersUsed - Returns number of iterations CAMSHIFT took to converge 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Returns: 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// The function itself returns the area found 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// Notes: 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn//F*/ 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL int 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvCamShift( const void* imgProb, CvRect windowIn, 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvTermCriteria criteria, 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvConnectedComp* _comp, 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvBox2D* box ) 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int TOLERANCE = 10; 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMoments moments; 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double m00 = 0, m10, m01, mu20, mu11, mu02, inv_m00; 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double a, b, c, xc, yc; 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double rotate_a, rotate_c; 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double theta = 0, square; 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double cs, sn; 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double length = 0, width = 0; 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int itersUsed = 0; 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvConnectedComp comp; 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat cur_win, stub, *mat = (CvMat*)imgProb; 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvCamShift" ); 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect = windowIn; 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( mat = cvGetMat( mat, &stub )); 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( itersUsed = cvMeanShift( mat, windowIn, criteria, &comp )); 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn = comp.rect; 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.x -= TOLERANCE; 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( windowIn.x < 0 ) 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.x = 0; 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.y -= TOLERANCE; 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( windowIn.y < 0 ) 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.y = 0; 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.width += 2 * TOLERANCE; 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( windowIn.x + windowIn.width > mat->width ) 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.width = mat->width - windowIn.x; 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.height += 2 * TOLERANCE; 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( windowIn.y + windowIn.height > mat->height ) 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn windowIn.height = mat->height - windowIn.y; 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvGetSubRect( mat, &cur_win, windowIn )); 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Calculating moments in new center mass */ 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvMoments( &cur_win, &moments )); 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m00 = moments.m00; 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m10 = moments.m10; 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m01 = moments.m01; 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mu11 = moments.mu11; 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mu20 = moments.mu20; 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mu02 = moments.mu02; 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( fabs(m00) < DBL_EPSILON ) 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn inv_m00 = 1. / m00; 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn xc = cvRound( m10 * inv_m00 + windowIn.x ); 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn yc = cvRound( m01 * inv_m00 + windowIn.y ); 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn a = mu20 * inv_m00; 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn b = mu11 * inv_m00; 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c = mu02 * inv_m00; 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Calculating width & height */ 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn square = sqrt( 4 * b * b + (a - c) * (a - c) ); 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Calculating orientation */ 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn theta = atan2( 2 * b, a - c + square ); 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Calculating width & length of figure */ 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cs = cos( theta ); 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sn = sin( theta ); 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rotate_a = cs * cs * mu20 + 2 * cs * sn * mu11 + sn * sn * mu02; 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn rotate_c = sn * sn * mu20 - 2 * cs * sn * mu11 + cs * cs * mu02; 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn length = sqrt( rotate_a * inv_m00 ) * 4; 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn width = sqrt( rotate_c * inv_m00 ) * 4; 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* In case, when tetta is 0 or 1.57... the Length & Width may be exchanged */ 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( length < width ) 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double t; 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SWAP( length, width, t ); 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_SWAP( cs, sn, t ); 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn theta = CV_PI*0.5 - theta; 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn /* Saving results */ 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _comp || box ) 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t0, t1; 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int _xc = cvRound( xc ); 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int _yc = cvRound( yc ); 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = cvRound( fabs( length * cs )); 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t1 = cvRound( fabs( width * sn )); 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = MAX( t0, t1 ) + 2; 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = MIN( t0, (mat->width - _xc) * 2 ); 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = cvRound( fabs( length * sn )); 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t1 = cvRound( fabs( width * cs )); 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = MAX( t0, t1 ) + 2; 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = MIN( t0, (mat->height - _yc) * 2 ); 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.x = MAX( 0, _xc - comp.rect.width / 2 ); 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y = MAX( 0, _yc - comp.rect.height / 2 ); 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.width = MIN( mat->width - comp.rect.x, comp.rect.width ); 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.height = MIN( mat->height - comp.rect.y, comp.rect.height ); 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.area = (float) m00; 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( _comp ) 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn *_comp = comp; 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( box ) 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.height = (float)length; 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->size.width = (float)width; 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->angle = (float)(theta*180./CV_PI); 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn box->center = cvPoint2D32f( comp.rect.x + comp.rect.width*0.5f, 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn comp.rect.y + comp.rect.height*0.5f); 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return itersUsed; 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* End of file. */ 301