finish VipsMeasure
plus a fix to operation.c
This commit is contained in:
parent
13d90ef660
commit
7a42449868
4
TODO
4
TODO
@ -1,4 +1,6 @@
|
||||
- finish adding maxpos stuff to im_stats
|
||||
- avg/dev etc. should uncode images? eg. labq2lab etc.
|
||||
|
||||
test new measure
|
||||
|
||||
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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" ),
|
||||
|
@ -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 \
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user