vips_hough_circle() added

This commit is contained in:
John Cupitt 2014-04-01 12:27:15 +01:00
parent a7e6c6e009
commit ee53b01886
8 changed files with 65 additions and 80 deletions

View File

@ -8,7 +8,6 @@
im_draw_smudge(), im_label_regions() as classes im_draw_smudge(), im_label_regions() as classes
- better rounding in vips_flatten() - better rounding in vips_flatten()
- VipsStatistic operations are sequential - VipsStatistic operations are sequential
- vipsthumbnail attaches main image metadata to embedded thumbnails
- vipsthumbnail has --rotate auto-rotate option - vipsthumbnail has --rotate auto-rotate option
- removed embedded thumbnail reader from vipsthumbnail: embedded thumbnails - removed embedded thumbnail reader from vipsthumbnail: embedded thumbnails
are too unlike the main image are too unlike the main image
@ -16,6 +15,7 @@
- add vips_sum() - add vips_sum()
- add vips_hough base class and vips_hough_line() - add vips_hough base class and vips_hough_line()
- add "mode" param to vips_draw_image() - add "mode" param to vips_draw_image()
- add vips_hough_circle()
6/3/14 started 7.38.6 6/3/14 started 7.38.6
- grey ramp minimum was wrong - grey ramp minimum was wrong

1
TODO
View File

@ -1,4 +1,3 @@
- hough_circle can use circle thing to incremet in circles
- test draw_mask on labq images - test draw_mask on labq images

View File

@ -5,6 +5,7 @@ libarithmetic_la_SOURCES = \
hough.c \ hough.c \
hough.h \ hough.h \
hough_line.c \ hough_line.c \
hough_circle.c \
abs.c \ abs.c \
complex.c \ complex.c \
deviate.c \ deviate.c \

View File

@ -708,6 +708,7 @@ vips_arithmetic_operation_init( void )
extern GType vips_hist_find_ndim_get_type( void ); extern GType vips_hist_find_ndim_get_type( void );
extern GType vips_hist_find_indexed_get_type( void ); extern GType vips_hist_find_indexed_get_type( void );
extern GType vips_hough_line_get_type( void ); extern GType vips_hough_line_get_type( void );
extern GType vips_hough_circle_get_type( void );
extern GType vips_project_get_type( void ); extern GType vips_project_get_type( void );
extern GType vips_profile_get_type( void ); extern GType vips_profile_get_type( void );
extern GType vips_measure_get_type( void ); extern GType vips_measure_get_type( void );
@ -745,6 +746,7 @@ vips_arithmetic_operation_init( void )
vips_hist_find_ndim_get_type(); vips_hist_find_ndim_get_type();
vips_hist_find_indexed_get_type(); vips_hist_find_indexed_get_type();
vips_hough_line_get_type(); vips_hough_line_get_type();
vips_hough_circle_get_type();
vips_project_get_type(); vips_project_get_type();
vips_profile_get_type(); vips_profile_get_type();
vips_measure_get_type(); vips_measure_get_type();

View File

