From 4f3b37ad04fdb83f0b51b46e5fd58d5c01d7f47f Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Fri, 23 May 2014 13:46:38 +0100 Subject: [PATCH] wrap im_match*() as a class --- ChangeLog | 2 +- TODO | 4 +- libvips/include/vips/mosaicing.h | 4 + libvips/mosaicing/match.c | 276 +++++++++++++++++++++++++------ libvips/mosaicing/mosaic.c | 4 +- libvips/mosaicing/mosaicing.c | 2 + 6 files changed, 238 insertions(+), 54 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1e8377b8..7f5bc6b0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -33,7 +33,7 @@ - added im_tile_cache_random() to help nip2 - added hough_circle() to vips7 C++ API - added Travis CI config, thanks Lovell -- im_*merge(), im_*mosaic() redone as classes +- im_*merge(), im_*mosaic(), im_match*() redone as classes 6/3/14 started 7.38.6 - grey ramp minimum was wrong diff --git a/TODO b/TODO index b031713f..3e099efe 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ +- test vips_match() - quickly wrap the useful bits of mosaicing/ @@ -5,10 +6,9 @@ im_*merge() done im_*mosaic() done + im_match_linear*() done im_global_balancef() im_remosaic() - im_match_linear() - im_match_linear_search() - can we use postbuild elsewhere? look at use of "preclose" / "written", etc. diff --git a/libvips/include/vips/mosaicing.h b/libvips/include/vips/mosaicing.h index 57f9f6b8..03369801 100644 --- a/libvips/include/vips/mosaicing.h +++ b/libvips/include/vips/mosaicing.h @@ -44,6 +44,10 @@ int vips_merge( VipsImage *ref, VipsImage *sec, VipsImage **out, int vips_mosaic( VipsImage *ref, VipsImage *sec, VipsImage **out, VipsDirection direction, int xref, int yref, int xsec, int ysec, ... ) __attribute__((sentinel)); +int vips_match( VipsImage *ref, VipsImage *sec, VipsImage **out, + int xr1, int yr1, int xs1, int ys1, + int xr2, int yr2, int xs2, int ys2, ... ) + __attribute__((sentinel)); diff --git a/libvips/mosaicing/match.c b/libvips/mosaicing/match.c index c310bef7..94b5d61b 100644 --- a/libvips/mosaicing/match.c +++ b/libvips/mosaicing/match.c @@ -90,26 +90,6 @@ im__coeff( int xr1, int yr1, int xs1, int ys1, return( 0 ); } -/** - * im_match_linear: - * @ref: reference image - * @sec: secondary image - * @out: output image - * @xr1: first reference tie-point - * @yr1: first reference tie-point - * @xs1: first secondary tie-point - * @ys1: first secondary tie-point - * @xr2: second reference tie-point - * @yr2: second reference tie-point - * @xs2: second secondary tie-point - * @ys2: second secondary tie-point - * - * Scale, rotate and translate @sec so that the tie-points line up. - * - * See also: im_match_linear_search(). - * - * Returns: 0 on success, -1 on error - */ int im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out, int xr1, int yr1, int xs1, int ys1, @@ -140,35 +120,6 @@ im_match_linear( IMAGE *ref, IMAGE *sec, IMAGE *out, return( 0 ); } - -/** - * im_match_linear_search: - * @ref: reference image - * @sec: secondary image - * @out: output image - * @xr1: first reference tie-point - * @yr1: first reference tie-point - * @xs1: first secondary tie-point - * @ys1: first secondary tie-point - * @xr2: second reference tie-point - * @yr2: second reference tie-point - * @xs2: second secondary tie-point - * @ys2: second secondary tie-point - * @hwindowsize: half window size - * @hsearchsize: half search size - * - * Scale, rotate and translate @sec so that the tie-points line up. - * - * Before performing the transformation, the tie-points are improved by - * searching an area of @sec of size @hsearchsize for a - * match of size @hwindowsize to @ref. - * - * This function will only work well for small rotates and scales. - * - * See also: im_match_linear(). - * - * Returns: 0 on success, -1 on error - */ int im_match_linear_search( IMAGE *ref, IMAGE *sec, IMAGE *out, int xr1, int yr1, int xs1, int ys1, @@ -189,3 +140,230 @@ im_match_linear_search( IMAGE *ref, IMAGE *sec, IMAGE *out, return( 0 ); } + +typedef struct { + VipsOperation parent_instance; + + VipsImage *ref; + VipsImage *sec; + VipsImage *out; + int xr1; + int yr1; + int xs1; + int ys1; + int xr2; + int yr2; + int xs2; + int ys2; + int hwindow; + int harea; + gboolean search; + +} VipsMatch; + +typedef VipsOperationClass VipsMatchClass; + +G_DEFINE_TYPE( VipsMatch, vips_match, VIPS_TYPE_OPERATION ); + +static int +vips_match_build( VipsObject *object ) +{ + VipsMatch *match = (VipsMatch *) object; + + g_object_set( match, "out", vips_image_new(), NULL ); + + if( VIPS_OBJECT_CLASS( vips_match_parent_class )->build( object ) ) + return( -1 ); + + if( match->search ) { + int xs3, ys3; + int xs4, ys4; + double cor1, cor2; + + if( im_correl( match->ref, match->sec, + match->xr1, match->yr1, match->xs1, match->ys1, + match->hwindow, match->harea, + &cor1, &xs3, &ys3 ) ) + return( -1 ); + if( im_correl( match->ref, match->sec, + match->xr2, match->yr2, match->xs2, match->ys2, + match->hwindow, match->harea, + &cor2, &xs4, &ys4 ) ) + return( -1 ); + match->xs1 = xs3; + match->ys1 = ys3; + match->xs2 = xs4; + match->ys2 = ys4; + } + + if( im_match_linear( match->ref, match->sec, match->out, + match->xr1, match->yr1, match->xs1, match->ys1, + match->xr2, match->yr2, match->xs2, match->ys2 ) ) + return( -1 ); + + return( 0 ); +} + +static void +vips_match_class_init( VipsMatchClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *object_class = (VipsObjectClass *) class; + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + object_class->nickname = "match"; + object_class->description = _( "first-order match of two images" ); + object_class->build = vips_match_build; + + VIPS_ARG_IMAGE( class, "ref", 1, + _( "Reference" ), + _( "Reference image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, ref ) ); + + VIPS_ARG_IMAGE( class, "sec", 2, + _( "Secondary" ), + _( "Secondary image" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, sec ) ); + + VIPS_ARG_IMAGE( class, "out", 3, + _( "Output" ), + _( "Output image" ), + VIPS_ARGUMENT_REQUIRED_OUTPUT, + G_STRUCT_OFFSET( VipsMatch, out ) ); + + VIPS_ARG_INT( class, "xr1", 5, + _( "xr1" ), + _( "Position of first reference tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, xr1 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "yr1", 6, + _( "yr1" ), + _( "Position of first reference tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, yr1 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "xs1", 7, + _( "xs1" ), + _( "Position of first secondary tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, xs1 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "ys1", 8, + _( "ys1" ), + _( "Position of first secondary tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, ys1 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "xr2", 9, + _( "xr2" ), + _( "Position of second reference tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, xr2 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "yr2", 10, + _( "yr2" ), + _( "Position of second reference tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, yr2 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "xs2", 11, + _( "xs2" ), + _( "Position of second secondary tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, xs2 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "ys2", 12, + _( "ys2" ), + _( "Position of second secondary tie-point" ), + VIPS_ARGUMENT_REQUIRED_INPUT, + G_STRUCT_OFFSET( VipsMatch, ys2 ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "hwindow", 13, + _( "hwindow" ), + _( "Half window size" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsMatch, hwindow ), + 0, 1000000000, 1 ); + + VIPS_ARG_INT( class, "harea", 14, + _( "harea" ), + _( "Half area size" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsMatch, harea ), + 0, 1000000000, 1 ); + + VIPS_ARG_BOOL( class, "search", 13, + _( "search" ), + _( "Search to improve tie-points" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsMatch, search ), + FALSE ); + +} + +static void +vips_match_init( VipsMatch *match ) +{ + match->hwindow = 5; + match->harea = 15; + match->search = FALSE; +} + +/** + * vips_match: + * @ref: reference image + * @sec: secondary image + * @out: output image + * @xr1: first reference tie-point + * @yr1: first reference tie-point + * @xs1: first secondary tie-point + * @ys1: first secondary tie-point + * @xr2: second reference tie-point + * @yr2: second reference tie-point + * @xs2: second secondary tie-point + * @ys2: second secondary tie-point + * + * Optional arguments: + * + * @search: search to improve tie-points + * @hwindow: half window size + * @harea: half search size + * + * Scale, rotate and translate @sec so that the tie-points line up. + * + * If @search is %TRUE, before performing the transformation, the tie-points + * are improved by searching an area of @sec of size @harea for a + * match of size @hwindow to @ref. + * + * This function will only work well for small rotates and scales. + * + * Returns: 0 on success, -1 on error + */ +int +vips_match( VipsImage *ref, VipsImage *sec, VipsImage **out, + int xr1, int yr1, int xs1, int ys1, + int xr2, int yr2, int xs2, int ys2, ... ) +{ + va_list ap; + int result; + + va_start( ap, ys2 ); + result = vips_call_split( "match", ap, ref, sec, out, + xr1, yr1, xs1, ys1, xr2, yr2, xs2, ys2 ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/mosaicing/mosaic.c b/libvips/mosaicing/mosaic.c index ce4bf8f6..962f6f6b 100644 --- a/libvips/mosaicing/mosaic.c +++ b/libvips/mosaicing/mosaic.c @@ -208,14 +208,14 @@ vips_mosaic_class_init( VipsMosaicClass *class ) VIPS_ARG_INT( class, "xsec", 7, _( "xsec" ), - _( "Position of reference tie-point" ), + _( "Position of secondary tie-point" ), VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsMosaic, xsec ), 0, 1000000000, 1 ); VIPS_ARG_INT( class, "ysec", 8, _( "ysec" ), - _( "Position of reference tie-point" ), + _( "Position of secondary tie-point" ), VIPS_ARGUMENT_REQUIRED_INPUT, G_STRUCT_OFFSET( VipsMosaic, ysec ), 0, 1000000000, 1 ); diff --git a/libvips/mosaicing/mosaicing.c b/libvips/mosaicing/mosaicing.c index 47098262..3d23be8f 100644 --- a/libvips/mosaicing/mosaicing.c +++ b/libvips/mosaicing/mosaicing.c @@ -97,7 +97,9 @@ vips_mosaicing_operation_init( void ) { extern int vips_merge_get_type( void ); extern int vips_mosaic_get_type( void ); + extern int vips_match_get_type( void ); vips_merge_get_type(); vips_mosaic_get_type(); + vips_match_get_type(); }