From 4c1d07f53a3349f468833c9a3e874f52a2382950 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 28 Mar 2014 14:11:05 +0000 Subject: [PATCH] vips_hough uses vips_draw_image() to accumulate rather than vips_sum() ... 2x faster --- TODO | 7 +-- libvips/arithmetic/hough.c | 118 +++++++++++++++++-------------------- libvips/arithmetic/hough.h | 9 +-- 3 files changed, 56 insertions(+), 78 deletions(-) diff --git a/TODO b/TODO index f9f17dbc..59534fe8 100644 --- a/TODO +++ b/TODO @@ -1,13 +1,8 @@ - vips_draw_image() might need a direct mode? see vips_flood_direct() -- hough_line.c should have a main accumulator and use vips_draw_add() to add - threads to that - - big memory saving - - need call operation along a circle, see line draw -- use with vips_draw_add() to make amask image for each radius for +- use with vips_draw_add() to make a mask image for each radius for vips_hough_circle() diff --git a/libvips/arithmetic/hough.c b/libvips/arithmetic/hough.c index a435fc59..83e470d6 100644 --- a/libvips/arithmetic/hough.c +++ b/libvips/arithmetic/hough.c @@ -45,60 +45,13 @@ G_DEFINE_ABSTRACT_TYPE( VipsHough, vips_hough, VIPS_TYPE_STATISTIC ); -static int -vips_hough_build( VipsObject *object ) +static VipsImage * +vips_hough_new_accumulator( VipsHough *hough ) { - VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); - VipsStatistic *statistic = VIPS_STATISTIC( object ); - VipsHough *hough = (VipsHough *) object; - - VipsImage *out; - - /* Mono only, we use the bands dimension of the output image for - * a parameter. - */ - if( statistic->in ) - if( vips_check_mono( class->nickname, statistic->in ) ) - return( -1 ); - - if( VIPS_OBJECT_CLASS( vips_hough_parent_class )->build( object ) ) - return( -1 ); - - /* hough->threads should be an array of completed accumulators, and we - * should have noted one for each thread we started. - */ - g_assert( hough->threads ); - g_assert( hough->n_threads > 0 ); - g_assert( hough->n_threads == hough->ith ); - - if( vips_sum( hough->threads, &out, hough->n_threads, NULL ) ) - return( -1 ); - - g_object_set( object, - "out", out, - NULL ); - - return( 0 ); -} - -/* Build a new accumulator. - */ -static void * -vips_hough_start( VipsStatistic *statistic ) -{ - VipsHough *hough = (VipsHough *) statistic; VipsHoughClass *class = VIPS_HOUGH_GET_CLASS( hough ); + VipsStatistic *statistic = VIPS_STATISTIC( hough ); - VipsImage *accumulator; - - /* Make a note of the number of threads we start. - */ - hough->n_threads += 1; - - /* We assume that we don't start any more threads after the first stop - * is called. - */ - g_assert( !hough->threads ); + VipsImage *accumulator; accumulator = vips_image_new_buffer(); @@ -116,6 +69,49 @@ vips_hough_start( VipsStatistic *statistic ) memset( VIPS_IMAGE_ADDR( accumulator, 0, 0 ), 0, VIPS_IMAGE_SIZEOF_IMAGE( accumulator ) ); + return( accumulator ); +} + +static int +vips_hough_build( VipsObject *object ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + VipsStatistic *statistic = VIPS_STATISTIC( object ); + VipsHough *hough = (VipsHough *) object; + + VipsImage *out; + + /* Mono only, we use the bands dimension of the output image for + * a parameter. + */ + if( statistic->in ) + if( vips_check_mono( class->nickname, statistic->in ) ) + return( -1 ); + + if( !(out = vips_hough_new_accumulator( hough )) ) + return( -1 ); + g_object_set( object, + "out", out, + NULL ); + + if( VIPS_OBJECT_CLASS( vips_hough_parent_class )->build( object ) ) + return( -1 ); + + return( 0 ); +} + +/* Build a new accumulator. + */ +static void * +vips_hough_start( VipsStatistic *statistic ) +{ + VipsHough *hough = (VipsHough *) statistic; + + VipsImage *accumulator; + + if( !(accumulator = vips_hough_new_accumulator( hough )) ) + return( NULL ); + return( (void *) accumulator ); } @@ -127,20 +123,14 @@ vips_hough_stop( VipsStatistic *statistic, void *seq ) VipsImage *accumulator = (VipsImage *) seq; VipsHough *hough = (VipsHough *) statistic; - /* If this is the first stop, build the main accumulator array. We - * assume no more threads will start, see the assert above. - */ - if( !hough->threads ) - /* This will unref the accumulators automatically on dispose. - */ - hough->threads = (VipsImage **) - vips_object_local_array( VIPS_OBJECT( hough ), - hough->n_threads ); + if( vips_draw_image( hough->out, accumulator, 0, 0, + "mode", VIPS_COMBINE_MODE_ADD, + NULL ) ) { + g_object_unref( accumulator ); + return( -1 ); + } - g_assert( !hough->threads[hough->ith] ); - - hough->threads[hough->ith] = accumulator; - hough->ith += 1; + g_object_unref( accumulator ); return( 0 ); } diff --git a/libvips/arithmetic/hough.h b/libvips/arithmetic/hough.h index a3313bce..095ffe87 100644 --- a/libvips/arithmetic/hough.h +++ b/libvips/arithmetic/hough.h @@ -70,13 +70,6 @@ struct _VipsHough { int width; int height; - /* Each thread adds its accumulator image to this array on stop. - * ith is the index the ith thread places its image at. - */ - VipsImage **threads; - int n_threads; - int ith; - /* Sum the thread accumulators to here. */ VipsImage *out; @@ -86,7 +79,7 @@ struct _VipsHough { struct _VipsHoughClass { VipsStatisticClass parent_class; - /* Make a new accumulator image. + /* Init an accumulator image. */ VipsHoughInitAccumulator init_accumulator;