📄 cvpyrsegmentation.cpp
字号:
p_cur[j].c /= a;
}
cmp_node.data = p_cur + j;
CV_WRITE_SEQ_ELEM( cmp_node, writer );
}
else
{
p_cur[j].c = p_prev->c;
}
if( l == 0 )
{
p_prev = _CV_NEXT_BASE_C1(p_prev, (j * 2 < step - 2 ? 2 : 1));
}
else
{
p_prev++;
}
}
}
if( l + 1 == level && !is_last_iter )
for( j = 0; j <= size.width; j++ )
p_cur[j].a = 0;
if( !(i & 1) )
{
p_prev = p_row_prev;
}
else
{
p_prev = (_CvPyramid*)((char*)p_row_prev + step *
(l == 0 ? sizeof(_CvPyramidBase) : sizeof(_CvPyramid)));
}
}
}
} /* end of the iteration process */
/* construct a connected components */
size.width = roi.width >> level;
size.height = roi.height >> level;
p_cur = pyram[level];
for( i = 0; i < size.height; i++, p_cur += size.width + 1 )
{
for( j = 0; j < size.width; j++ )
{
if( p_cur[j].a != 0 )
{
cmp_node.data = p_cur + j;
CV_WRITE_SEQ_ELEM( cmp_node, writer );
}
}
}
cvEndWriteSeq( &writer );
/* clusterization segmented components and construction
output connected components */
icvSegmentClusterC1( cmp_seq, res_seq, threshold2, pyram[1], roi );
/* convert (inplace) resultant segment values to int (top level) */
/* propagate segment values top down */
for( l = level - 1; l >= 0; l-- )
{
p_cur = pyram[l];
size.width <<= 1;
size.height <<= 1;
if( l == 0 )
{
size.width--;
size.height--;
}
for( i = 0; i <= size.height; i++ )
{
for( j = 0; j <= size.width; j++ )
{
_CvPyramid *p = p_cur->p;
assert( p != 0 );
if( p != &stub )
p_cur->c = p->c;
if( l == 0 )
{
Cv32suf _c;
/* copy the segmented values to destination image */
_c.f = p_cur->c; dst_image[j] = (uchar)_c.i;
p_cur = _CV_NEXT_BASE_C1(p_cur, 1);
}
else
{
p_cur++;
}
}
if( l == 0 )
dst_image += dst_step;
}
}
M_END:
cvFree( &buffer );
cvReleaseMemStorage( &temp_storage );
if( status == CV_OK )
*dst_comp = res_seq;
return status;
}
/****************************************************************************************\
color!!! image segmentation by pyramid-linking
\****************************************************************************************/
static CvStatus
icvPyrSegmentation8uC3R( uchar * src_image, int src_step,
uchar * dst_image, int dst_step,
CvSize roi, CvFilter filter,
CvSeq ** dst_comp, CvMemStorage * storage,
int level, int threshold1, int threshold2 )
{
int i, j, l;
int step;
const int max_iter = 3; /* maximum number of iterations */
int cur_iter = 0; /* current iteration */
_CvPyramidC3 *pyram[16]; /* pointers to the pyramid down up to level */
float *pyramida = 0;
_CvPyramidC3 stub;
_CvPyramidC3 *p_cur;
_CvPyramidBaseC3 *p_base;
_CvListNode cmp_node;
CvSeq *cmp_seq = 0;
CvSeq *res_seq = 0;
CvMemStorage *temp_storage = 0;
CvSize size;
CvStatus status;
CvSeqWriter writer;
int buffer_size;
char *buffer = 0;
status = CV_OK;
threshold1 *= _CV_RGB_THRESH_SCALE;
threshold2 *= _CV_RGB_THRESH_SCALE;
/* clear pointer to resultant sequence */
if( dst_comp )
*dst_comp = 0;
/* check args */
if( !src_image || !dst_image || !storage || !dst_comp )
return CV_NULLPTR_ERR;
if( roi.width <= 0 || roi.height <= 0 ||
src_step < roi.width * 3 || dst_step < roi.width * 3 ) return CV_BADSIZE_ERR;
if( filter != CV_GAUSSIAN_5x5 )
return CV_BADRANGE_ERR;
if( threshold1 < 0 || threshold2 < 0 )
return CV_BADRANGE_ERR;
if( level <= 0 )
return CV_BADRANGE_ERR;
if( ((roi.width | roi.height) & ((1 << level) - 1)) != 0 )
return CV_BADCOEF_ERR;
temp_storage = cvCreateChildMemStorage( storage );
/* sequence for temporary components */
cmp_seq = cvCreateSeq( 0, sizeof( CvSeq ), sizeof( _CvListNode ), temp_storage );
assert( cmp_seq != 0 );
res_seq = cvCreateSeq( CV_SEQ_CONNECTED_COMP, sizeof( CvSeq ),
sizeof( CvConnectedComp ), storage );
assert( res_seq != 0 );
/* calculate buffer size */
buffer_size = roi.width * roi.height * (sizeof( _CvRGBf ) + sizeof( _CvPyramidBaseC3 ));
for( l = 1; l <= level; l++ )
buffer_size += ((roi.width >> l) + 1) * ((roi.height >> l) + 1) * sizeof(_CvPyramidC3);
/* allocate buffer */
buffer = (char *) cvAlloc( buffer_size );
if( !buffer )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
pyramida = (float *) buffer;
/* initialization pyramid-linking properties down up to level */
step = roi.width * sizeof( _CvRGBf );
{
CvMat _src;
CvMat _pyramida;
cvInitMatHeader( &_src, roi.height, roi.width, CV_8UC3, src_image, src_step );
cvInitMatHeader( &_pyramida, roi.height, roi.width, CV_32FC3, pyramida, step );
cvConvert( &_src, &_pyramida );
/*_CV_CHECK( icvCvtTo_32f_C1R( src_image, src_step, pyramida, step,
cvSize( roi.width * 3, roi.height ), CV_8UC1 ));*/
}
p_base = (_CvPyramidBaseC3 *) (buffer + step * roi.height);
pyram[0] = (_CvPyramidC3 *) p_base;
/* fill base level of pyramid */
for( i = 0; i < roi.height; i++ )
{
for( j = 0; j < roi.width; j++, p_base++ )
{
p_base->c = ((_CvRGBf *) pyramida)[i * roi.width + j];
p_base->p = &stub;
}
}
p_cur = (_CvPyramidC3 *) p_base;
size = roi;
/* calculate initial pyramid */
for( l = 1; l <= level; l++ )
{
CvSize dst_size = { size.width/2 + 1, size.height/2 + 1 };
CvMat prev_level = cvMat( size.height, size.width, CV_32FC3 );
CvMat next_level = cvMat( dst_size.height, dst_size.width, CV_32FC3 );
cvSetData( &prev_level, pyramida, step );
cvSetData( &next_level, pyramida, step );
cvPyrDown( &prev_level, &next_level );
//_CV_CHECK( icvPyrDown_Gauss5x5_32f_C3R( pyramida, step, pyramida, step, size, buff ));
//_CV_CHECK( icvPyrDownBorder_32f_CnR( pyramida, step, size, pyramida, step, dst_size, 3 ));
pyram[l] = p_cur;
size.width = dst_size.width - 1;
size.height = dst_size.height - 1;
/* fill layer #l */
for( i = 0; i <= size.height; i++ )
{
assert( (char*)p_cur - buffer < buffer_size );
for( j = 0; j <= size.width; j++, p_cur++ )
{
p_cur->c = ((_CvRGBf *) pyramida)[i * roi.width + j];
p_cur->p = &stub;
p_cur->a = 0;
p_cur->rect.x2 = 0;
}
}
}
cvStartAppendToSeq( cmp_seq, &writer );
/* do several iterations to determine son-father links */
for( cur_iter = 0; cur_iter < max_iter; cur_iter++ )
{
int is_last_iter = cur_iter == max_iter - 1;
size = roi;
/* build son-father links down up to level */
for( l = 0; l < level; l++ )
{
icvUpdatePyrLinks_8u_C3( l, pyram[l], size, pyram[l + 1], &writer,
(float) threshold1, is_last_iter, &stub,
(CvWriteNodeFunction)icvWritePyrNode );
/* clear last border row */
if( l > 0 )
{
p_cur = pyram[l] + (size.width + 1) * size.height;
for( j = 0; j <= size.width; j++ )
p_cur[j].c.blue = p_cur[j].c.green = p_cur[j].c.red = 0;
}
size.width >>= 1;
size.height >>= 1;
}
/* clear the old c value for the last level */
p_cur = pyram[level];
for( i = 0; i <= size.height; i++, p_cur += size.width + 1 )
for( j = 0; j <= size.width; j++ )
p_cur[j].c.blue = p_cur[j].c.green = p_cur[j].c.red = 0;
size = roi;
step = roi.width;
/* calculate average c value for the 0 < l <=level */
for( l = 0; l < level; l++, step = (step >> 1) + 1 )
{
_CvPyramidC3 *p_prev, *p_row_prev;
stub.c.blue = stub.c.green = stub.c.red = 0;
/* calculate average c value for the next level */
if( l == 0 )
{
p_base = (_CvPyramidBaseC3 *) pyram[0];
for( i = 0; i < roi.height; i++, p_base += size.width )
{
for( j = 0; j < size.width; j++ )
{
_CvPyramidC3 *p = p_base[j].p;
p->c.blue += p_base[j].c.blue;
p->c.green += p_base[j].c.green;
p->c.red += p_base[j].c.red;
}
}
}
else
{
p_cur = pyram[l];
for( i = 0; i < size.height; i++, p_cur += size.width + 1 )
{
for( j = 0; j < size.width; j++ )
{
_CvPyramidC3 *p = p_cur[j].p;
float a = (float) p_cur[j].a;
p->c.blue += a * p_cur[j].c.blue;
p->c.green += a * p_cur[j].c.green;
p->c.red += a * p_cur[j].c.red;
if( !is_last_iter )
p_cur[j].a = 0;
}
if( !is_last_iter )
p_cur[size.width].a = 0;
}
if( !is_last_iter )
{
for( j = 0; j <= size.width; j++ )
{
p_cur[j].a = 0;
}
}
}
/* assign random values of the next level null c */
p_cur = pyram[l + 1];
p_row_prev = p_prev = pyram[l];
size.width >>= 1;
size.height >>= 1;
for( i = 0; i <= size.height; i++, p_cur += size.width + 1 )
{
if( i < size.height || !is_last_iter )
{
for( j = 0; j < size.width; j++ )
{
int a = p_cur[j].a;
if( a != 0 )
{
float inv_a;
if( a <= _CV_INV_TAB_SIZE )
{
inv_a = icvInvTab[a - 1];
}
else
{
inv_a = 1.f / a;
}
p_cur[j].c.blue *= inv_a;
p_cur[j].c.green *= inv_a;
p_cur[j].c.red *= inv_a;
}
else
{
p_cur[j].c = p_prev->c;
}
if( l == 0 )
p_prev = _CV_NEXT_BASE_C3( p_prev, 2 );
else
p_prev += 2;
}
if( p_cur[size.width].a == 0 )
{
p_cur[size.width].c = p_prev[(l != 0) - 1].c;
}
else
{
p_cur[size.width].c.blue /= p_cur[size.width].a;
p_cur[size.width].c.green /= p_cur[size.width].a;
p_cur[size.width].c.red /= p_cur[size.width].a;
if( is_last_iter )
{
cmp_node.data = p_cur + size.width;
CV_WRITE_SEQ_ELEM( cmp_node, writer );
}
}
}
else
{
for( j = 0; j <= size.width; j++ )
{
int a = p_cur[j].a;
if( a != 0 )
{
float inv_a;
if( a <= _CV_INV_TAB_SIZE )
{
inv_a = icvInvTab[a - 1];
}
else
{
inv_a = 1.f / a;
}
p_cur[j].c.blue *= inv_a;
p_cur[j].c.green *= inv_a;
p_cur[j].c.red *= inv_a;
cmp_node.data = p_cur + j;
CV_WRITE_SEQ_ELEM( cmp_node, writer );
}
else
{
p_cur[j].c = p_prev->c;
}
if( l == 0 )
{
p_prev = _CV_NEXT_BASE_C3( p_prev, (j * 2 < step - 2 ? 2 : 1));
}
else
{
p_prev++;
}
}
}
if( l + 1 == level && !is_last_iter )
for( j = 0; j <= size.width; j++ )
p_cur[j].a = 0;
if( !(i & 1) )
{
p_prev = p_row_prev;
}
else
{
p_prev = (_CvPyramidC3*)((char*)p_row_prev + step *
(l == 0 ? sizeof( _CvPyramidBaseC3 ) : sizeof( _CvPyramidC3 )));
}
}
}
} /* end of the iteration process */
/* construct a connected components */
size.width = roi.width >> level;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -