1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
43 typedef struct _CvRGBf
50 typedef struct _CvRect16u
52 ushort x1, y1, x2, y2;
56 typedef struct _CvPyramid
61 _CvRect16u rect; /* ROI for the connected component */
64 /* element of base layer */
65 typedef struct _CvPyramidBase
72 typedef struct _CvPyramidC3
75 struct _CvPyramidC3 *p;
77 _CvRect16u rect; /* ROI for the connected component */
80 /* element of base layer */
81 typedef struct _CvPyramidBaseC3
84 struct _CvPyramidC3 *p;
88 typedef struct _CvListNode
90 struct _CvListNode* next;
96 static CvStatus icvSegmentClusterC1( CvSeq* cmp_seq, CvSeq* res_seq,
98 _CvPyramid* first_level_end,
99 CvSize first_level_size );
101 static CvStatus icvSegmentClusterC3( CvSeq* cmp_seq, CvSeq* res_seq,
103 _CvPyramidC3* first_level_end,
104 CvSize first_level_size );
106 static CvStatus icvUpdatePyrLinks_8u_C1
107 (int layer, void *layer_data, CvSize size, void *parent_layer,
108 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/);
110 static CvStatus icvUpdatePyrLinks_8u_C3
111 (int layer, void *layer_data, CvSize size, void *parent_layer,
112 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/);
114 static void icvMaxRoi( _CvRect16u *max_rect, _CvRect16u* cur_rect );
115 static void icvMaxRoi1( _CvRect16u *max_rect, int x, int y );
118 #define _CV_CHECK( icvFun ) \
120 if( icvFun != CV_OK ) \
125 #define _CV_MAX3( a, b, c) ((a)>(b) ? ((a)>(c) ? (a) : (c)) : ((b)>(c) ? (b) : (c)))
127 /*#define _CV_RGB_DIST(a, b) _CV_MAX3((float)fabs((a).red - (b).red), \
128 (float)fabs((a).green - (b).green), \
129 (float)fabs((a).blue - (b).blue))*/
131 #define _CV_NEXT_BASE_C1(p,n) (_CvPyramid*)((char*)(p) + (n)*sizeof(_CvPyramidBase))
132 #define _CV_NEXT_BASE_C3(p,n) (_CvPyramidC3*)((char*)(p) + (n)*sizeof(_CvPyramidBaseC3))
135 CV_INLINE float icvRGBDist_Max( const _CvRGBf& a, const _CvRGBf& b )
137 float tr = (float)fabs(a.red - b.red);
138 float tg = (float)fabs(a.green - b.green);
139 float tb = (float)fabs(a.blue - b.blue);
141 return _CV_MAX3( tr, tg, tb );
144 CV_INLINE float icvRGBDist_Sum( const _CvRGBf& a, const _CvRGBf& b )
146 float tr = (float)fabs(a.red - b.red);
147 float tg = (float)fabs(a.green - b.green);
148 float tb = (float)fabs(a.blue - b.blue);
150 return (tr + tg + tb);
154 #define _CV_RGB_DIST icvRGBDist_Max
155 #define _CV_RGB_THRESH_SCALE 1
157 #define _CV_RGB_DIST icvRGBDist_Sum
158 #define _CV_RGB_THRESH_SCALE 3
161 #define _CV_INV_TAB_SIZE 32
163 static const float icvInvTab[ /*_CV_INV_TAB_SIZE*/ ] =
165 1.00000000f, 0.50000000f, 0.33333333f, 0.25000000f, 0.20000000f, 0.16666667f,
166 0.14285714f, 0.12500000f, 0.11111111f, 0.10000000f, 0.09090909f, 0.08333333f,
167 0.07692308f, 0.07142857f, 0.06666667f, 0.06250000f, 0.05882353f, 0.05555556f,
168 0.05263158f, 0.05000000f, 0.04761905f, 0.04545455f, 0.04347826f, 0.04166667f,
169 0.04000000f, 0.03846154f, 0.03703704f, 0.03571429f, 0.03448276f, 0.03333333f,
170 0.03225806f, 0.03125000f
174 icvWritePyrNode( void *elem, void *writer )
176 CV_WRITE_SEQ_ELEM( *(_CvListNode *) elem, *(CvSeqWriter *) writer );
181 icvPyrSegmentation8uC1R( uchar * src_image, int src_step,
182 uchar * dst_image, int dst_step,
183 CvSize roi, CvFilter filter,
184 CvSeq ** dst_comp, CvMemStorage * storage,
185 int level, int threshold1, int threshold2 )
189 const int max_iter = 3; /* maximum number of iterations */
190 int cur_iter = 0; /* current iteration */
192 _CvPyramid *pyram[16]; /* pointers to the pyramid down up to level */
198 _CvPyramidBase *p_base;
199 _CvListNode cmp_node;
203 CvMemStorage *temp_storage = 0;
213 /* clear pointer to resultant sequence */
218 if( !src_image || !dst_image || !storage || !dst_comp )
219 return CV_NULLPTR_ERR;
220 if( roi.width <= 0 || roi.height <= 0 || src_step < roi.width || dst_step < roi.width )
221 return CV_BADSIZE_ERR;
222 if( filter != CV_GAUSSIAN_5x5 )
223 return CV_BADRANGE_ERR;
224 if( threshold1 < 0 || threshold2 < 0 )
225 return CV_BADRANGE_ERR;
227 return CV_BADRANGE_ERR;
229 if( ((roi.width | roi.height) & ((1 << level) - 1)) != 0 )
230 return CV_BADCOEF_ERR;
232 temp_storage = cvCreateChildMemStorage( storage );
234 /* sequence for temporary components */
235 cmp_seq = cvCreateSeq( 0, sizeof( CvSeq ), sizeof( _CvListNode ), temp_storage );
236 assert( cmp_seq != 0 );
238 res_seq = cvCreateSeq( CV_SEQ_CONNECTED_COMP, sizeof( CvSeq ),
239 sizeof( CvConnectedComp ), storage );
240 assert( res_seq != 0 );
242 /* calculate buffer size */
243 buffer_size = roi.width * roi.height * (sizeof( float ) + sizeof( _CvPyramidBase ));
245 for( l = 1; l <= level; l++ )
246 buffer_size += ((roi.width >> l) + 1) * ((roi.height >> l) + 1) * sizeof(_CvPyramid);
248 /* allocate buffer */
249 buffer = (char *) cvAlloc( buffer_size );
252 status = CV_OUTOFMEM_ERR;
256 pyramida = (float *) buffer;
258 /* initialization pyramid-linking properties down up to level */
259 step = roi.width * sizeof( float );
264 cvInitMatHeader( &_src, roi.height, roi.width, CV_8UC1, src_image, src_step );
265 cvInitMatHeader( &_pyramida, roi.height, roi.width, CV_32FC1, pyramida, step );
266 cvConvert( &_src, &_pyramida );
267 /*_CV_CHECK( icvCvtTo_32f_C1R( src_image, src_step, pyramida, step, roi, CV_8UC1 ));*/
269 p_base = (_CvPyramidBase *) (buffer + step * roi.height);
270 pyram[0] = (_CvPyramid *) p_base;
272 /* fill base level of pyramid */
273 for( i = 0; i < roi.height; i++ )
275 for( j = 0; j < roi.width; j++, p_base++ )
277 p_base->c = pyramida[i * roi.width + j];
282 p_cur = (_CvPyramid *) p_base;
285 /* calculate initial pyramid */
286 for( l = 1; l <= level; l++ )
288 CvSize dst_size = { size.width/2+1, size.height/2+1 };
289 CvMat prev_level = cvMat( size.height, size.width, CV_32FC1 );
290 CvMat next_level = cvMat( dst_size.height, dst_size.width, CV_32FC1 );
292 cvSetData( &prev_level, pyramida, step );
293 cvSetData( &next_level, pyramida, step );
294 cvPyrDown( &prev_level, &next_level );
296 //_CV_CHECK( icvPyrDown_Gauss5x5_32f_C1R( pyramida, step, pyramida, step, size, buff ));
297 //_CV_CHECK( icvPyrDownBorder_32f_CnR( pyramida, step, size, pyramida, step, dst_size, 1 ));
300 size.width = dst_size.width - 1;
301 size.height = dst_size.height - 1;
304 for( i = 0; i <= size.height; i++ )
306 for( j = 0; j <= size.width; j++, p_cur++ )
308 p_cur->c = pyramida[i * roi.width + j];
316 cvStartAppendToSeq( cmp_seq, &writer );
318 /* do several iterations to determine son-father links */
319 for( cur_iter = 0; cur_iter < max_iter; cur_iter++ )
321 int is_last_iter = cur_iter == max_iter - 1;
325 /* build son-father links down up to level */
326 for( l = 0; l < level; l++ )
328 icvUpdatePyrLinks_8u_C1( l, pyram[l], size, pyram[l + 1], &writer,
329 (float) threshold1, is_last_iter, &stub,
332 /* clear last border row */
335 p_cur = pyram[l] + (size.width + 1) * size.height;
336 for( j = 0; j <= size.width; j++ )
344 /* clear the old c value for the last level */
345 p_cur = pyram[level];
346 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 )
347 for( j = 0; j <= size.width; j++ )
353 /* calculate average c value for the 0 < l <=level */
354 for( l = 0; l < level; l++, step = (step >> 1) + 1 )
356 _CvPyramid *p_prev, *p_row_prev;
360 /* calculate average c value for the next level */
363 p_base = (_CvPyramidBase *) pyram[0];
364 for( i = 0; i < roi.height; i++, p_base += size.width )
366 for( j = 0; j < size.width; j += 2 )
368 _CvPyramid *p1 = p_base[j].p;
369 _CvPyramid *p2 = p_base[j + 1].p;
371 p1->c += p_base[j].c;
372 p2->c += p_base[j + 1].c;
379 for( i = 0; i < size.height; i++, p_cur += size.width + 1 )
381 for( j = 0; j < size.width; j += 2 )
383 _CvPyramid *p1 = p_cur[j].p;
384 _CvPyramid *p2 = p_cur[j + 1].p;
386 float t0 = (float) p_cur[j].a * p_cur[j].c;
387 float t1 = (float) p_cur[j + 1].a * p_cur[j + 1].c;
393 p_cur[j].a = p_cur[j + 1].a = 0;
396 p_cur[size.width].a = 0;
400 for( j = 0; j <= size.width; j++ )
407 /* assign random values of the next level null c */
408 p_cur = pyram[l + 1];
409 p_row_prev = p_prev = pyram[l];
414 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 )
416 if( i < size.height || !is_last_iter )
418 for( j = 0; j < size.width; j++ )
424 if( a <= _CV_INV_TAB_SIZE )
426 p_cur[j].c *= icvInvTab[a - 1];
435 p_cur[j].c = p_prev->c;
439 p_prev = _CV_NEXT_BASE_C1(p_prev,2);
444 if( p_cur[size.width].a == 0 )
446 p_cur[size.width].c = p_prev[(l != 0) - 1].c;
450 p_cur[size.width].c /= p_cur[size.width].a;
453 cmp_node.data = p_cur + size.width;
454 CV_WRITE_SEQ_ELEM( cmp_node, writer );
460 for( j = 0; j <= size.width; j++ )
466 if( a <= _CV_INV_TAB_SIZE )
468 p_cur[j].c *= icvInvTab[a - 1];
475 cmp_node.data = p_cur + j;
476 CV_WRITE_SEQ_ELEM( cmp_node, writer );
480 p_cur[j].c = p_prev->c;
485 p_prev = _CV_NEXT_BASE_C1(p_prev, (j * 2 < step - 2 ? 2 : 1));
494 if( l + 1 == level && !is_last_iter )
495 for( j = 0; j <= size.width; j++ )
504 p_prev = (_CvPyramid*)((char*)p_row_prev + step *
505 (l == 0 ? sizeof(_CvPyramidBase) : sizeof(_CvPyramid)));
509 } /* end of the iteration process */
511 /* construct a connected components */
512 size.width = roi.width >> level;
513 size.height = roi.height >> level;
515 p_cur = pyram[level];
517 for( i = 0; i < size.height; i++, p_cur += size.width + 1 )
519 for( j = 0; j < size.width; j++ )
521 if( p_cur[j].a != 0 )
523 cmp_node.data = p_cur + j;
524 CV_WRITE_SEQ_ELEM( cmp_node, writer );
529 cvEndWriteSeq( &writer );
531 /* clusterization segmented components and construction
532 output connected components */
533 icvSegmentClusterC1( cmp_seq, res_seq, threshold2, pyram[1], roi );
535 /* convert (inplace) resultant segment values to int (top level) */
537 /* propagate segment values top down */
538 for( l = level - 1; l >= 0; l-- )
551 for( i = 0; i <= size.height; i++ )
553 for( j = 0; j <= size.width; j++ )
555 _CvPyramid *p = p_cur->p;
564 /* copy the segmented values to destination image */
565 _c.f = p_cur->c; dst_image[j] = (uchar)_c.i;
566 p_cur = _CV_NEXT_BASE_C1(p_cur, 1);
574 dst_image += dst_step;
580 cvReleaseMemStorage( &temp_storage );
582 if( status == CV_OK )
590 /****************************************************************************************\
591 color!!! image segmentation by pyramid-linking
592 \****************************************************************************************/
594 icvPyrSegmentation8uC3R( uchar * src_image, int src_step,
595 uchar * dst_image, int dst_step,
596 CvSize roi, CvFilter filter,
597 CvSeq ** dst_comp, CvMemStorage * storage,
598 int level, int threshold1, int threshold2 )
603 const int max_iter = 3; /* maximum number of iterations */
604 int cur_iter = 0; /* current iteration */
606 _CvPyramidC3 *pyram[16]; /* pointers to the pyramid down up to level */
612 _CvPyramidBaseC3 *p_base;
613 _CvListNode cmp_node;
617 CvMemStorage *temp_storage = 0;
627 threshold1 *= _CV_RGB_THRESH_SCALE;
628 threshold2 *= _CV_RGB_THRESH_SCALE;
630 /* clear pointer to resultant sequence */
635 if( !src_image || !dst_image || !storage || !dst_comp )
636 return CV_NULLPTR_ERR;
637 if( roi.width <= 0 || roi.height <= 0 ||
638 src_step < roi.width * 3 || dst_step < roi.width * 3 ) return CV_BADSIZE_ERR;
639 if( filter != CV_GAUSSIAN_5x5 )
640 return CV_BADRANGE_ERR;
641 if( threshold1 < 0 || threshold2 < 0 )
642 return CV_BADRANGE_ERR;
644 return CV_BADRANGE_ERR;
646 if( ((roi.width | roi.height) & ((1 << level) - 1)) != 0 )
647 return CV_BADCOEF_ERR;
649 temp_storage = cvCreateChildMemStorage( storage );
651 /* sequence for temporary components */
652 cmp_seq = cvCreateSeq( 0, sizeof( CvSeq ), sizeof( _CvListNode ), temp_storage );
653 assert( cmp_seq != 0 );
655 res_seq = cvCreateSeq( CV_SEQ_CONNECTED_COMP, sizeof( CvSeq ),
656 sizeof( CvConnectedComp ), storage );
657 assert( res_seq != 0 );
659 /* calculate buffer size */
660 buffer_size = roi.width * roi.height * (sizeof( _CvRGBf ) + sizeof( _CvPyramidBaseC3 ));
662 for( l = 1; l <= level; l++ )
663 buffer_size += ((roi.width >> l) + 1) * ((roi.height >> l) + 1) * sizeof(_CvPyramidC3);
665 /* allocate buffer */
666 buffer = (char *) cvAlloc( buffer_size );
669 status = CV_OUTOFMEM_ERR;
673 pyramida = (float *) buffer;
675 /* initialization pyramid-linking properties down up to level */
676 step = roi.width * sizeof( _CvRGBf );
681 cvInitMatHeader( &_src, roi.height, roi.width, CV_8UC3, src_image, src_step );
682 cvInitMatHeader( &_pyramida, roi.height, roi.width, CV_32FC3, pyramida, step );
683 cvConvert( &_src, &_pyramida );
684 /*_CV_CHECK( icvCvtTo_32f_C1R( src_image, src_step, pyramida, step,
685 cvSize( roi.width * 3, roi.height ), CV_8UC1 ));*/
688 p_base = (_CvPyramidBaseC3 *) (buffer + step * roi.height);
689 pyram[0] = (_CvPyramidC3 *) p_base;
691 /* fill base level of pyramid */
692 for( i = 0; i < roi.height; i++ )
694 for( j = 0; j < roi.width; j++, p_base++ )
696 p_base->c = ((_CvRGBf *) pyramida)[i * roi.width + j];
701 p_cur = (_CvPyramidC3 *) p_base;
704 /* calculate initial pyramid */
705 for( l = 1; l <= level; l++ )
707 CvSize dst_size = { size.width/2 + 1, size.height/2 + 1 };
708 CvMat prev_level = cvMat( size.height, size.width, CV_32FC3 );
709 CvMat next_level = cvMat( dst_size.height, dst_size.width, CV_32FC3 );
711 cvSetData( &prev_level, pyramida, step );
712 cvSetData( &next_level, pyramida, step );
713 cvPyrDown( &prev_level, &next_level );
715 //_CV_CHECK( icvPyrDown_Gauss5x5_32f_C3R( pyramida, step, pyramida, step, size, buff ));
716 //_CV_CHECK( icvPyrDownBorder_32f_CnR( pyramida, step, size, pyramida, step, dst_size, 3 ));
719 size.width = dst_size.width - 1;
720 size.height = dst_size.height - 1;
723 for( i = 0; i <= size.height; i++ )
725 assert( (char*)p_cur - buffer < buffer_size );
726 for( j = 0; j <= size.width; j++, p_cur++ )
728 p_cur->c = ((_CvRGBf *) pyramida)[i * roi.width + j];
736 cvStartAppendToSeq( cmp_seq, &writer );
738 /* do several iterations to determine son-father links */
739 for( cur_iter = 0; cur_iter < max_iter; cur_iter++ )
741 int is_last_iter = cur_iter == max_iter - 1;
745 /* build son-father links down up to level */
746 for( l = 0; l < level; l++ )
748 icvUpdatePyrLinks_8u_C3( l, pyram[l], size, pyram[l + 1], &writer,
749 (float) threshold1, is_last_iter, &stub,
752 /* clear last border row */
755 p_cur = pyram[l] + (size.width + 1) * size.height;
756 for( j = 0; j <= size.width; j++ )
757 p_cur[j].c.blue = p_cur[j].c.green = p_cur[j].c.red = 0;
764 /* clear the old c value for the last level */
765 p_cur = pyram[level];
766 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 )
767 for( j = 0; j <= size.width; j++ )
768 p_cur[j].c.blue = p_cur[j].c.green = p_cur[j].c.red = 0;
773 /* calculate average c value for the 0 < l <=level */
774 for( l = 0; l < level; l++, step = (step >> 1) + 1 )
776 _CvPyramidC3 *p_prev, *p_row_prev;
778 stub.c.blue = stub.c.green = stub.c.red = 0;
780 /* calculate average c value for the next level */
783 p_base = (_CvPyramidBaseC3 *) pyram[0];
784 for( i = 0; i < roi.height; i++, p_base += size.width )
786 for( j = 0; j < size.width; j++ )
788 _CvPyramidC3 *p = p_base[j].p;
790 p->c.blue += p_base[j].c.blue;
791 p->c.green += p_base[j].c.green;
792 p->c.red += p_base[j].c.red;
799 for( i = 0; i < size.height; i++, p_cur += size.width + 1 )
801 for( j = 0; j < size.width; j++ )
803 _CvPyramidC3 *p = p_cur[j].p;
804 float a = (float) p_cur[j].a;
806 p->c.blue += a * p_cur[j].c.blue;
807 p->c.green += a * p_cur[j].c.green;
808 p->c.red += a * p_cur[j].c.red;
814 p_cur[size.width].a = 0;
818 for( j = 0; j <= size.width; j++ )
825 /* assign random values of the next level null c */
826 p_cur = pyram[l + 1];
827 p_row_prev = p_prev = pyram[l];
832 for( i = 0; i <= size.height; i++, p_cur += size.width + 1 )
834 if( i < size.height || !is_last_iter )
836 for( j = 0; j < size.width; j++ )
844 if( a <= _CV_INV_TAB_SIZE )
846 inv_a = icvInvTab[a - 1];
852 p_cur[j].c.blue *= inv_a;
853 p_cur[j].c.green *= inv_a;
854 p_cur[j].c.red *= inv_a;
858 p_cur[j].c = p_prev->c;
862 p_prev = _CV_NEXT_BASE_C3( p_prev, 2 );
867 if( p_cur[size.width].a == 0 )
869 p_cur[size.width].c = p_prev[(l != 0) - 1].c;
873 p_cur[size.width].c.blue /= p_cur[size.width].a;
874 p_cur[size.width].c.green /= p_cur[size.width].a;
875 p_cur[size.width].c.red /= p_cur[size.width].a;
878 cmp_node.data = p_cur + size.width;
879 CV_WRITE_SEQ_ELEM( cmp_node, writer );
885 for( j = 0; j <= size.width; j++ )
893 if( a <= _CV_INV_TAB_SIZE )
895 inv_a = icvInvTab[a - 1];
901 p_cur[j].c.blue *= inv_a;
902 p_cur[j].c.green *= inv_a;
903 p_cur[j].c.red *= inv_a;
905 cmp_node.data = p_cur + j;
906 CV_WRITE_SEQ_ELEM( cmp_node, writer );
910 p_cur[j].c = p_prev->c;
915 p_prev = _CV_NEXT_BASE_C3( p_prev, (j * 2 < step - 2 ? 2 : 1));
924 if( l + 1 == level && !is_last_iter )
925 for( j = 0; j <= size.width; j++ )
934 p_prev = (_CvPyramidC3*)((char*)p_row_prev + step *
935 (l == 0 ? sizeof( _CvPyramidBaseC3 ) : sizeof( _CvPyramidC3 )));
939 } /* end of the iteration process */
941 /* construct a connected components */
942 size.width = roi.width >> level;
943 size.height = roi.height >> level;
945 p_cur = pyram[level];
947 for( i = 0; i < size.height; i++, p_cur += size.width + 1 )
949 for( j = 0; j < size.width; j++ )
951 if( p_cur[j].a != 0 )
953 cmp_node.data = p_cur + j;
954 CV_WRITE_SEQ_ELEM( cmp_node, writer );
959 cvEndWriteSeq( &writer );
961 /* clusterization segmented components and construction
962 output connected components */
963 icvSegmentClusterC3( cmp_seq, res_seq, threshold2, pyram[1], roi );
965 /* convert (inplace) resultant segment values to int (top level) */
967 /* propagate segment values top down */
968 for( l = level - 1; l >= 0; l-- )
981 for( i = 0; i <= size.height; i++ )
983 for( j = 0; j <= size.width; j++ )
985 _CvPyramidC3 *p = p_cur->p;
996 /* copy the segmented values to destination image */
997 _c.f = p_cur->c.blue; dst_image[j*3] = (uchar)_c.i;
998 _c.f = p_cur->c.green; dst_image[j*3+1] = (uchar)_c.i;
999 _c.f = p_cur->c.red; dst_image[j*3+2] = (uchar)_c.i;
1000 p_cur = _CV_NEXT_BASE_C3(p_cur,1);
1008 dst_image += dst_step;
1015 cvReleaseMemStorage( &temp_storage );
1017 if( status == CV_OK )
1018 *dst_comp = res_seq;
1024 static CvStatus icvUpdatePyrLinks_8u_C1
1025 (int layer, void *layer_data, CvSize size, void *parent_layer,
1026 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/)
1029 _CvListNode cmp_node;
1031 _CvPyramid *stub = (_CvPyramid *) _stub;
1032 _CvPyramid *p_cur = (_CvPyramid *) layer_data;
1033 _CvPyramid *p_next1 = (_CvPyramid *) parent_layer;
1034 _CvPyramid *p_next3 = p_next1 + (size.width >> 1) + 1;
1036 CvSeqWriter & writer = *(CvSeqWriter *) _writer;
1038 for( i = 0; i < size.height; i++ )
1040 for( j = 0; j < size.width; j += 2 )
1042 float c0, c1, c2, c3, c4;
1045 /* son-father threshold linking for the current node establish */
1048 /* find pointer for the first pixel */
1049 c1 = (float) fabs( c0 - p_next1[0].c );
1050 c2 = (float) fabs( c0 - p_next1[1].c );
1051 c3 = (float) fabs( c0 - p_next3[0].c );
1052 c4 = (float) fabs( c0 - p_next3[1].c );
1072 if( c1 <= threshold )
1079 p_cur = (_CvPyramid*)((char*)p_cur + sizeof(_CvPyramidBase));
1081 icvMaxRoi1( &(p->rect), j, i );
1090 if( is_last_iter && a != 0 )
1091 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) );
1099 cmp_node.data = p_cur;
1100 CV_WRITE_SEQ_ELEM( cmp_node, writer );
1104 p_cur = _CV_NEXT_BASE_C1(p_cur,1);
1113 /* find pointer for the second pixel */
1116 c1 = (float) fabs( c0 - p_next1[0].c );
1117 c2 = (float) fabs( c0 - p_next1[1].c );
1118 c3 = (float) fabs( c0 - p_next3[0].c );
1119 c4 = (float) fabs( c0 - p_next3[1].c );
1142 if( c1 <= threshold )
1149 p_cur = _CV_NEXT_BASE_C1(p_cur,1);
1151 icvMaxRoi1( &(p->rect), j + 1, i );
1160 if( is_last_iter && a != 0 )
1161 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) );
1169 cmp_node.data = p_cur;
1170 CV_WRITE_SEQ_ELEM( cmp_node, writer );
1174 p_cur = _CV_NEXT_BASE_C1(p_cur,1);
1193 p_next1 -= size.width >> 1;
1194 p_next3 -= size.width >> 1;
1207 static CvStatus icvUpdatePyrLinks_8u_C3
1208 (int layer, void *layer_data, CvSize size, void *parent_layer,
1209 void *_writer, float threshold, int is_last_iter, void *_stub, CvWriteNodeFunction /*func*/)
1212 _CvListNode cmp_node;
1214 _CvPyramidC3 *stub = (_CvPyramidC3 *) _stub;
1215 _CvPyramidC3 *p_cur = (_CvPyramidC3 *) layer_data;
1216 _CvPyramidC3 *p_next1 = (_CvPyramidC3 *) parent_layer;
1217 _CvPyramidC3 *p_next3 = p_next1 + (size.width >> 1) + 1;
1219 CvSeqWriter & writer = *(CvSeqWriter *) _writer;
1221 for( i = 0; i < size.height; i++ )
1223 for( j = 0; j < size.width; j += 2 )
1225 float c1, c2, c3, c4;
1228 /* find pointer for the first pixel */
1229 c1 = _CV_RGB_DIST( p_cur->c, p_next1[0].c );
1230 c2 = _CV_RGB_DIST( p_cur->c, p_next1[1].c );
1231 c3 = _CV_RGB_DIST( p_cur->c, p_next3[0].c );
1232 c4 = _CV_RGB_DIST( p_cur->c, p_next3[1].c );
1252 if( c1 < threshold )
1259 p_cur = _CV_NEXT_BASE_C3(p_cur,1);
1261 icvMaxRoi1( &(p->rect), j, i );
1268 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0;
1270 if( is_last_iter && a != 0 )
1271 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) );
1277 if( is_last_iter /* && ( == 0 || p_cur->a != 0) */ )
1279 cmp_node.data = p_cur;
1280 CV_WRITE_SEQ_ELEM( cmp_node, writer );
1285 p_cur = _CV_NEXT_BASE_C3(p_cur,1);
1289 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0;
1294 /* find pointer for the second pixel */
1295 c1 = _CV_RGB_DIST( p_cur->c, p_next1[0].c );
1296 c2 = _CV_RGB_DIST( p_cur->c, p_next1[1].c );
1297 c3 = _CV_RGB_DIST( p_cur->c, p_next3[0].c );
1298 c4 = _CV_RGB_DIST( p_cur->c, p_next3[1].c );
1321 if( c1 < threshold )
1328 p_cur = _CV_NEXT_BASE_C3(p_cur,1);
1330 icvMaxRoi1( &(p->rect), j + 1, i );
1337 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0;
1339 if( is_last_iter && a != 0 )
1340 icvMaxRoi( &(p->rect), &(p_cur[-1].rect) );
1346 if( is_last_iter /* && ( == 0 || p_cur->a != 0) */ )
1348 cmp_node.data = p_cur;
1349 CV_WRITE_SEQ_ELEM( cmp_node, writer );
1353 p_cur = _CV_NEXT_BASE_C3(p_cur,1);
1357 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0;
1366 p_cur->c.blue = p_cur->c.green = p_cur->c.red = 0;
1372 p_next1 -= size.width >> 1;
1373 p_next3 -= size.width >> 1;
1387 /****************************************************************************************\
1389 clusterization segmented components
1391 \****************************************************************************************/
1393 icvExpandBaseLevelC1( _CvPyramid * base_p, _CvPyramid * p, _CvPyramidBase * start, int width )
1395 int x = (int)((_CvPyramidBase *) base_p - start);
1400 p->rect.x1 = (ushort) x;
1401 p->rect.y1 = (ushort) y;
1402 p->rect.x2 = (ushort) (x + 1);
1403 p->rect.y2 = (ushort) (y + 1);
1408 icvSegmentClusterC1( CvSeq * cmp_seq, CvSeq * res_seq,
1409 double threshold, _CvPyramid * first_level_end, CvSize first_level_size )
1411 const double eps = 1.;
1414 _CvPyramid temp_cmp;
1415 _CvPyramidBase *first_level_start = (_CvPyramidBase *) first_level_end -
1416 first_level_size.width * first_level_size.height;
1417 int c, i, count = cmp_seq->total;
1419 cvStartReadSeq( cmp_seq, &reader, 0 );
1420 cvStartAppendToSeq( res_seq, &writer );
1422 if( threshold < eps )
1424 /* if threshold is too small then simply copy all
1425 the components to the output sequence */
1426 for( i = 0; i < count; i++ )
1428 CvConnectedComp comp;
1429 _CvPyramid *cmp = (_CvPyramid *) (((_CvListNode *) reader.ptr)->data);
1432 if( cmp < first_level_end )
1434 icvExpandBaseLevelC1( cmp, &temp_cmp, first_level_start,
1435 first_level_size.width );
1439 _c.i = cvRound( cmp->c );
1441 comp.value = cvRealScalar(_c.i);
1443 comp.rect.x = cmp->rect.x1;
1444 comp.rect.y = cmp->rect.y1;
1445 comp.rect.width = cmp->rect.x2 - cmp->rect.x1;
1446 comp.rect.height = cmp->rect.y2 - cmp->rect.y1;
1449 CV_WRITE_SEQ_ELEM( comp, writer );
1450 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader );
1455 _CvListNode stub_node;
1456 _CvListNode *prev = &stub_node;
1460 for( i = 0; i < count; i++ )
1462 _CvListNode *node = (_CvListNode *) reader.ptr;
1466 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader );
1469 prev = stub_node.next;
1473 _CvListNode *node = prev->next;
1474 _CvListNode *acc = prev;
1475 _CvPyramid *cmp = (_CvPyramid *) (acc->data);
1476 CvConnectedComp comp;
1479 if( cmp < first_level_end )
1481 icvExpandBaseLevelC1( cmp, &temp_cmp, first_level_start,
1482 first_level_size.width );
1487 temp_cmp.c *= temp_cmp.a;
1496 cmp = (_CvPyramid *) (node->data);
1497 if( fabs( c0 - cmp->c ) < threshold )
1501 /* exclude from global list and add to list of joint component */
1502 prev->next = node->next;
1506 if( cmp < first_level_end )
1508 icvExpandBaseLevelC1( cmp, &temp, first_level_start,
1509 first_level_size.width );
1513 temp_cmp.a += cmp->a;
1514 temp_cmp.c += cmp->c * cmp->a;
1515 icvMaxRoi( &(temp_cmp.rect), &(cmp->rect) );
1519 if( prev == &stub_node )
1521 stub_node.next = node;
1528 if( temp_cmp.a != 0 )
1530 c = cvRound( temp_cmp.c / temp_cmp.a );
1541 cmp = (_CvPyramid *) (node->data);
1542 _c.i = c; cmp->c = _c.f;
1546 comp.value = cvRealScalar(c);
1547 comp.area = temp_cmp.a;
1548 comp.rect.x = temp_cmp.rect.x1;
1549 comp.rect.y = temp_cmp.rect.y1;
1550 comp.rect.width = temp_cmp.rect.x2 - temp_cmp.rect.x1;
1551 comp.rect.height = temp_cmp.rect.y2 - temp_cmp.rect.y1;
1554 CV_WRITE_SEQ_ELEM( comp, writer );
1555 prev = stub_node.next;
1559 cvEndWriteSeq( &writer );
1563 /****************************************************************************************\
1565 clusterization segmented components
1567 \****************************************************************************************/
1569 icvExpandBaseLevelC3( _CvPyramidC3 * base_p, _CvPyramidC3 * p,
1570 _CvPyramidBaseC3 * start, int width )
1572 int x = (int)((_CvPyramidBaseC3 *) base_p - start);
1577 p->rect.x1 = (ushort) x;
1578 p->rect.y1 = (ushort) y;
1579 p->rect.x2 = (ushort) (x + 1);
1580 p->rect.y2 = (ushort) (y + 1);
1585 icvSegmentClusterC3( CvSeq * cmp_seq, CvSeq * res_seq,
1587 _CvPyramidC3 * first_level_end, CvSize first_level_size )
1589 const double eps = 1.;
1592 _CvPyramidC3 temp_cmp;
1593 _CvPyramidBaseC3 *first_level_start = (_CvPyramidBaseC3 *) first_level_end -
1594 first_level_size.width * first_level_size.height;
1595 int i, count = cmp_seq->total;
1596 int c_blue, c_green, c_red;
1598 cvStartReadSeq( cmp_seq, &reader, 0 );
1599 cvStartAppendToSeq( res_seq, &writer );
1601 if( threshold < eps )
1603 /* if threshold is too small then simply copy all
1604 the components to the output sequence */
1605 for( i = 0; i < count; i++ )
1607 CvConnectedComp comp;
1608 _CvPyramidC3 *cmp = (_CvPyramidC3 *) (((_CvListNode *) reader.ptr)->data);
1611 if( cmp < first_level_end )
1613 icvExpandBaseLevelC3( cmp, &temp_cmp, first_level_start,
1614 first_level_size.width );
1618 c_blue = cvRound( cmp->c.blue );
1619 c_green = cvRound( cmp->c.green );
1620 c_red = cvRound( cmp->c.red );
1621 _c.i = c_blue; cmp->c.blue = _c.f;
1622 _c.i = c_green; cmp->c.green = _c.f;
1623 _c.i = c_red; cmp->c.red = _c.f;
1624 comp.value = cvScalar( c_blue, c_green, c_red );
1626 comp.rect.x = cmp->rect.x1;
1627 comp.rect.y = cmp->rect.y1;
1628 comp.rect.width = cmp->rect.x2 - cmp->rect.x1;
1629 comp.rect.height = cmp->rect.y2 - cmp->rect.y1;
1632 CV_WRITE_SEQ_ELEM( comp, writer );
1633 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader );
1638 _CvListNode stub_node;
1639 _CvListNode *prev = &stub_node;
1643 for( i = 0; i < count; i++ )
1645 _CvListNode *node = (_CvListNode *) reader.ptr;
1649 CV_NEXT_SEQ_ELEM( sizeof( _CvListNode ), reader );
1652 prev = stub_node.next;
1656 _CvListNode *node = prev->next;
1657 _CvListNode *acc = prev;
1658 _CvPyramidC3 *cmp = (_CvPyramidC3 *) (acc->data);
1659 CvConnectedComp comp;
1660 _CvRGBf c0 = cmp->c;
1662 if( cmp < first_level_end )
1664 icvExpandBaseLevelC3( cmp, &temp_cmp, first_level_start,
1665 first_level_size.width );
1670 temp_cmp.c.blue *= temp_cmp.a;
1671 temp_cmp.c.green *= temp_cmp.a;
1672 temp_cmp.c.red *= temp_cmp.a;
1681 cmp = (_CvPyramidC3 *) (node->data);
1682 if( _CV_RGB_DIST( c0, cmp->c ) < threshold )
1686 /* exclude from global list and add to list of joint component */
1687 prev->next = node->next;
1691 if( cmp < first_level_end )
1693 icvExpandBaseLevelC3( cmp, &temp, first_level_start,
1694 first_level_size.width );
1698 temp_cmp.a += cmp->a;
1699 temp_cmp.c.blue += cmp->c.blue * cmp->a;
1700 temp_cmp.c.green += cmp->c.green * cmp->a;
1701 temp_cmp.c.red += cmp->c.red * cmp->a;
1702 icvMaxRoi( &(temp_cmp.rect), &(cmp->rect) );
1706 if( prev == &stub_node )
1708 stub_node.next = node;
1715 if( temp_cmp.a != 0 )
1717 c_blue = cvRound( temp_cmp.c.blue / temp_cmp.a );
1718 c_green = cvRound( temp_cmp.c.green / temp_cmp.a );
1719 c_red = cvRound( temp_cmp.c.red / temp_cmp.a );
1723 c_blue = cvRound( c0.blue );
1724 c_green = cvRound( c0.green );
1725 c_red = cvRound( c0.red );
1732 cmp = (_CvPyramidC3 *) (node->data);
1733 _c.i = c_blue; cmp->c.blue = _c.f;
1734 _c.i = c_green; cmp->c.green = _c.f;
1735 _c.i = c_red; cmp->c.red = _c.f;
1739 comp.value = cvScalar( c_blue, c_green, c_red );
1740 comp.area = temp_cmp.a;
1741 comp.rect.x = temp_cmp.rect.x1;
1742 comp.rect.y = temp_cmp.rect.y1;
1743 comp.rect.width = temp_cmp.rect.x2 - temp_cmp.rect.x1;
1744 comp.rect.height = temp_cmp.rect.y2 - temp_cmp.rect.y1;
1747 CV_WRITE_SEQ_ELEM( comp, writer );
1748 prev = stub_node.next;
1752 cvEndWriteSeq( &writer );
1756 /****************************************************************************************\
1758 definition of the maximum roi size
1760 \****************************************************************************************/
1762 icvMaxRoi( _CvRect16u * max_rect, _CvRect16u * cur_rect )
1764 if( max_rect->x2 == 0 )
1765 *max_rect = *cur_rect;
1768 if( max_rect->x1 > cur_rect->x1 )
1769 max_rect->x1 = cur_rect->x1;
1770 if( max_rect->y1 > cur_rect->y1 )
1771 max_rect->y1 = cur_rect->y1;
1773 if( max_rect->x2 < cur_rect->x2 )
1774 max_rect->x2 = cur_rect->x2;
1775 if( max_rect->y2 < cur_rect->y2 )
1776 max_rect->y2 = cur_rect->y2;
1781 icvMaxRoi1( _CvRect16u * max_rect, int x, int y )
1783 if( max_rect->x2 == 0 )
1785 max_rect->x1 = (ushort) x;
1786 max_rect->y1 = (ushort) y;
1791 max_rect->x2 = (ushort) x;
1792 max_rect->y2 = (ushort) y;
1796 if( max_rect->x1 > x )
1797 max_rect->x1 = (ushort) x;
1798 if( max_rect->y1 > y )
1799 max_rect->y1 = (ushort) y;
1804 if( max_rect->x2 < x )
1805 max_rect->x2 = (ushort) x;
1806 if( max_rect->y2 < y )
1807 max_rect->y2 = (ushort) y;
1812 /*F///////////////////////////////////////////////////////////////////////////////////////
1813 // Name: cvPyrSegmentation
1815 // segments an image using pyramid-linking technique
1818 // src - source image
1819 // dst - destination image
1820 // comp - pointer to returned connected component sequence
1821 // storage - where the sequence is stored
1822 // level - maximal pyramid level
1823 // threshold1 - first threshold, affecting on detalization level when pyramid
1825 // threshold2 - second threshold - affects on final components merging.
1828 // Source and destination image must be equal types and channels
1831 cvPyrSegmentation( IplImage * src,
1833 CvMemStorage * storage,
1834 CvSeq ** comp, int level, double threshold1, double threshold2 )
1836 CvSize src_size, dst_size;
1837 uchar *src_data = 0;
1838 uchar *dst_data = 0;
1839 int src_step = 0, dst_step = 0;
1840 int thresh1 = cvRound( threshold1 );
1841 int thresh2 = cvRound( threshold2 );
1843 CV_FUNCNAME( "cvPyrSegmentation" );
1847 if( src->depth != IPL_DEPTH_8U )
1848 CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
1850 if( src->depth != dst->depth || src->nChannels != dst->nChannels )
1851 CV_ERROR( CV_StsBadArg, "src and dst have different formats" );
1853 cvGetRawData( src, &src_data, &src_step, &src_size );
1854 cvGetRawData( dst, &dst_data, &dst_step, &dst_size );
1856 if( src_size.width != dst_size.width ||
1857 src_size.height != dst_size.height )
1858 CV_ERROR( CV_StsBadArg, "src and dst have different ROIs" );
1860 switch (src->nChannels)
1863 IPPI_CALL( icvPyrSegmentation8uC1R( src_data, src_step,
1867 comp, storage, level, thresh1, thresh2 ));
1870 IPPI_CALL( icvPyrSegmentation8uC3R( src_data, src_step,
1874 comp, storage, level, thresh1, thresh2 ));
1877 CV_ERROR( CV_BadNumChannels, cvUnsupportedFormat );