im_label_regions() is a class
This commit is contained in:
parent
487e6ed95e
commit
025e56c894
@ -5,7 +5,7 @@
|
||||
- operations can be tagged as "deprecated"
|
||||
- redo im_draw_circle(), im_draw_flood(), im_draw_line(), im_draw_mask(),
|
||||
im_draw_image(), im_draw_rect(), im_draw_point(), im_read_point(),
|
||||
im_draw_smudge() as classes
|
||||
im_draw_smudge(), im_label_regions() as classes
|
||||
- better rounding in vips_flatten()
|
||||
- VipsStatistic operations are sequential
|
||||
|
||||
|
16
TODO
16
TODO
@ -1,6 +1,4 @@
|
||||
- need to do im_label_regions in morph
|
||||
|
||||
- swap VipsArea ink for VipsArrayDouble?
|
||||
- nip2 make check is failing
|
||||
|
||||
- ink to vec etc. should work for complex .. output or accept a double-length
|
||||
vector
|
||||
@ -18,6 +16,9 @@
|
||||
current behaviour of imaginary == 0 always
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- try
|
||||
|
||||
$ vips getpoint
|
||||
@ -46,19 +47,18 @@
|
||||
y-array - Array of vertical positions, output VipsArrayInt
|
||||
|
||||
don't list out-array or out as args in the usage line, since they don't need
|
||||
an arg ... these args should be in a separet section I guess?
|
||||
an arg ... these args should be in a separate section, I guess?
|
||||
|
||||
put description first
|
||||
|
||||
|
||||
|
||||
|
||||
- try:
|
||||
|
||||
$ vips max babe.v --x-array --size 0
|
||||
Segmentation fault (core dumped)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- try:
|
||||
|
||||
im = VIPS::Image.new(ARGV[0])
|
||||
|
@ -4498,6 +4498,23 @@ im_cntlines( VipsImage *im, double *nolines, int flag )
|
||||
NULL ) );
|
||||
}
|
||||
|
||||
int
|
||||
im_label_regions( IMAGE *test, IMAGE *mask, int *segments )
|
||||
{
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_labelregions( test, &x, "segments", segments, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
if( im_copy( x, mask ) ) {
|
||||
g_object_unref( x );
|
||||
return( -1 );
|
||||
}
|
||||
g_object_unref( x );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int
|
||||
im_rank( IMAGE *in, IMAGE *out, int width, int height, int index )
|
||||
{
|
||||
@ -4653,10 +4670,12 @@ im_draw_flood( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout )
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
dout->left = left;
|
||||
dout->top = top;
|
||||
dout->width = width;
|
||||
dout->height = height;
|
||||
if( dout ) {
|
||||
dout->left = left;
|
||||
dout->top = top;
|
||||
dout->width = width;
|
||||
dout->height = height;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -4683,10 +4702,12 @@ im_draw_flood_blob( IMAGE *image, int x, int y, VipsPel *ink, Rect *dout )
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
dout->left = left;
|
||||
dout->top = top;
|
||||
dout->width = width;
|
||||
dout->height = height;
|
||||
if( dout ) {
|
||||
dout->left = left;
|
||||
dout->top = top;
|
||||
dout->width = width;
|
||||
dout->height = height;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
@ -4695,15 +4716,12 @@ int
|
||||
im_draw_flood_other( IMAGE *image,
|
||||
IMAGE *test, int x, int y, int serial, Rect *dout )
|
||||
{
|
||||
double vec[1];
|
||||
int left;
|
||||
int top;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
vec[0] = serial;
|
||||
|
||||
if( vips_draw_flood( image, vec, 1, x, y,
|
||||
if( vips_draw_flood1( image, serial, x, y,
|
||||
"test", test,
|
||||
"equal", TRUE,
|
||||
"left", &left,
|
||||
@ -4713,10 +4731,12 @@ im_draw_flood_other( IMAGE *image,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
dout->left = left;
|
||||
dout->top = top;
|
||||
dout->width = width;
|
||||
dout->height = height;
|
||||
if( dout ) {
|
||||
dout->left = left;
|
||||
dout->top = top;
|
||||
dout->width = width;
|
||||
dout->height = height;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -55,9 +55,7 @@ extern "C" {
|
||||
typedef struct _VipsDrawink {
|
||||
VipsDraw parent_instance;
|
||||
|
||||
/* Parameters.
|
||||
*/
|
||||
VipsArea *ink; /* With this */
|
||||
VipsArrayDouble *ink;
|
||||
|
||||
/* Ink cast to pixel type.
|
||||
*/
|
||||
|
@ -50,16 +50,14 @@ int vips_morph( VipsImage *in, VipsImage **out, VipsImage *mask,
|
||||
int vips_rank( VipsImage *in, VipsImage **out,
|
||||
int width, int height, int index, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_median( VipsImage *in, VipsImage **out, int size, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_countlines( VipsImage *in, double *nolines,
|
||||
VipsDirection direction, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_median( VipsImage *in, VipsImage **out, int size, ... )
|
||||
int vips_labelregions( VipsImage *in, VipsImage **out, ... )
|
||||
__attribute__((sentinel));
|
||||
|
||||
|
||||
|
||||
int im_label_regions( VipsImage *test, VipsImage *mask, int *segments );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -998,6 +998,7 @@ int im_fractsurf( VipsImage *out, int size, double frd );
|
||||
int im_phasecor_fft( VipsImage *in1, VipsImage *in2, VipsImage *out );
|
||||
|
||||
int im_cntlines( VipsImage *im, double *nolines, int flag );
|
||||
int im_label_regions( VipsImage *test, VipsImage *mask, int *segments );
|
||||
int im_rank( VipsImage *in, VipsImage *out, int width, int height, int index );
|
||||
int im_zerox( VipsImage *in, VipsImage *out, int sign );
|
||||
|
||||
|
@ -7,6 +7,6 @@ libmorphology_la_SOURCES = \
|
||||
rank.c \
|
||||
hitmiss.c \
|
||||
morph.c \
|
||||
im_label_regions.c
|
||||
labelregions.c
|
||||
|
||||
AM_CPPFLAGS = -I${top_srcdir}/libvips/include @VIPS_CFLAGS@ @VIPS_INCLUDES@
|
||||
|
@ -1,117 +0,0 @@
|
||||
/* im_label_regions.c
|
||||
*
|
||||
* 5/11/09
|
||||
* - renamed from im_segment()
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
||||
VIPS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
/**
|
||||
* im_label_regions:
|
||||
* @test: image to test
|
||||
* @mask: write labelled regions here
|
||||
* @segments: return number of regions here
|
||||
*
|
||||
* im_label_regions() repeatedly scans @test for regions of 4-connected pixels
|
||||
* with the same pixel value. Every time a region is discovered, those
|
||||
* pixels are marked in @mask with a unique serial number. Once all pixels
|
||||
* have been labelled, the operation returns, setting @segments to the number
|
||||
* of discrete regions which were detected.
|
||||
*
|
||||
* @mask is always a 1-band %IM_BANDFMT_UINT image of the same dimensions as
|
||||
* @test.
|
||||
*
|
||||
* This operation is useful for, for example, blob counting. You can use the
|
||||
* morphological operators to detect and isolate a series of objects, then use
|
||||
* im_label_regions() to number them all.
|
||||
*
|
||||
* Use im_histindexed() to (for example) find blob coordinates.
|
||||
*
|
||||
* See also: im_histindexed()
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
im_label_regions( IMAGE *test, IMAGE *mask, int *segments )
|
||||
{
|
||||
IMAGE *t[2];
|
||||
int serial;
|
||||
int *m;
|
||||
int x, y;
|
||||
|
||||
/* Create the zero mask image.
|
||||
*/
|
||||
if( im_open_local_array( mask, t, 2, "im_label_regions", "p" ) ||
|
||||
im_black( t[0], test->Xsize, test->Ysize, 1 ) ||
|
||||
im_clip2fmt( t[0], t[1], IM_BANDFMT_INT ) )
|
||||
return( -1 );
|
||||
|
||||
/* Search the mask image, flooding as we find zero pixels.
|
||||
*/
|
||||
if( im_rwcheck( t[1] ) )
|
||||
return( -1 );
|
||||
serial = 0;
|
||||
m = (int *) t[1]->data;
|
||||
for( y = 0; y < test->Ysize; y++ ) {
|
||||
for( x = 0; x < test->Xsize; x++ ) {
|
||||
if( !m[x] ) {
|
||||
/*
|
||||
if( im_flood_other_old( t[1], test,
|
||||
x, y, serial ) )
|
||||
*/
|
||||
if( im_flood_other( test, t[1],
|
||||
x, y, serial, NULL ) )
|
||||
// if( im_flood_other_old( t[1], test,
|
||||
// x, y, serial ) )
|
||||
return( -1 );
|
||||
|
||||
serial += 1;
|
||||
}
|
||||
}
|
||||
|
||||
m += test->Xsize;
|
||||
}
|
||||
|
||||
/* Copy result to mask.
|
||||
*/
|
||||
if( im_copy( t[1], mask ) )
|
||||
return( -1 );
|
||||
if( segments )
|
||||
*segments = serial;
|
||||
|
||||
return( 0 );
|
||||
}
|
182
libvips/morphology/labelregions.c
Normal file
182
libvips/morphology/labelregions.c
Normal file
@ -0,0 +1,182 @@
|
||||
/* labelregions.c
|
||||
*
|
||||
* 5/11/09
|
||||
* - renamed from im_segment()
|
||||
* 11/2/14
|
||||
* - redo as a class
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This file is part of VIPS.
|
||||
|
||||
VIPS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif /*HAVE_CONFIG_H*/
|
||||
#include <vips/intl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
#include "pmorphology.h"
|
||||
|
||||
typedef struct _VipsLabelregions {
|
||||
VipsMorphology parent_instance;
|
||||
|
||||
VipsImage *mask;
|
||||
int segments;
|
||||
} VipsLabelregions;
|
||||
|
||||
typedef VipsMorphologyClass VipsLabelregionsClass;
|
||||
|
||||
G_DEFINE_TYPE( VipsLabelregions, vips_labelregions, VIPS_TYPE_MORPHOLOGY );
|
||||
|
||||
static int
|
||||
vips_labelregions_build( VipsObject *object )
|
||||
{
|
||||
VipsMorphology *morphology = VIPS_MORPHOLOGY( object );
|
||||
VipsImage *in = morphology->in;
|
||||
VipsImage **t = (VipsImage **) vips_object_local_array( object, 7 );
|
||||
|
||||
int serial;
|
||||
int *m;
|
||||
int x, y;
|
||||
|
||||
if( VIPS_OBJECT_CLASS( vips_labelregions_parent_class )->
|
||||
build( object ) )
|
||||
return( -1 );
|
||||
|
||||
/* Create the zero mask image.
|
||||
*/
|
||||
if( vips_black( &t[0], in->Xsize, in->Ysize, 1, NULL ) ||
|
||||
vips_cast( t[0], &t[1], VIPS_FORMAT_INT, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
/* Search the mask image, flooding as we find zero pixels.
|
||||
*/
|
||||
if( vips_image_inplace( t[1] ) )
|
||||
return( -1 );
|
||||
|
||||
serial = 0;
|
||||
m = (int *) t[1]->data;
|
||||
for( y = 0; y < t[1]->Ysize; y++ ) {
|
||||
for( x = 0; x < t[1]->Xsize; x++ ) {
|
||||
if( !m[x] ) {
|
||||
if( vips_draw_flood1( t[1], serial, x, y,
|
||||
"test", in,
|
||||
"equal", TRUE,
|
||||
NULL ) )
|
||||
return( -1 );
|
||||
|
||||
serial += 1;
|
||||
}
|
||||
}
|
||||
|
||||
m += t[1]->Xsize;
|
||||
}
|
||||
|
||||
g_object_set( object,
|
||||
"mask", t[1],
|
||||
"segments", serial,
|
||||
NULL );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static void
|
||||
vips_labelregions_class_init( VipsLabelregionsClass *class )
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||
VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class );
|
||||
|
||||
gobject_class->set_property = vips_object_set_property;
|
||||
gobject_class->get_property = vips_object_get_property;
|
||||
|
||||
vobject_class->nickname = "labelregions";
|
||||
vobject_class->description = _( "label regions in an image" );
|
||||
vobject_class->build = vips_labelregions_build;
|
||||
|
||||
VIPS_ARG_IMAGE( class, "mask", 2,
|
||||
_( "Mask" ),
|
||||
_( "Mask of region labels" ),
|
||||
VIPS_ARGUMENT_REQUIRED_OUTPUT,
|
||||
G_STRUCT_OFFSET( VipsLabelregions, mask ) );
|
||||
|
||||
VIPS_ARG_INT( class, "segments", 3,
|
||||
_( "Segments" ),
|
||||
_( "Number of discrete contigious regions" ),
|
||||
VIPS_ARGUMENT_OPTIONAL_OUTPUT,
|
||||
G_STRUCT_OFFSET( VipsLabelregions, segments ),
|
||||
0, 1000000000, 0 );
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
vips_labelregions_init( VipsLabelregions *labelregions )
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* vips_labelregions:
|
||||
* @test: image to test
|
||||
* @mask: write labelled regions here
|
||||
*
|
||||
* Optional arguments:
|
||||
*
|
||||
* @segments: return number of regions found here
|
||||
*
|
||||
* Repeatedly scans @test for regions of 4-connected pixels
|
||||
* with the same pixel value. Every time a region is discovered, those
|
||||
* pixels are marked in @mask with a unique serial number. Once all pixels
|
||||
* have been labelled, the operation returns, setting @segments to the number
|
||||
* of discrete regions which were detected.
|
||||
*
|
||||
* @mask is always a 1-band #VIPS_FORMAT_INT image of the same dimensions as
|
||||
* @test.
|
||||
*
|
||||
* This operation is useful for, for example, blob counting. You can use the
|
||||
* morphological operators to detect and isolate a series of objects, then use
|
||||
* vips_labelregions() to number them all.
|
||||
*
|
||||
* Use vips_hist_find_indexed() to (for example) find blob coordinates.
|
||||
*
|
||||
* See also: vips_hist_find_indexed().
|
||||
*
|
||||
* Returns: 0 on success, -1 on error.
|
||||
*/
|
||||
int
|
||||
vips_labelregions( VipsImage *in, VipsImage **mask, ... )
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
va_start( ap, mask );
|
||||
result = vips_call_split( "labelregions", ap, in, mask );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
}
|
Loading…
Reference in New Issue
Block a user