% %
% %
% %
+% C a n n y E d g e I m a g e %
+% %
+% %
+% %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% CannyEdgeImage() uses a multi-stage algorithm to detect a wide range of
+% edges in images.
+%
+% The format of the EdgeImage method is:
+%
+% Image *CannyEdgeImage(const Image *image,const double radius,
+% const double sigma,const double low_factor,const double high_factor,
+% const size_t threshold,ExceptionInfo *exception)
+%
+% A description of each parameter follows:
+%
+% o image: the image.
+%
+% o channel: the channel type.
+%
+% o radius: the radius of the gaussian smoothing filter.
+%
+% o sigma: the sigma of the gaussian smoothing filter.
+%
+% o low_factor: use this low factor in hysteresis.
+%
+% o hight_factor: use this high factor in hysteresis.
+%
+% o exception: return any errors or warnings in this structure.
+%
+*/
+MagickExport Image *CannyEdgeImage(const Image *image,const double radius,
+ const double sigma,const double low_factor,const double high_factor,
+ ExceptionInfo *exception)
+{
+ Image
+ *edge_image;
+
+ assert(image != (const Image *) NULL);
+ assert(image->signature == MagickSignature);
+ if (image->debug != MagickFalse)
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ assert(exception != (ExceptionInfo *) NULL);
+ assert(exception->signature == MagickSignature);
+ edge_image=(Image *) NULL;
+ return(edge_image);
+}
+\f
+/*
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %
+% %
+% %
% C o n v o l v e I m a g e %
% %
% %
*AdaptiveSharpenImage(const Image *,const double,const double,
ExceptionInfo *),
*BlurImage(const Image *,const double,const double,ExceptionInfo *),
+ *CannyEdgeImage(const Image *,const double,const double,const double,
+ const double,ExceptionInfo *),
*ConvolveImage(const Image *,const KernelInfo *,ExceptionInfo *),
*DespeckleImage(const Image *,ExceptionInfo *),
*EdgeImage(const Image *,const double,ExceptionInfo *),
{ "-brightness-contrast", 1L, SimpleOperatorFlag, MagickFalse },
{ "+cache", 0L, GlobalOptionFlag, MagickFalse },
{ "-cache", 1L, GlobalOptionFlag, MagickFalse },
+ { "+edge", 1L, SimpleOperatorFlag, MagickTrue },
+ { "-edge", 1L, SimpleOperatorFlag, MagickFalse },
{ "+caption", 0L, ImageInfoOptionFlag | NeverInterpretArgsFlag, MagickFalse },
{ "-caption", 1L, ImageInfoOptionFlag | NeverInterpretArgsFlag, MagickFalse },
{ "+cdl", 1L, DeprecateOptionFlag, MagickTrue },
"-bordercolor color border color",
"-brightness-contrast geometry",
" improve brightness / contrast of the image",
+ "-canny geometry detect edges in the image",
"-cdl filename color correct with a color decision list",
"-charcoal radius simulate a charcoal drawing",
"-chop geometry remove pixels from the image interior",
ThrowConvertInvalidArgumentException(option,argv[i]);
break;
}
+ if (LocaleCompare("canny",option+1) == 0)
+ {
+ if (*option == '+')
+ break;
+ i++;
+ if (i == (ssize_t) (argc-1))
+ ThrowConvertException(OptionError,"MissingArgument",option);
+ if (IsGeometry(argv[i]) == MagickFalse)
+ ThrowConvertInvalidArgumentException(option,argv[i]);
+ break;
+ }
if (LocaleCompare("caption",option+1) == 0)
{
if (*option == '+')
}
case 'c':
{
+ if (LocaleCompare("canny",option+1) == 0)
+ {
+ /*
+ Detect edges in the image.
+ */
+ (void) SyncImageSettings(mogrify_info,*image,exception);
+ flags=ParseGeometry(argv[i+1],&geometry_info);
+ if ((flags & SigmaValue) == 0)
+ geometry_info.sigma=1.0;
+ if ((flags & XiValue) == 0)
+ geometry_info.xi=0.35;
+ if ((flags & PsiValue) == 0)
+ geometry_info.psi=0.75;
+ mogrify_image=CannyEdgeImage(*image,geometry_info.rho,
+ geometry_info.sigma,geometry_info.xi,geometry_info.psi,exception);
+ break;
+ }
if (LocaleCompare("cdl",option+1) == 0)
{
char
"-bordercolor color border color",
"-brightness-contrast geometry",
" improve brightness / contrast of the image",
+ "-canny geometry detect edges in the image",
"-cdl filename color correct with a color decision list",
"-charcoal geometry simulate a charcoal drawing",
"-chop geometry remove pixels from the image interior",
ThrowMogrifyInvalidArgumentException(option,argv[i]);
break;
}
+ if (LocaleCompare("canny",option+1) == 0)
+ {
+ if (*option == '+')
+ break;
+ i++;
+ if (i == (ssize_t) argc)
+ ThrowMogrifyException(OptionError,"MissingArgument",option);
+ if (IsGeometry(argv[i]) == MagickFalse)
+ ThrowMogrifyInvalidArgumentException(option,argv[i]);
+ break;
+ }
if (LocaleCompare("caption",option+1) == 0)
{
if (*option == '+')
}
case 'c':
{
+ if (LocaleCompare("canny",option+1) == 0)
+ {
+ flags=ParseGeometry(arg1,&geometry_info);
+ if ((flags & (RhoValue|SigmaValue)) == 0)
+ CLIWandExceptArgBreak(OptionError,"InvalidArgument",option,arg1);
+ if ((flags & SigmaValue) == 0)
+ geometry_info.sigma=1.0;
+ if ((flags & XiValue) == 0)
+ geometry_info.xi=0.35;
+ if ((flags & PsiValue) == 0)
+ geometry_info.psi=0.75;
+ new_image=CannyEdgeImage(_image,geometry_info.rho,
+ geometry_info.sigma,geometry_info.xi,geometry_info.psi,_exception);
+ break;
+ }
if (LocaleCompare("cdl",option+1) == 0)
{
/* Note: arguments do not have percent escapes expanded */
{ "Poly", { {"terms", ArrayReference},
{"channel", MagickChannelOptions} } },
{ "Grayscale", { {"method", MagickNoiseOptions} } },
+ { "CannyEdge", { {"geometry", StringReference},
+ {"radius", RealReference}, {"sigma", RealReference},
+ {"low-factor", RealReference}, {"high-factor", RealReference} } },
};
static SplayTreeInfo
PolyImage = 274
Grayscale = 275
GrayscaleImage = 276
+ CannyEdge = 278
+ CannyEdgeImage = 279
MogrifyRegion = 666
PPCODE:
{
(void) GrayscaleImage(image,method,exception);
break;
}
+ case 138: /* Canny */
+ {
+ if (attribute_flag[0] != 0)
+ {
+ flags=ParseGeometry(argument_list[0].string_reference,
+ &geometry_info);
+ if ((flags & SigmaValue) == 0)
+ geometry_info.sigma=1.0;
+ if ((flags & XiValue) == 0)
+ geometry_info.xi=0.35;
+ if ((flags & PsiValue) == 0)
+ geometry_info.psi=0.75;
+ }
+ if (attribute_flag[1] != 0)
+ geometry_info.rho=argument_list[1].real_reference;
+ if (attribute_flag[2] != 0)
+ geometry_info.sigma=argument_list[2].real_reference;
+ if (attribute_flag[3] != 0)
+ geometry_info.xi=argument_list[3].real_reference;
+ if (attribute_flag[4] != 0)
+ geometry_info.psi=argument_list[4].real_reference;
+ if (attribute_flag[5] != 0)
+ channel=(ChannelType) argument_list[5].integer_reference;
+ channel_mask=SetImageChannelMask(image,channel);
+ image=CannyEdgeImage(image,geometry_info.rho,geometry_info.sigma,
+ geometry_info.xi,geometry_info.psi,exception);
+ if (image != (Image *) NULL)
+ (void) SetImageChannelMask(image,channel_mask);
+ break;
+ }
}
if (next != (Image *) NULL)
(void) CatchImageException(next);
\-border geometry surround image with a border of color
\-brightness-contrast geometry
\ improve brightness / contrast of the image
+ \-canny geometry detect edges in the image
\-charcoal radius simulate a charcoal drawing
\-chop geometry remove pixels from the image interior
\-clamp keep pixel values in range (0-QuantumRange)
\-border geometry surround image with a border of color
\-brightness-contrast geometry
improve brightness / contrast of the image
+ \-canny geometry detect edges in the image
\-charcoal radius simulate a charcoal drawing
\-chop geometry remove pixels from the image interior
\-clamp keep pixel values in range (0-QuantumRange)