@ -39,6 +39,7 @@
#include <string.h> #include <string.h>
#include <vips/vips.h> #include <vips/vips.h>
#include <vips/internal.h>
#include "statistic.h" #include "statistic.h"
#include "hough.h" #include "hough.h"
@ -60,7 +61,6 @@ static int
vips_hough_circle_build( VipsObject *object ) vips_hough_circle_build( VipsObject *object )
{ {
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
VipsHough *hough = (VipsHough *) object;
VipsHoughCircle *hough_circle = (VipsHoughCircle *) object; VipsHoughCircle *hough_circle = (VipsHoughCircle *) object;
if( !vips_object_argument_isset( object, "bands" ) ) if( !vips_object_argument_isset( object, "bands" ) )
@ -70,7 +70,7 @@ vips_hough_circle_build( VipsObject *object )
if( hough_circle->min_radius > hough_circle->max_radius ) { if( hough_circle->min_radius > hough_circle->max_radius ) {
vips_error( class->nickname, vips_error( class->nickname,
"%s", _( "parameters out of range" ) ); "%s", _( "parameters out of range" ) );
return( NULL ); return( -1 );
} }
if( VIPS_OBJECT_CLASS( vips_hough_circle_parent_class )-> if( VIPS_OBJECT_CLASS( vips_hough_circle_parent_class )->
@ -95,79 +95,47 @@ vips_hough_circle_init_accumulator( VipsHough *hough, VipsImage *accumulator )
} }
static inline void static inline void
vips_hough_circle_pel( VipsImage *accumulator, int band, int x, int y ) vips_hough_circle_vote_point( VipsImage *image, int x, int y, void *client )
{ {
VIPS_IMAGE_ADDR( accumulator, x, y )[band] += 1; guint *q = (guint *) VIPS_IMAGE_ADDR( image, x, y );
int r = *((int *) client);
g_assert( image->BandFmt == VIPS_FORMAT_UINT );
g_assert( x >= 0 );
g_assert( y >= 0 );
g_assert( x < image->Xsize );
g_assert( y < image->Xsize );
g_assert( r >= 0 );
g_assert( r < image->Bands );
q[r] += 1;
} }
static inline void /* Vote endpoints, with clip.
vips_hough_circle_pel_clip( VipsImage *accumulator, int band, int x, int y ) */
static void
vips_hough_circle_vote_endpoints_clip( VipsImage *image,
int y, int x1, int x2, void *client )
{ {
if( x >= 0 && if( y >= 0 &&
x < accumulator->Xsize && y < image->Ysize ) {
y >= 0 && if( x1 >=0 &&
y < accumulator->Ysize ) x1 < image->Xsize )
VIPS_IMAGE_ADDR( accumulator, x, y )[band] += 1; vips_hough_circle_vote_point( image, x1, y, client );
} if( x2 >=0 &&
x2 < image->Xsize )
static void vips_hough_circle_vote_point( image, x2, y, client );
vips_hough_circle_octants( VipsImage *accumulator,
gboolean noclip, int band,
int cx, int cy, int x, int y )
{
if( noclip ) {
vips_hough_circle_pel( accumulator, band, cx + y, cy - x );
vips_hough_circle_pel( accumulator, band, cx + y, cy + x );
vips_hough_circle_pel( accumulator, band, cx - y, cy - x );
vips_hough_circle_pel( accumulator, band, cx - y, cy + x );
vips_hough_circle_pel( accumulator, band, cx + x, cy - y );
vips_hough_circle_pel( accumulator, band, cx + x, cy + y );
vips_hough_circle_pel( accumulator, band, cx - x, cy - y );
vips_hough_circle_pel( accumulator, band, cx - x, cy + y );
}
else {
vips_hough_circle_pel_clip( accumulator, band, cx + y, cy - x );
vips_hough_circle_pel_clip( accumulator, band, cx + y, cy + x );
vips_hough_circle_pel_clip( accumulator, band, cx - y, cy - x );
vips_hough_circle_pel_clip( accumulator, band, cx - y, cy + x );
vips_hough_circle_pel_clip( accumulator, band, cx + x, cy - y );
vips_hough_circle_pel_clip( accumulator, band, cx + x, cy + y );
vips_hough_circle_pel_clip( accumulator, band, cx - x, cy - y );
vips_hough_circle_pel_clip( accumulator, band, cx - x, cy + y );
} }
} }
static void /* Vote endpoints, no clip.
vips_hough_circle_draw( VipsHoughCircle *hough_circle, */
VipsImage *accumulator, int cx, int cy, int radius ) static void
vips_hough_circle_vote_endpoints_noclip( VipsImage *image,
int y, int x1, int x2, void *client )
{ {
int bands = hough_circle->bands; vips_hough_circle_vote_point( image, x1, y, client );
int band = bands * (radius - hough_circle->min_band) / bands; vips_hough_circle_vote_point( image, x2, y, client );
gboolean noclip;
int x, y, d;
noclip = cx - radius >= 0 &&
cx + radius < accumulator->Xsize &&
cy - radius >= 0 &&
cy + radius < accumulator->Ysize;
y = radius;
d = 3 - 2 * radius;
for( x = 0; x < y; x++ ) {
vips_draw_circle_octants( accumulator, noclip, band, x, y );
if( d < 0 )
d += 4 * x + 6;
else {
d += 4 * (x - y) + 10;
y--;
}
}
if( x == y )
vips_draw_circle_octants( accumulator, noclip, band, x, y );
} }
/* Cast votes for all possible circles passing through x, y. /* Cast votes for all possible circles passing through x, y.
@ -177,19 +145,31 @@ vips_hough_circle_vote( VipsHough *hough, VipsImage *accumulator, int x, int y )
{ {
VipsHoughCircle *hough_circle = (VipsHoughCircle *) hough; VipsHoughCircle *hough_circle = (VipsHoughCircle *) hough;
VipsStatistic *statistic = (VipsStatistic *) hough; VipsStatistic *statistic = (VipsStatistic *) hough;
double xd = (double) x / statistic->ready->Xsize; int min_radius = hough_circle->min_radius;
double yd = (double) y / statistic->ready->Ysize; int max_radius = hough_circle->max_radius;
int range = max_radius - min_radius;
int cx = x * accumulator->Xsize / statistic->ready->Xsize;
int cy = y * accumulator->Ysize / statistic->ready->Ysize;
int r; int r;
for( i = 0; i < hough->width; i++ ) { g_assert( range >= 0 );
int i90 = (i + hough->width / 4) % hough->width;
double r = xd * hough_circle->sin[i90] + yd * hough_circle->sin[i];
int ri = hough->height * r;
if( ri >= 0 && for( r = min_radius; r <= max_radius; r++ ) {
ri < hough->height ) int rb = (r - min_radius) * hough_circle->bands / (range + 1);
*VIPS_IMAGE_ADDR( accumulator, i, ri ) += 1;
VipsDrawScanline draw_scanline;
if( cx - r >= 0 &&
cx + r < accumulator->Xsize &&
cy - r >= 0 &&
cy + r < accumulator->Ysize )
draw_scanline = vips_hough_circle_vote_endpoints_noclip;
else
draw_scanline = vips_hough_circle_vote_endpoints_clip;
vips__draw_circle_direct( accumulator,
cx, cy, r, draw_scanline, &rb );
} }
} }
@ -253,6 +233,7 @@ vips_hough_circle_init( VipsHoughCircle *hough_circle )
* @height: vertical size of parameter space * @height: vertical size of parameter space
* @min_radius: smallest radius to search for * @min_radius: smallest radius to search for
* @max_radius: largest radius to search for * @max_radius: largest radius to search for
* @bands: number of bands (radii) in accumulator image
* *
* See also: * See also:
* *

View File

@ -68,7 +68,7 @@ vips_hough_line_build( VipsObject *object )
return( -1 ); return( -1 );
for( i = 0; i < hough->width; i++ ) for( i = 0; i < hough->width; i++ )
hough_line->sin[i] = sin( 2 * M_PI * i / hough->width ); hough_line->sin[i] = sin( 2 * VIPS_PI * i / hough->width );
if( VIPS_OBJECT_CLASS( vips_hough_line_parent_class )->build( object ) ) if( VIPS_OBJECT_CLASS( vips_hough_line_parent_class )->build( object ) )
return( -1 ); return( -1 );

View File

@ -128,7 +128,7 @@ static void
vips_draw_circle_draw_endpoints_clip( VipsImage *image, vips_draw_circle_draw_endpoints_clip( VipsImage *image,
int y, int x1, int x2, void *client ) int y, int x1, int x2, void *client )
{ {
if( y > 0 && if( y >= 0 &&
y < image->Ysize ) { y < image->Ysize ) {
if( x1 >=0 && if( x1 >=0 &&
x1 < image->Xsize ) x1 < image->Xsize )

View File

@ -390,6 +390,8 @@ int vips_hist_find_indexed( VipsImage *in, VipsImage *index,
__attribute__((sentinel)); __attribute__((sentinel));
int vips_hough_line( VipsImage *in, VipsImage **out, ... ) int vips_hough_line( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_hough_circle( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_project( VipsImage *in, VipsImage **columns, VipsImage **rows, ... ) int vips_project( VipsImage *in, VipsImage **columns, VipsImage **rows, ... )
__attribute__((sentinel)); __attribute__((sentinel));
int vips_profile( VipsImage *in, VipsImage **columns, VipsImage **rows, ... ) int vips_profile( VipsImage *in, VipsImage **columns, VipsImage **rows, ... )