finish VipsMeasure

plus a fix to operation.c
This commit is contained in:
John Cupitt 2011-11-09 10:17:40 +00:00
parent 13d90ef660
commit 7a42449868
9 changed files with 107 additions and 137 deletions

4
TODO
View File

@ -1,4 +1,6 @@
- finish adding maxpos stuff to im_stats
- avg/dev etc. should uncode images? eg. labq2lab etc.
test new measure

View File

@ -11,7 +11,7 @@ libarithmetic_la_SOURCES = \
im_linreg.c \
im_maxpos_avg.c \
im_maxpos_vec.c \
im_measure.c \
measure.c \
multiply.c \
im_point_bilinear.c \
im_remainder.c \

View File

@ -515,6 +515,7 @@ vips_arithmetic_operation_init( void )
extern GType vips_abs_get_type( void );
extern GType vips_sign_get_type( void );
extern GType vips_stats_get_type( void );
extern GType vips_measure_get_type( void );
vips_add_get_type();
vips_subtract_get_type();
@ -530,5 +531,6 @@ vips_arithmetic_operation_init( void )
vips_abs_get_type();
vips_sign_get_type();
vips_stats_get_type();
vips_measure_get_type();
}

View File

@ -113,104 +113,80 @@ vips_measure_build( VipsObject *object )
{
VipsMeasure *measure = (VipsMeasure *) object;
if( measure->in &&
vips_argument_get_assigned( object, "h" ) &&
vips_argument_get_assigned( object, "v" ) ) {
int bands = vips_image_get_bands( measure->in );
if( vips_check_noncomplex( "VipsMeasure", measure->in ) )
return( -1 );
g_object_set( object,
"out", vips_image_new_array( bands,
measure->h * measure->v ),
NULL );
}
int bands;
double pw;
double ph;
int j, i;
int w, h;
int b;
if( VIPS_OBJECT_CLASS( vips_measure_parent_class )->build( object ) )
return( -1 );
need labq2lab on labq images
bands = vips_image_get_bands( measure->in );
or maybe stats/avg/dev should do this?
g_object_set( object,
"out", vips_image_new_array( bands, measure->h * measure->v ),
NULL );
they could handle rad etc as well ... add it to statistics.c
need to keep the whole of im_measure() in deprecated, we've removed
the 'measure these patch numbers' feature
maybe remove the noncomplex check?
parent->build() only checks that inputs have been set, I think, we
don't actually need to set out before calling it
where else do we set out before build? verify
/* left/top/width/height default to the size of the image.
*/
if( !vips_argument_get_assigned( object, "width" ) )
g_object_set( object,
"width", vips_image_get_width( measure->in ),
NULL );
if( !vips_argument_get_assigned( object, "height" ) )
g_object_set( object,
"height", vips_image_get_height( measure->in ),
NULL );
/* How large are the patches we are to measure?
*/
double pw = (double) width / (double) u;
double ph = (double) height / (double) v;
pw = (double) measure->width / measure->h;
ph = (double) measure->height / measure->v;
/* Set up sub to be the size we need for a patch.
/* The size of a patch.
*/
w = (pw + 1) / 2;
h = (ph + 1) / 2;
/* Loop through sel, picking out areas to measure.
*/
for( j = 0, patch = 0; patch < nsel; patch++ ) {
/* Sanity check. Is the patch number sensible?
*/
if( sel[patch] <= 0 || sel[patch] > u * v ) {
im_error( "im_measure",
_( "patch %d is out of range" ),
sel[patch] );
return( 1 );
}
for( j = 0; j < measure->v; j++ ) {
for( i = 0; i < measure->h; i++ ) {
int x = measure->left + i * pw + (pw + 2) / 4;
int y = measure->top + j * ph + (ph + 2) / 4;
/* Patch coordinates.
*/
m = (sel[patch] - 1) % u;
n = (sel[patch] - 1) / u;
double avg, dev;
/* Move sub to correct position.
*/
x = left + m * pw + (pw + 2) / 4;
y = top + n * ph + (ph + 2) / 4;
for( b = 0; b < bands; b++ ) {
VipsImage **t = (VipsImage **)
vips_object_local_array( object, 2 );
/* Loop through bands.
*/
for( i = 0; i < im->Bands; i++, j++ ) {
/* Make temp buffer to extract to.
*/
if( !(tmp = im_open( "patch", "t" )) )
return( -1 );
/* Extract and measure.
*/
if( im_extract_areabands( im, tmp, x, y, w, h, i, 1 ) ||
im_avg( tmp, &avg ) ||
im_deviate( tmp, &dev ) ) {
im_close( tmp );
return( -1 );
/* Extract and measure.
*/
if( vips_extract_area( measure->in, &t[0],
x, y, w, h, NULL ) ||
vips_extract_band( t[0], &t[1],
b, NULL ) ||
vips_avg( t[1], &avg, NULL ) ||
vips_deviate( t[1], &dev, NULL ) )
return( -1 );
/* Is the deviation large compared with the
* average? This could be a clue that our
* parameters have caused us to miss the
* patch. Look out for averages <0, or
* averages near zero (can get these if use
* measure on IM_TYPE_LAB images).
*/
if( dev * 5 > fabs( avg ) && fabs( avg ) > 3 )
im_warn( "im_measure",
_( "patch %d x %d, band %d: "
"avg = %g, sdev = %g" ),
i, j, avg, dev );
*ARY( measure->out, b, x + y * measure->h ) =
avg;
}
im_close( tmp );
/* Is the deviation large compared with the average?
* This could be a clue that our parameters have
* caused us to miss the patch. Look out for averages
* <0, or averages near zero (can get these if use
* im_measure() on IM_TYPE_LAB images).
*/
if( dev * 5 > fabs( avg ) && fabs( avg ) > 3 )
im_warn( "im_measure",
_( "patch %d, band %d: "
"avg = %g, sdev = %g" ),
patch, i, avg, dev );
/* Save results.
*/
coeff[j] = avg;
}
}
@ -240,7 +216,7 @@ vips_measure_class_init( VipsMeasureClass *class )
_( "in" ),
_( "Image to measure" ),
VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsJoin, in1 ) );
G_STRUCT_OFFSET( VipsMeasure, in ) );
VIPS_ARG_IMAGE( class, "out", 2,
_( "Output" ),

View File

@ -17,6 +17,7 @@ libdeprecated_la_SOURCES = \
im_printlines.c \
im_convsub.c \
im_line.c \
im_measure.c \
im_resize_linear.c \
im_debugim.c \
im_gfadd.c \

View File

@ -19,6 +19,9 @@
* - remove deprecated im_extract()
* 30/11/09
* - changes for im_extract() broke averaging
* 9/11/11
* - moved to deprecated, the new VipsMeasure does not have the
* select-patches thing, so we have to keep this around
*/
/*
@ -142,55 +145,8 @@ measure_patches( IMAGE *im, double *coeff,
return( 0 );
}
/**
* im_measure_area:
* @im: image to measure
* @left: area of image containing chart
* @top: area of image containing chart
* @width: area of image containing chart
* @height: area of image containing chart
* @h: patches across chart
* @v: patches down chart
* @sel: array of patch numbers to measure (numbered from 1 in row-major order)
* @nsel: length of patch number array
* @name: name to give to returned @DOUBLEMASK
*
* Analyse a grid of colour patches, producing a #DOUBLEMASK of patch averages.
* The mask has a row for each measured patch, and a column for each image
* band. The operations issues a warning if any patch has a deviation more
* than 20% of
* the mean. Only the central 50% of each patch is averaged. If @sel is %NULL
* then all patches are measured.
*
* Example: 6 band image of 4x2 block of colour patches.
*
* <tgroup cols='4' align='left' colsep='1' rowsep='1'>
* <tbody>
* <row>
* <entry>1</entry>
* <entry>2</entry>
* <entry>3</entry>
* <entry>4</entry>
* </row>
* <row>
* <entry>5</entry>
* <entry>6</entry>
* <entry>7</entry>
* <entry>8</entry>
* </row>
* </tbody>
* </tgroup>
*
* Then call im_measure( im, box, 4, 2, { 2, 4 }, 2, "fred" ) makes a mask
* "fred" which has 6 columns, two rows. The first row contains the averages
* for patch 2, the second for patch 4.
*
* See also: im_avg(), im_deviate(), im_stats().
*
* Returns: #DOUBLEMASK of measurements.
*/
DOUBLEMASK *
im_measure_area( IMAGE *im,
static DOUBLEMASK *
internal_im_measure_area( IMAGE *im,
int left, int top, int width, int height,
int u, int v,
int *sel, int nsel, const char *name )
@ -249,3 +205,33 @@ im_measure_area( IMAGE *im,
return( mask );
}
DOUBLEMASK *
im_measure_area( IMAGE *im,
int left, int top, int width, int height,
int u, int v,
int *sel, int nsel, const char *name )
{
if( sel )
return( internal_im_measure_area( im,
left, top, width, height, u, v, sel, nsel, name ) );
else {
DOUBLEMASK *msk;
VipsImage *t;
if( vips_measure( im, &t, u, v,
"left", left,
"top", top,
"width", width,
"height", height,
NULL ) )
return( NULL );
if( !(msk = im_vips2mask( t, name )) ) {
g_object_unref( t );
return( NULL );
}
g_object_unref( t );
return( msk );
}
}

View File

@ -98,14 +98,12 @@ int vips_sign( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_stats( VipsImage *in, VipsImage **out, ... )
__attribute__((sentinel));
int vips_measure( VipsImage *in, VipsImage **out, int h, int v, ... )
__attribute__((sentinel));
DOUBLEMASK *im_measure_area( VipsImage *im,
int left, int top, int width, int height,
int h, int v,
int *sel, int nsel, const char *name );
int im_maxpos_avg( VipsImage *im, double *xpos, double *ypos, double *out );
int im_maxpos_vec( VipsImage *im, int *xpos, int *ypos, double *maxima, int n );
int im_minpos_vec( VipsImage *im, int *xpos, int *ypos, double *minima, int n );

View File

@ -536,6 +536,10 @@ int im_lintra_vec( int n, double *a, VipsImage *in, double *b, VipsImage *out );
int im_abs( VipsImage *in, VipsImage *out );
int im_sign( VipsImage *in, VipsImage *out );
DOUBLEMASK *im_stats( VipsImage *in );
DOUBLEMASK *im_measure_area( VipsImage *im,
int left, int top, int width, int height,
int h, int v,
int *sel, int nsel, const char *name );
int im_sintra( VipsImage *in, VipsImage *out );
int im_costra( VipsImage *in, VipsImage *out );

View File

@ -859,7 +859,8 @@ vips_call_argv_unref_output( VipsObject *object,
void *a, void *b )
{
if( (argument_class->flags & VIPS_ARGUMENT_OUTPUT) &&
G_IS_PARAM_SPEC_OBJECT( pspec ) ) {
G_IS_PARAM_SPEC_OBJECT( pspec ) &&
argument_instance->assigned ) {
GObject *value;
g_object_get( object,