try a simpler edge detect in canny

simple +/- differencing seems to work better
This commit is contained in:
John Cupitt 2018-02-08 17:14:26 +00:00
parent 43cbd32955
commit 407291c3ff
2 changed files with 86 additions and 29 deletions

View File

@ -63,6 +63,88 @@ typedef VipsOperationClass VipsCannyClass;
G_DEFINE_TYPE( VipsCanny, vips_canny, VIPS_TYPE_OPERATION );
static int
vips_canny_gradient_sobel( VipsImage *in, VipsImage **Gx, VipsImage **Gy )
{
VipsImage *scope;
VipsImage **t;
scope = vips_image_new();
t = (VipsImage **) vips_object_local_array( (VipsObject *) scope, 20 );
/* Separated Sobel gives Gx / Gy. Aim for vector path. Scale down by 2
* to try to avoid clipping.
*/
t[1] = vips_image_new_matrixv( 1, 3, 1.0, 2.0, 1.0 );
vips_image_set_double( t[1], "scale", 2.0 );
t[2] = vips_image_new_matrixv( 3, 1, 1.0, 0.0, -1.0 );
vips_image_set_double( t[2], "offset", 128.0 );
if( vips_conv( in, &t[3], t[1],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ||
vips_conv( t[3], Gx, t[2],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ) {
g_object_unref( scope );
return( -1 );
}
t[5] = vips_image_new_matrixv( 3, 1, 1.0, 2.0, 1.0 );
vips_image_set_double( t[5], "scale", 2.0 );
t[6] = vips_image_new_matrixv( 1, 3, 1.0, 0.0, -1.0 );
vips_image_set_double( t[6], "offset", 128.0 );
if( vips_conv( in, &t[7], t[5],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ||
vips_conv( t[7], Gy, t[6],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ) {
g_object_unref( scope );
return( -1 );
}
g_object_unref( scope );
return( 0 );
}
/* Simple -1/+1 difference. The sobel version above does an edge
* detect as well.
*/
static int
vips_canny_gradient_simple( VipsImage *in, VipsImage **Gx, VipsImage **Gy )
{
VipsImage *scope;
VipsImage **t;
scope = vips_image_new();
t = (VipsImage **) vips_object_local_array( (VipsObject *) scope, 20 );
t[1] = vips_image_new_matrixv( 2, 1, -1.0, 1.0 );
vips_image_set_double( t[1], "scale", 2.0 );
vips_image_set_double( t[1], "offset", 128.0 );
if( vips_conv( in, Gx, t[1],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ) {
g_object_unref( scope );
return( -1 );
}
t[5] = vips_image_new_matrixv( 1, 2, -1.0, 1.0 );
vips_image_set_double( t[5], "scale", 2.0 );
vips_image_set_double( t[5], "offset", 128.0 );
if( vips_conv( in, Gy, t[5],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ) {
g_object_unref( scope );
return( -1 );
}
g_object_unref( scope );
return( 0 );
}
static int
vips_canny_polar_generate( VipsRegion *or,
void *vseq, void *a, void *b, gboolean *stop )
@ -356,34 +438,8 @@ vips_canny_build( VipsObject *object )
return( -1 );
in = t[0];
/* Separated Sobel gives Gx / Gy. Aim for vector path. Scale down by 2
* to try to avoid clipping.
*/
t[1] = vips_image_new_matrixv( 1, 3, 1.0, 2.0, 1.0 );
vips_image_set_double( t[1], "scale", 2.0 );
t[2] = vips_image_new_matrixv( 3, 1, 1.0, 0.0, -1.0 );
vips_image_set_double( t[2], "offset", 128.0 );
if( vips_conv( in, &t[3], t[1],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ||
vips_conv( t[3], &t[4], t[2],
"precision", VIPS_PRECISION_INTEGER,
NULL ) )
return( -1 );
Gx = t[4];
t[5] = vips_image_new_matrixv( 3, 1, 1.0, 2.0, 1.0 );
vips_image_set_double( t[5], "scale", 2.0 );
t[6] = vips_image_new_matrixv( 1, 3, 1.0, 0.0, -1.0 );
vips_image_set_double( t[6], "offset", 128.0 );
if( vips_conv( in, &t[7], t[5],
"precision", VIPS_PRECISION_INTEGER,
NULL ) ||
vips_conv( t[7], &t[8], t[6],
"precision", VIPS_PRECISION_INTEGER,
NULL ) )
return( -1 );
Gy = t[8];
if( vips_canny_gradient_simple( in, &Gx, &Gy ) )
return( -1 );
/* Form (G, theta), with theta coded.
*/

View File

@ -236,7 +236,8 @@ vips_resize_build( VipsObject *object )
*/
if( hscale > 1.0 ||
vscale > 1.0 ) {
const char *nickname = vips_resize_interpolate( resize->kernel );
const char *nickname =
vips_resize_interpolate( resize->kernel );
/* Input displacement. For centre sampling, shift by 0.5 down
* and right.