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 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_cv.h" 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\ 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn* Watershed * 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/ 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvWSNode 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn struct CvWSNode* next; 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int mask_ofs; 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int img_ofs; 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvWSNode; 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renntypedef struct CvWSQueue 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvWSNode* first; 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvWSNode* last; 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCvWSQueue; 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic CvWSNode* 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennicvAllocWSNodes( CvMemStorage* storage ) 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvWSNode* n = 0; 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "icvAllocWSNodes" ); 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, count = (storage->block_size - sizeof(CvMemBlock))/sizeof(*n) - 1; 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( n = (CvWSNode*)cvMemStorageAlloc( storage, count*sizeof(*n) )); 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < count-1; i++ ) 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n[i].next = n + i + 1; 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn n[count-1].next = 0; 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return n; 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvWatershed( const CvArr* srcarr, CvArr* dstarr ) 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int IN_QUEUE = -2; 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int WSHED = -1; 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int NQ = 256; 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMemStorage* storage = 0; 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvWatershed" ); 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sstub, *src; 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat dstub, *dst; 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize size; 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvWSNode* free_node = 0, *node; 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvWSQueue q[NQ]; 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int active_queue; 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j; 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int db, dg, dr; 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* mask; 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* img; 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int mstep, istep; 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int subs_tab[513]; 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // MAX(a,b) = b + MAX(a-b,0) 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #define ws_max(a,b) ((b) + subs_tab[(a)-(b)+NQ]) 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // MIN(a,b) = a - MAX(a-b,0) 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #define ws_min(a,b) ((a) - subs_tab[(a)-(b)+NQ]) 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #define ws_push(idx,mofs,iofs) \ 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { \ 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !free_node ) \ 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( free_node = icvAllocWSNodes( storage ));\ 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node = free_node; \ 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free_node = free_node->next;\ 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->next = 0; \ 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->mask_ofs = mofs; \ 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->img_ofs = iofs; \ 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( q[idx].last ) \ 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn q[idx].last->next=node; \ 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else \ 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn q[idx].first = node; \ 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn q[idx].last = node; \ 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #define ws_pop(idx,mofs,iofs) \ 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { \ 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node = q[idx].first; \ 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn q[idx].first = node->next; \ 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !node->next ) \ 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn q[idx].last = 0; \ 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn node->next = free_node; \ 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free_node = node; \ 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mofs = node->mask_ofs; \ 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn iofs = node->img_ofs; \ 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #define c_diff(ptr1,ptr2,diff) \ 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { \ 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn db = abs((ptr1)[0] - (ptr2)[0]);\ 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dg = abs((ptr1)[1] - (ptr2)[1]);\ 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dr = abs((ptr1)[2] - (ptr2)[2]);\ 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn diff = ws_max(db,dg); \ 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn diff = ws_max(diff,dr); \ 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( 0 <= diff && diff <= 255 ); \ 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( src = cvGetMat( srcarr, &sstub )); 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( dst = cvGetMat( dstarr, &dstub )); 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(src->type) != CV_8UC3 ) 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, "Only 8-bit, 3-channel input images are supported" ); 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(dst->type) != CV_32SC1 ) 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn "Only 32-bit, 1-channel output images are supported" ); 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_SIZES_EQ( src, dst )) 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, "The input and output images must have the same size" ); 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn size = cvGetMatSize(src); 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( storage = cvCreateMemStorage() ); 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn istep = src->step; 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn img = src->data.ptr; 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mstep = dst->step / sizeof(mask[0]); 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask = dst->data.i; 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( q, 0, NQ*sizeof(q[0]) ); 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 256; i++ ) 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn subs_tab[i] = 0; 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 256; i <= 512; i++ ) 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn subs_tab[i] = i - 256; 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // draw a pixel-wide border of dummy "watershed" (i.e. boundary) pixels 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < size.width; j++ ) 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask[j] = mask[j + mstep*(size.height-1)] = WSHED; 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // initial phase: put all the neighbor pixels of each marker to the ordered queue - 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // determine the initial boundaries of the basins 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < size.height-1; i++ ) 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn img += istep; mask += mstep; 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask[0] = mask[size.width-1] = WSHED; 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 1; j < size.width-1; j++ ) 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* m = mask + j; 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[0] < 0 ) m[0] = 0; 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[0] == 0 && (m[-1] > 0 || m[1] > 0 || m[-mstep] > 0 || m[mstep] > 0) ) 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* ptr = img + j*3; 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int idx = 256, t; 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[-1] > 0 ) 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr - 3, idx ); 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[1] > 0 ) 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr + 3, t ); 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idx = ws_min( idx, t ); 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[-mstep] > 0 ) 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr - istep, t ); 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idx = ws_min( idx, t ); 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[mstep] > 0 ) 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr + istep, t ); 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn idx = ws_min( idx, t ); 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( 0 <= idx && idx <= 255 ); 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ws_push( idx, i*mstep + j, i*istep + j*3 ); 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m[0] = IN_QUEUE; 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // find the first non-empty queue 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < NQ; i++ ) 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( q[i].first ) 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // if there is no markers, exit immediately 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i == NQ ) 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn EXIT; 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn active_queue = i; 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn img = src->data.ptr; 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask = dst->data.i; 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // recursively fill the basins 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(;;) 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int mofs, iofs; 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int lab = 0, t; 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int* m; 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* ptr; 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( q[active_queue].first == 0 ) 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = active_queue+1; i < NQ; i++ ) 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( q[i].first ) 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( i == NQ ) 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn active_queue = i; 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ws_pop( active_queue, mofs, iofs ); 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m = mask + mofs; 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr = img + iofs; 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = m[-1]; 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( t > 0 ) lab = t; 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = m[1]; 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( t > 0 ) 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( lab == 0 ) lab = t; 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( t != lab ) lab = WSHED; 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = m[-mstep]; 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( t > 0 ) 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( lab == 0 ) lab = t; 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( t != lab ) lab = WSHED; 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t = m[mstep]; 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( t > 0 ) 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( lab == 0 ) lab = t; 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( t != lab ) lab = WSHED; 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn assert( lab != 0 ); 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m[0] = lab; 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( lab == WSHED ) 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[-1] == 0 ) 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr - 3, t ); 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ws_push( t, mofs - 1, iofs - 3 ); 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn active_queue = ws_min( active_queue, t ); 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m[-1] = IN_QUEUE; 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[1] == 0 ) 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr + 3, t ); 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ws_push( t, mofs + 1, iofs + 3 ); 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn active_queue = ws_min( active_queue, t ); 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m[1] = IN_QUEUE; 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[-mstep] == 0 ) 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr - istep, t ); 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ws_push( t, mofs - mstep, iofs - istep ); 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn active_queue = ws_min( active_queue, t ); 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m[-mstep] = IN_QUEUE; 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( m[mstep] == 0 ) 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c_diff( ptr, ptr + 3, t ); 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ws_push( t, mofs + mstep, iofs + istep ); 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn active_queue = ws_min( active_queue, t ); 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m[mstep] = IN_QUEUE; 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMemStorage( &storage ); 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/****************************************************************************************\ 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn* Meanshift * 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn\****************************************************************************************/ 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCV_IMPL void 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RenncvPyrMeanShiftFiltering( const CvArr* srcarr, CvArr* dstarr, 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sp0, double sr, int max_level, 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvTermCriteria termcrit ) 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int cn = 3; 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const int MAX_LEVELS = 8; 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat* src_pyramid[MAX_LEVELS+1]; 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat* dst_pyramid[MAX_LEVELS+1]; 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat* mask0 = 0; 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int i, j, level; 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //uchar* submask = 0; 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn #define cdiff(ofs0) (tab[c0-dptr[ofs0]+255] + \ 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tab[c1-dptr[(ofs0)+1]+255] + tab[c2-dptr[(ofs0)+2]+255] >= isr22) 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( src_pyramid, 0, sizeof(src_pyramid) ); 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memset( dst_pyramid, 0, sizeof(dst_pyramid) ); 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_FUNCNAME( "cvPyrMeanShiftFiltering" ); 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __BEGIN__; 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double sr2 = sr * sr; 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int isr2 = cvRound(sr2), isr22 = MAX(isr2,16); 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int tab[768]; 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat sstub0, *src0; 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat dstub0, *dst0; 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( src0 = cvGetMat( srcarr, &sstub0 )); 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( dst0 = cvGetMat( dstarr, &dstub0 )); 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( CV_MAT_TYPE(src0->type) != CV_8UC3 ) 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnsupportedFormat, "Only 8-bit, 3-channel images are supported" ); 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_TYPES_EQ( src0, dst0 )) 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedFormats, "The input and output images must have the same type" ); 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CV_ARE_SIZES_EQ( src0, dst0 )) 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsUnmatchedSizes, "The input and output images must have the same size" ); 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( (unsigned)max_level > (unsigned)MAX_LEVELS ) 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_ERROR( CV_StsOutOfRange, "The number of pyramid levels is too large or negative" ); 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !(termcrit.type & CV_TERMCRIT_ITER) ) 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn termcrit.max_iter = 5; 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn termcrit.max_iter = MAX(termcrit.max_iter,1); 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn termcrit.max_iter = MIN(termcrit.max_iter,100); 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !(termcrit.type & CV_TERMCRIT_EPS) ) 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn termcrit.epsilon = 1.f; 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn termcrit.epsilon = MAX(termcrit.epsilon, 0.f); 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < 768; i++ ) 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tab[i] = (i - 255)*(i - 255); 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // 1. construct pyramid 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn src_pyramid[0] = src0; 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dst_pyramid[0] = dst0; 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( level = 1; level <= max_level; level++ ) 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( src_pyramid[level] = cvCreateMat( (src_pyramid[level-1]->rows+1)/2, 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (src_pyramid[level-1]->cols+1)/2, src_pyramid[level-1]->type )); 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( dst_pyramid[level] = cvCreateMat( src_pyramid[level]->rows, 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn src_pyramid[level]->cols, src_pyramid[level]->type )); 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( cvPyrDown( src_pyramid[level-1], src_pyramid[level] )); 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //CV_CALL( cvResize( src_pyramid[level-1], src_pyramid[level], CV_INTER_AREA )); 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CV_CALL( mask0 = cvCreateMat( src0->rows, src0->cols, CV_8UC1 )); 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //CV_CALL( submask = (uchar*)cvAlloc( (sp+2)*(sp+2) )); 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // 2. apply meanshift, starting from the pyramid top (i.e. the smallest layer) 3976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( level = max_level; level >= 0; level-- ) 3986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat* src = src_pyramid[level]; 4006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize size = cvGetMatSize(src); 4016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* sptr = src->data.ptr; 4026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int sstep = src->step; 4036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* mask = 0; 4046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int mstep = 0; 4056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* dptr; 4066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int dstep; 4076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn float sp = (float)(sp0 / (1 << level)); 4086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sp = MAX( sp, 1 ); 4096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( level < max_level ) 4116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvSize size1 = cvGetMatSize(dst_pyramid[level+1]); 4136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CvMat m = cvMat( size.height, size.width, CV_8UC1, mask0->data.ptr ); 4146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dstep = dst_pyramid[level+1]->step; 4156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dptr = dst_pyramid[level+1]->data.ptr + dstep + cn; 4166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mstep = m.step; 4176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask = m.data.ptr + mstep; 4186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //cvResize( dst_pyramid[level+1], dst_pyramid[level], CV_INTER_CUBIC ); 4196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvPyrUp( dst_pyramid[level+1], dst_pyramid[level] ); 4206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvZero( &m ); 4216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i < size1.height-1; i++, dptr += dstep - (size1.width-2)*3, mask += mstep*2 ) 4236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 1; j < size1.width-1; j++, dptr += cn ) 4256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int c0 = dptr[0], c1 = dptr[1], c2 = dptr[2]; 4276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask[j*2 - 1] = cdiff(-3) || cdiff(3) || cdiff(-dstep-3) || cdiff(-dstep) || 4286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cdiff(-dstep+3) || cdiff(dstep-3) || cdiff(dstep) || cdiff(dstep+3); 4296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvDilate( &m, &m, 0, 1 ); 4336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask = m.data.ptr; 4346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dptr = dst_pyramid[level]->data.ptr; 4376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dstep = dst_pyramid[level]->step; 4386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 0; i < size.height; i++, sptr += sstep - size.width*3, 4406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dptr += dstep - size.width*3, 4416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn mask += mstep ) 4426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( j = 0; j < size.width; j++, sptr += 3, dptr += 3 ) 4446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int x0 = j, y0 = i, x1, y1, iter; 4466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int c0, c1, c2; 4476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( mask && !mask[j] ) 4496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn continue; 4506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c0 = sptr[0], c1 = sptr[1], c2 = sptr[2]; 4526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // iterate meanshift procedure 4546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( iter = 0; iter < termcrit.max_iter; iter++ ) 4556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* ptr; 4576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int x, y, count = 0; 4586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int minx, miny, maxx, maxy; 4596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int s0 = 0, s1 = 0, s2 = 0, sx = 0, sy = 0; 4606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn double icount; 4616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int stop_flag; 4626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn //mean shift: process pixels in window (p-sigmaSp)x(p+sigmaSp) 4646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn minx = cvRound(x0 - sp); minx = MAX(minx, 0); 4656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn miny = cvRound(y0 - sp); miny = MAX(miny, 0); 4666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn maxx = cvRound(x0 + sp); maxx = MIN(maxx, size.width-1); 4676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn maxy = cvRound(y0 + sp); maxy = MIN(maxy, size.height-1); 4686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ptr = sptr + (miny - i)*sstep + (minx - j)*3; 4696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 4706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( y = miny; y <= maxy; y++, ptr += sstep - (maxx-minx+1)*3 ) 4716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int row_count = 0; 4736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x = minx; 4746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; x + 3 <= maxx; x += 4, ptr += 12 ) 4756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t0 = ptr[0], t1 = ptr[1], t2 = ptr[2]; 4776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tab[t0-c0+255] + tab[t1-c1+255] + tab[t2-c2+255] <= isr2 ) 4786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s0 += t0; s1 += t1; s2 += t2; 4806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sx += x; row_count++; 4816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = ptr[3], t1 = ptr[4], t2 = ptr[5]; 4836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tab[t0-c0+255] + tab[t1-c1+255] + tab[t2-c2+255] <= isr2 ) 4846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s0 += t0; s1 += t1; s2 += t2; 4866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sx += x+1; row_count++; 4876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = ptr[6], t1 = ptr[7], t2 = ptr[8]; 4896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tab[t0-c0+255] + tab[t1-c1+255] + tab[t2-c2+255] <= isr2 ) 4906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s0 += t0; s1 += t1; s2 += t2; 4926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sx += x+2; row_count++; 4936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 4946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn t0 = ptr[9], t1 = ptr[10], t2 = ptr[11]; 4956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tab[t0-c0+255] + tab[t1-c1+255] + tab[t2-c2+255] <= isr2 ) 4966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 4976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s0 += t0; s1 += t1; s2 += t2; 4986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sx += x+3; row_count++; 4996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( ; x <= maxx; x++, ptr += 3 ) 5036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int t0 = ptr[0], t1 = ptr[1], t2 = ptr[2]; 5056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( tab[t0-c0+255] + tab[t1-c1+255] + tab[t2-c2+255] <= isr2 ) 5066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s0 += t0; s1 += t1; s2 += t2; 5086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sx += x; row_count++; 5096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn count += row_count; 5126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sy += y*row_count; 5136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( count == 0 ) 5166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 5176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn icount = 1./count; 5196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x1 = cvRound(sx*icount); 5206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn y1 = cvRound(sy*icount); 5216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s0 = cvRound(s0*icount); 5226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s1 = cvRound(s1*icount); 5236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn s2 = cvRound(s2*icount); 5246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn stop_flag = (x0 == x1 && y0 == y1) || abs(x1-x0) + abs(y1-y0) + 5266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tab[s0 - c0 + 255] + tab[s1 - c1 + 255] + 5276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn tab[s2 - c2 + 255] <= termcrit.epsilon; 5286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn x0 = x1; y0 = y1; 5306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn c0 = s0; c1 = s1; c2 = s2; 5316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( stop_flag ) 5336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn break; 5346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dptr[0] = (uchar)c0; 5376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dptr[1] = (uchar)c1; 5386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn dptr[2] = (uchar)c2; 5396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn __END__; 5446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 5456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for( i = 1; i <= MAX_LEVELS; i++ ) 5466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 5476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &src_pyramid[i] ); 5486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &dst_pyramid[i] ); 5496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 5506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn cvReleaseMat( &mask0 ); 5516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 5526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 553