From 7164a2abec3c5f4b178729a62c814f93dba4ce49 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Tue, 29 Sep 2009 13:45:58 +0000 Subject: [PATCH] added im_segment() --- ChangeLog | 1 + libvips/include/vips/proto.h | 5 ++-- libvips/inplace/im_flood_other.c | 48 ++++++++++++++++++++++++++++-- libvips/inplace/inplace_dispatch.c | 32 ++++++++++++++++++++ 4 files changed, 81 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 28ee3924..f80a3510 100644 --- a/ChangeLog +++ b/ChangeLog @@ -49,6 +49,7 @@ and else parts - better im_check() functions - added im_flood_other() as start of simple segmentation operator +- added im_segment() 25/3/09 started 7.18.0 - revised version numbers diff --git a/libvips/include/vips/proto.h b/libvips/include/vips/proto.h index e66b2863..8c38e8bc 100644 --- a/libvips/include/vips/proto.h +++ b/libvips/include/vips/proto.h @@ -620,8 +620,9 @@ int im_flood( IMAGE *, int, int, PEL *, Rect * ); int im_flood_blob( IMAGE *, int, int, PEL *, Rect * ); int im_flood_blob_copy( IMAGE *in, IMAGE *out, int x, int y, PEL *ink ); int im_flood_other( IMAGE *mask, IMAGE *test, int x, int y, int serial ); -int im_flood_other_copy( IMAGE *mask, IMAGE *out, - IMAGE *test, int x, int y, int serial ); +int im_flood_other_copy( IMAGE *mask, IMAGE *test, IMAGE *out, + int x, int y, int serial ); +int im_segment( IMAGE *test, IMAGE *mask, int *segments ); int im_lineset( IMAGE *in, IMAGE *out, IMAGE *mask, IMAGE *ink, int n, int *x1v, int *y1v, int *x2v, int *y2v ); diff --git a/libvips/inplace/im_flood_other.c b/libvips/inplace/im_flood_other.c index 164bb247..4518cf8b 100644 --- a/libvips/inplace/im_flood_other.c +++ b/libvips/inplace/im_flood_other.c @@ -275,7 +275,7 @@ im_flood_other( IMAGE *mask, IMAGE *test, int x, int y, int serial ) if( im_check_known_coded( "im_flood_other", test ) || im_check_uncoded( "im_flood_other", mask ) || im_check_mono( "im_flood_other", mask ) || - im_check_int( "im_flood_other", mask ) || + im_check_format( "im_flood_other", mask, IM_BANDFMT_INT ) || im_check_same_size( "im_flood_other", test, mask ) ) return( -1 ); @@ -315,8 +315,8 @@ im_flood_other( IMAGE *mask, IMAGE *test, int x, int y, int serial ) * automatically. Maybe nip could do it if it sees a RW image argument? */ int -im_flood_other_copy( IMAGE *mask, IMAGE *out, - IMAGE *test, int x, int y, int serial ) +im_flood_other_copy( IMAGE *mask, IMAGE *test, IMAGE *out, + int x, int y, int serial ) { IMAGE *t; @@ -329,4 +329,46 @@ im_flood_other_copy( IMAGE *mask, IMAGE *out, return( 0 ); } +/* Now: segment with im_flood_other(). + */ +int +im_segment( IMAGE *test, IMAGE *mask, int *segments ) +{ + IMAGE *t[2]; + int serial; + int x, y; + + /* Create the mask image. + */ + if( im_open_local_array( mask, t, 2, "im_segment", "p" ) || + im_black( t[0], test->Xsize, test->Ysize, 1 ) || + im_clip2fmt( t[0], t[1], IM_BANDFMT_INT ) ) + return( 0 ); + + /* Search the mask image, flooding as we find zero pixels. + */ + if( im_incheck( t[1] ) ) + return( -1 ); + serial = 0; + for( y = 0; y < test->Ysize; y++ ) + for( x = 0; x < test->Xsize; x++ ) { + int *m = (int *) t[1]->data + x + y * test->Ysize; + + if( !*m ) { + if( im_flood_other( t[1], test, x, y, serial ) ) + return( -1 ); + + serial += 1; + } + } + + /* Copy result to mask. + */ + if( im_copy( t[1], mask ) ) + return( -1 ); + if( segments ) + *segments = serial; + + return( 0 ); +} diff --git a/libvips/inplace/inplace_dispatch.c b/libvips/inplace/inplace_dispatch.c index 18871f0c..53fe72cc 100644 --- a/libvips/inplace/inplace_dispatch.c +++ b/libvips/inplace/inplace_dispatch.c @@ -295,6 +295,37 @@ static im_function flood_other_copy_desc = { flood_other_copy_args /* Arg list */ }; +/* Args for im_segment(). + */ +static im_arg_desc segment_args[] = { + IM_INPUT_IMAGE( "test" ), + IM_OUTPUT_IMAGE( "mask" ), + IM_OUTPUT_INT( "segments" ) +}; + +/* Call im_segment() via arg vector. + */ +static int +segment_vec( im_object *argv ) +{ + IMAGE *test = argv[1]; + IMAGE *mask = argv[0]; + int *serial = (int *) argv[5]; + + return( im_segment( test, mask, serial ) ); +} + +/* Description of im_segment(). + */ +static im_function segment_desc = { + "im_segment", /* Name */ + "number continuous regions in an image", + 0, /* Flags */ + segment_vec, /* Dispatch function */ + IM_NUMBER( segment_args ),/* Size of arg list */ + segment_args /* Arg list */ +}; + /* To do: * these all need some kind of pel type * @@ -313,6 +344,7 @@ static im_function *inplace_list[] = { &circle_desc, &flood_blob_copy_desc, &flood_other_copy_desc, + &segment_desc, &insertplace_desc, &line_desc, &lineset_desc