sobel done
This commit is contained in:
parent
bf70c49fa5
commit
bc0b8ba5c1
@ -46,11 +46,6 @@
|
|||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
|
||||||
/* TODO
|
|
||||||
* - check sobel speed with separated and non-sep masks
|
|
||||||
* - add an 8-bit sobel path, with offset 128 and code for abs() + abs()
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct _VipsSobel {
|
typedef struct _VipsSobel {
|
||||||
VipsOperation parent_instance;
|
VipsOperation parent_instance;
|
||||||
|
|
||||||
@ -88,10 +83,11 @@ vips_sobel_uchar_gen( VipsRegion *or,
|
|||||||
VIPS_REGION_ADDR( or, r->left, r->top + y );
|
VIPS_REGION_ADDR( or, r->left, r->top + y );
|
||||||
|
|
||||||
for( x = 0; x < sz; x++ ) {
|
for( x = 0; x < sz; x++ ) {
|
||||||
int v1 = p1[x] - 128;
|
int v1 = 2 * (p1[x] - 128);
|
||||||
int v2 = p2[x] - 128;
|
int v2 = 2 * (p2[x] - 128);
|
||||||
|
int v = VIPS_ABS( v1 ) + VIPS_ABS( v2 );
|
||||||
|
|
||||||
q[x] = VIPS_ABS( v1 ) + VIPS_ABS( v2 );
|
q[x] = v > 255 ? 255 : v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,35 +102,38 @@ vips_sobel_build_uchar( VipsSobel *sobel )
|
|||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( VIPS_OBJECT( sobel ), 20 );
|
vips_object_local_array( VIPS_OBJECT( sobel ), 20 );
|
||||||
|
|
||||||
t[1] = vips_image_new_matrixv( 1, 3, 1.0, 2.0, 1.0 );
|
g_info( "vips_sobel: uchar path" );
|
||||||
t[2] = vips_image_new_matrixv( 3, 1, 1.0, 0.0, -1.0 );
|
|
||||||
vips_image_set_double( t[2], "offset", 128.0 );
|
/* Sobel is separable, but it's so small there's no speed to be gained,
|
||||||
|
* and doing it one pass lets us keep more precision.
|
||||||
|
*
|
||||||
|
* Divide the result by 2 to prevent overflow, since our result will be
|
||||||
|
* just 8 bits.
|
||||||
|
*/
|
||||||
|
t[1] = vips_image_new_matrixv( 3, 3,
|
||||||
|
1.0, 2.0, 1.0,
|
||||||
|
0.0, 0.0, 0.0,
|
||||||
|
-1.0, -2.0, -1.0 );
|
||||||
|
vips_image_set_double( t[1], "offset", 128.0 );
|
||||||
|
vips_image_set_double( t[1], "scale", 2.0 );
|
||||||
if( vips_conv( sobel->in, &t[3], t[1],
|
if( vips_conv( sobel->in, &t[3], t[1],
|
||||||
"precision", VIPS_PRECISION_INTEGER,
|
"precision", VIPS_PRECISION_INTEGER,
|
||||||
NULL ) ||
|
NULL ) )
|
||||||
vips_conv( t[3], &t[4], t[2],
|
|
||||||
"precision", VIPS_PRECISION_INTEGER,
|
|
||||||
NULL ) )
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
t[5] = vips_image_new_matrixv( 3, 1, 1.0, 2.0, 1.0 );
|
if( vips_rot90( t[1], &t[5], NULL ) ||
|
||||||
t[6] = vips_image_new_matrixv( 1, 3, 1.0, 0.0, -1.0 );
|
vips_conv( sobel->in, &t[7], t[5],
|
||||||
vips_image_set_double( t[6], "offset", 128.0 );
|
|
||||||
if( vips_conv( sobel->in, &t[7], t[5],
|
|
||||||
"precision", VIPS_PRECISION_INTEGER,
|
|
||||||
NULL ) ||
|
|
||||||
vips_conv( t[7], &t[8], t[6],
|
|
||||||
"precision", VIPS_PRECISION_INTEGER,
|
"precision", VIPS_PRECISION_INTEGER,
|
||||||
NULL ) )
|
NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
g_object_set( sobel, "out", vips_image_new(), NULL );
|
g_object_set( sobel, "out", vips_image_new(), NULL );
|
||||||
|
|
||||||
sobel->args[0] = t[4];
|
sobel->args[0] = t[3];
|
||||||
sobel->args[1] = t[8];
|
sobel->args[1] = t[7];
|
||||||
sobel->args[2] = NULL;
|
sobel->args[2] = NULL;
|
||||||
if( vips_image_pipeline_array( sobel->out,
|
if( vips_image_pipeline_array( sobel->out,
|
||||||
VIPS_DEMAND_STYLE_THINSTRIP, sobel->args ) )
|
VIPS_DEMAND_STYLE_FATSTRIP, sobel->args ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_image_generate( sobel->out,
|
if( vips_image_generate( sobel->out,
|
||||||
@ -153,20 +152,19 @@ vips_sobel_build_float( VipsSobel *sobel )
|
|||||||
VipsImage **t = (VipsImage **)
|
VipsImage **t = (VipsImage **)
|
||||||
vips_object_local_array( VIPS_OBJECT( sobel ), 20 );
|
vips_object_local_array( VIPS_OBJECT( sobel ), 20 );
|
||||||
|
|
||||||
t[1] = vips_image_new_matrixv( 1, 3, 1.0, 2.0, 1.0 );
|
g_info( "vips_sobel: float path" );
|
||||||
t[2] = vips_image_new_matrixv( 3, 1, 1.0, 0.0, -1.0 );
|
|
||||||
if( vips_conv( sobel->in, &t[3], t[1], NULL ) ||
|
t[1] = vips_image_new_matrixv( 3, 3,
|
||||||
vips_conv( t[3], &t[4], t[2], NULL ) )
|
1.0, 2.0, 1.0,
|
||||||
|
0.0, 0.0, 0.0,
|
||||||
|
-1.0, -2.0, -1.0 );
|
||||||
|
if( vips_rot90( t[1], &t[2], NULL ) ||
|
||||||
|
vips_conv( sobel->in, &t[3], t[1], NULL ) ||
|
||||||
|
vips_conv( sobel->in, &t[7], t[2], NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
t[5] = vips_image_new_matrixv( 3, 1, 1.0, 2.0, 1.0 );
|
if( vips_abs( t[3], &t[9], NULL ) ||
|
||||||
t[6] = vips_image_new_matrixv( 1, 3, 1.0, 0.0, -1.0 );
|
vips_abs( t[7], &t[10], NULL ) ||
|
||||||
if( vips_conv( sobel->in, &t[7], t[5], NULL ) ||
|
|
||||||
vips_conv( t[7], &t[8], t[6], NULL ) )
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
if( vips_abs( t[4], &t[9], NULL ) ||
|
|
||||||
vips_abs( t[8], &t[10], NULL ) ||
|
|
||||||
vips_add( t[9], t[10], &t[11], NULL ) ||
|
vips_add( t[9], t[10], &t[11], NULL ) ||
|
||||||
vips_cast( t[11], &t[12], sobel->in->BandFmt, NULL ) )
|
vips_cast( t[11], &t[12], sobel->in->BandFmt, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -201,7 +199,6 @@ vips_sobel_class_init( VipsSobelClass *class )
|
|||||||
{
|
{
|
||||||
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
GObjectClass *gobject_class = G_OBJECT_CLASS( class );
|
||||||
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
VipsObjectClass *object_class = (VipsObjectClass *) class;
|
||||||
VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
|
|
||||||
|
|
||||||
gobject_class->set_property = vips_object_set_property;
|
gobject_class->set_property = vips_object_set_property;
|
||||||
gobject_class->get_property = vips_object_get_property;
|
gobject_class->get_property = vips_object_get_property;
|
||||||
@ -210,8 +207,6 @@ vips_sobel_class_init( VipsSobelClass *class )
|
|||||||
object_class->description = _( "Sobel edge detector" );
|
object_class->description = _( "Sobel edge detector" );
|
||||||
object_class->build = vips_sobel_build;
|
object_class->build = vips_sobel_build;
|
||||||
|
|
||||||
operation_class->flags = VIPS_OPERATION_SEQUENTIAL;
|
|
||||||
|
|
||||||
VIPS_ARG_IMAGE( class, "in", 1,
|
VIPS_ARG_IMAGE( class, "in", 1,
|
||||||
_( "Input" ),
|
_( "Input" ),
|
||||||
_( "Input image" ),
|
_( "Input image" ),
|
||||||
|
Loading…
Reference in New Issue
Block a user