Canny Edge Detector#

A classical edge detection method used in image processing and relying on gradients. Based on Canny (1986).

The implementation is copied from that of scikit-image, with minor adjustments to make it more flexible.

Important

The implementation does not include the typical Gaussian filter. This allows to apply (or not) any filter that may not smooth features as much.

Definition#

Filtering#

Because this is a gradient based approach, it is a good idea to smooth out the noise in the input field. This is typically done with a Gaussian filter. Here this implementation does not do any filtering so that you can choose the filter you deem the most appropriate.

Non-maximal suppression#

The gradient magnitude and direction is computed using a 3x3 Sobel operator. The mask of non-valid pixels is eroded accordingly. The borders are masked as well.

Potential edges are then thinned to 1-pixel width. This is done by finding the normal to the edge at each point by looking at the x and y components of the gradient. The edge can be horizontal, vertical, diagonal, or anti-diagonal.

The central pixel is not kept if the gradient at neighboring pixels in the normal or reverse directions is greater than its own. The gradient in those directions is computed by interpolating the values from a selection of the 8 closest neighbors.

See the implementation at scikit-image/scikit-image.

Hysteresis or double-thresholding#

Edges are considered as weak or strong based on the gradient magnitude and two thresholds given by the user.

Note

If not given, the thresholds are taken as 10% and 20% of the input dtype maximum value.

If use_quantiles=True, the given values are taken as the quantiles of the image gradient magnitude.

Strong edges are all kept. Weak edges are kept only if they are recursively 8-connected to a strong edge. Meaning any weak edge that has a strong edge in at least one of its 8 closest neighbors is kept and now-considered as a strong edge (so weak edges connected to it will be kept as well etc.).

This step may make sense in the context of image processing, but not so much when detecting oceanic fronts. For that reason, it is possible to omit that step by passing hysteresis=False. In this case, both weak and strong edges are kept.

Important

The hysteresis can have non-local effects (a weak edge is affected by a strong edge at the other end of the image if they are connected). It cannot be applied to a Dask array that is chunked along one of the core dimension. Rechunk beforehand, for instance if using Xarray:

input_field = input_field.chunk(lon=-1, lat=-1)

Functions#

Detect edges:

Supported types and requirements#

Supported input types: Numpy, Dask, Xarray

Requirements:

References#

[canny_1986]

Canny, J., “A Computational Approach To Edge Detection”, in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. PAMI-8, no. 6, pp. 679-698, DOI:10.1109/TPAMI.1986.4767851, 1986.