almost done compass

This commit is contained in:
John Cupitt 2013-10-24 14:46:08 +01:00
parent 4d724c0023
commit e74a0b71d9
9 changed files with 234 additions and 37 deletions

7
TODO
View File

@ -1,5 +1,12 @@
- started compass .. convolution with a rotating mask
vips im_gradient k2.jpg x.v line.mat
vips compass k2.jpg x2.v line.mat --times 2 --angle 90 --combine sum
should give the same result, you'd think
deprecated/vips7compat.c defs for compass/grad/lindet commented out for now
need to do sep
- do conv and morph quickly as simple wrappers over the vips7 operations

View File

@ -4,6 +4,7 @@ libconvolution_la_SOURCES = \
convolution.c \
pconvolution.h \
conv.c \
compass.c \
morph.c \
convol_dispatch.c \
im_addgnoise.c \

View File

@ -31,11 +31,6 @@
*/
/* This is a simple wrapper over the old vips7 functions. At some point we
* should rewrite this as a pure vips8 class and redo the vips7 functions as
* wrappers over this.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /*HAVE_CONFIG_H*/
@ -51,8 +46,11 @@ typedef struct {
VipsConvolution parent_instance;
int times;
VipsRotate45 angle;
int join;
VipsAngle45 angle;
VipsCombine combine;
VipsPrecision precision;
int layers;
int cluster;
} VipsCompass;
typedef VipsConvolutionClass VipsCompassClass;
@ -64,12 +62,73 @@ vips_compass_build( VipsObject *object )
{
VipsConvolution *convolution = (VipsConvolution *) object;
VipsCompass *compass = (VipsCompass *) object;
VipsImage **masks;
VipsImage *mask;
VipsImage **images;
int i;
VipsImage **abs;
VipsImage **combine;
VipsImage *x;
g_object_set( compass, "out", vips_image_new(), NULL );
if( VIPS_OBJECT_CLASS( vips_compass_parent_class )->build( object ) )
return( -1 );
masks = (VipsImage **)
vips_object_local_array( object, compass->times );
images = (VipsImage **)
vips_object_local_array( object, compass->times );
abs = (VipsImage **)
vips_object_local_array( object, compass->times );
combine = (VipsImage **)
vips_object_local_array( object, compass->times );
mask = convolution->M;
for( i = 0; i < compass->times; i++ ) {
if( vips_conv( convolution->in, &images[i], mask,
"precision", compass->precision,
"layers", compass->layers,
"cluster", compass->cluster,
NULL ) )
return( -1 );
if( vips_rot45( mask, &masks[i],
"angle", compass->angle,
NULL ) )
return( -1 );
mask = masks[i];
}
for( i = 0; i < compass->times; i++ )
if( vips_abs( images[i], &abs[i], NULL ) )
return( -1 );
switch( compass->combine ) {
case VIPS_COMBINE_MAX:
if( vips_bandrank( abs, &combine[0], compass->times,
"index", compass->times - 1,
NULL ) )
return( -1 );
x = combine[0];
break;
case VIPS_COMBINE_SUM:
x = abs[0];
for( i = 1; i < compass->times; i++ ) {
if( vips_add( x, abs[i], &combine[i], NULL ) )
return( -1 );
x = combine[i];
}
break;
default:
g_assert( 0 );
}
if( vips_image_write( x, convolution->out ) )
return( -1 );
return( 0 );
}
@ -86,21 +145,42 @@ vips_compass_class_init( VipsCompassClass *class )
object_class->description = _( "convolution operation" );
object_class->build = vips_compass_build;
VIPS_ARG_ENUM( class, "precision", 103,
VIPS_ARG_INT( class, "times", 101,
_( "Times" ),
_( "Rotate and convolve this many times" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCompass, times ),
1, 1000, 2 );
VIPS_ARG_ENUM( class, "angle", 103,
_( "Angle" ),
_( "Rotate mask by this much between convolutions" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCompass, angle ),
VIPS_TYPE_ANGLE45, VIPS_ANGLE45_90 );
VIPS_ARG_ENUM( class, "combine", 104,
_( "Combine" ),
_( "Combine convolution results like this" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCompass, combine ),
VIPS_TYPE_COMBINE, VIPS_COMBINE_MAX );
VIPS_ARG_ENUM( class, "precision", 203,
_( "Precision" ),
_( "Convolve with this precision" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCompass, precision ),
VIPS_TYPE_PRECISION, VIPS_PRECISION_INTEGER );
VIPS_ARG_INT( class, "layers", 104,
VIPS_ARG_INT( class, "layers", 204,
_( "Layers" ),
_( "Use this many layers in approximation" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsCompass, layers ),
1, 1000, 5 );
VIPS_ARG_INT( class, "cluster", 105,
VIPS_ARG_INT( class, "cluster", 205,
_( "Cluster" ),
_( "Cluster lines closer than this in approximation" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
@ -112,9 +192,12 @@ vips_compass_class_init( VipsCompassClass *class )
static void
vips_compass_init( VipsCompass *compass )
{
compass->times = 1;
compass->angle = 5;
compass->join = 1;
compass->times = 2;
compass->angle = VIPS_ANGLE45_90;
compass->combine = VIPS_COMBINE_MAX;
compass->precision = VIPS_PRECISION_INTEGER;
compass->layers = 5;
compass->cluster = 1;
}
int

View File

@ -127,7 +127,7 @@ vips_convolution_class_init( VipsConvolutionClass *class )
VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsConvolution, out ) );
VIPS_ARG_IMAGE( class, "mask", 102,
VIPS_ARG_IMAGE( class, "mask", 20,
_( "Mask" ),
_( "Input matrix image" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
@ -148,7 +148,9 @@ vips_convolution_operation_init( void )
{
extern int vips_conv_get_type( void );
extern int vips_morph_get_type( void );
extern int vips_compass_get_type( void );
vips_conv_get_type();
vips_morph_get_type();
vips_compass_get_type();
}

View File

@ -2088,6 +2088,82 @@ im_recomb( IMAGE *in, IMAGE *out, DOUBLEMASK *recomb )
return( 0 );
}
/*
int
im_compass( VipsImage *in, VipsImage *out, INTMASK *mask )
{
VipsImage *t1, *t2;
if( !(t1 = vips_image_new()) ||
im_imask2vips( mask, t1 ) )
return( -1 );
if( vips_compass( in, &t2, t1,
"times", 8,
NULL ) ) {
g_object_unref( t1 );
return( -1 );
}
g_object_unref( t1 );
if( vips_image_write( t2, out ) ) {
g_object_unref( t2 );
return( -1 );
}
g_object_unref( t2 );
return( 0 );
}
int
im_lindetect( IMAGE *in, IMAGE *out, INTMASK *mask )
{
VipsImage *t1, *t2;
if( !(t1 = vips_image_new()) ||
im_imask2vips( mask, t1 ) )
return( -1 );
if( vips_compass( in, &t2, t1,
"times", 4,
NULL ) ) {
g_object_unref( t1 );
return( -1 );
}
g_object_unref( t1 );
if( vips_image_write( t2, out ) ) {
g_object_unref( t2 );
return( -1 );
}
g_object_unref( t2 );
return( 0 );
}
int
im_gradient( IMAGE *in, IMAGE *out, INTMASK *mask )
{
VipsImage *t1, *t2;
if( !(t1 = vips_image_new()) ||
im_imask2vips( mask, t1 ) )
return( -1 );
if( vips_compass( in, &t2, t1,
"times", 2,
"angle", VIPS_ANGLE45_90,
"combine", VIPS_COMBINE_SUM,
NULL ) ) {
g_object_unref( t1 );
return( -1 );
}
g_object_unref( t1 );
if( vips_image_write( t2, out ) ) {
g_object_unref( t2 );
return( -1 );
}
g_object_unref( t2 );
return( 0 );
}
*/
static int
vips__round( VipsImage *in, VipsImage *out, VipsOperationRound round )
{

View File

@ -41,11 +41,40 @@ extern "C" {
typedef enum {
VIPS_PRECISION_INTEGER,
VIPS_PRECISION_FLOAT,
VIPS_PRECISION_APPROXIMATE
VIPS_PRECISION_APPROXIMATE,
VIPS_PRECISION_LAST
} VipsPrecision;
typedef enum {
VIPS_COMBINE_MAX,
VIPS_COMBINE_SUM,
VIPS_COMBINE_LAST
} VipsCombine;
/**
* VipsOperationMorphology:
* @VIPS_OPERATION_MORPHOLOGY_ERODE: true if all set
* @VIPS_OPERATION_MORPHOLOGY_DILATE: true if one set
*
* More like hit-miss, really.
*
* See also: vips_morph().
*/
typedef enum {
VIPS_OPERATION_MORPHOLOGY_ERODE,
VIPS_OPERATION_MORPHOLOGY_DILATE,
VIPS_OPERATION_MORPHOLOGY_LAST
} VipsOperationMorphology;
int vips_conv( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
__attribute__((sentinel));
int vips_compass( VipsImage *in, VipsImage **out, VipsImage *mask, ... )
__attribute__((sentinel));
int vips_morph( VipsImage *in, VipsImage **out, VipsImage *mask,
VipsOperationMorphology morph, ... )
__attribute__((sentinel));
void vips_convolution_operation_init( void );

View File

@ -74,7 +74,8 @@ GType vips_operation_flags_get_type (void) G_GNUC_CONST;
/* enumerations from "../../../libvips/include/vips/convolution.h" */
GType vips_precision_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_PRECISION (vips_precision_get_type())
/* enumerations from "../../../libvips/include/vips/morphology.h" */
GType vips_combine_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_COMBINE (vips_combine_get_type())
GType vips_operation_morphology_get_type (void) G_GNUC_CONST;
#define VIPS_TYPE_OPERATION_MORPHOLOGY (vips_operation_morphology_get_type())
/* enumerations from "../../../libvips/include/vips/object.h" */

View File

@ -38,26 +38,6 @@
extern "C" {
#endif /*__cplusplus*/
/**
* VipsOperationMorphology:
* @VIPS_OPERATION_MORPHOLOGY_ERODE: true if all set
* @VIPS_OPERATION_MORPHOLOGY_DILATE: true if one set
*
* More like hit-miss, really.
*
* See also: vips_morph().
*/
typedef enum {
VIPS_OPERATION_MORPHOLOGY_ERODE,
VIPS_OPERATION_MORPHOLOGY_DILATE,
VIPS_OPERATION_MORPHOLOGY_LAST
} VipsOperationMorphology;
int vips_morph( VipsImage *in, VipsImage **out, VipsImage *mask,
VipsOperationMorphology morph, ... )
__attribute__((sentinel));

View File

@ -625,6 +625,7 @@ vips_precision_get_type( void )
{VIPS_PRECISION_INTEGER, "VIPS_PRECISION_INTEGER", "integer"},
{VIPS_PRECISION_FLOAT, "VIPS_PRECISION_FLOAT", "float"},
{VIPS_PRECISION_APPROXIMATE, "VIPS_PRECISION_APPROXIMATE", "approximate"},
{VIPS_PRECISION_LAST, "VIPS_PRECISION_LAST", "last"},
{0, NULL, NULL}
};
@ -633,7 +634,24 @@ vips_precision_get_type( void )
return( etype );
}
/* enumerations from "../../libvips/include/vips/morphology.h" */
GType
vips_combine_get_type( void )
{
static GType etype = 0;
if( etype == 0 ) {
static const GEnumValue values[] = {
{VIPS_COMBINE_MAX, "VIPS_COMBINE_MAX", "max"},
{VIPS_COMBINE_SUM, "VIPS_COMBINE_SUM", "sum"},
{VIPS_COMBINE_LAST, "VIPS_COMBINE_LAST", "last"},
{0, NULL, NULL}
};
etype = g_enum_register_static( "VipsCombine", values );
}
return( etype );
}
GType
vips_operation_morphology_get_type( void )
{