mgradient

Source code

There are three commonly used morphological gradient definitions: the beucher gradident dilate(img) - erode(img), the external half-gradient dilate(img) - img, and the internal half-gradident img - erode(img).

using ImageMorphology
using TestImages
using ImageBase
using ImageShow

img = restrict(testimage_dip3e("fig0940")) # rice
img01 = @. Gray(img > 0.5)
mosaic(img, img01; nrow=1)

Beucher gradient

The default mode is beucher gradient defined as dilate(img) - erode(img).

mosaic(mgradient(img), mgradient(img01); nrow=1)

There are two nice properties of the beucher gradient:

  • it is always positive if the structuring element is symmetric
  • it is a self-complementary operator – mgradient(img) == mgradient(complement.(img))
all(mgradient(rand(32, 32)) .> 0) # always positive
true
A = rand(32, 32)
mgradient(A) == mgradient(1 .- A) # self-complementary
true

Half gradient

If we look closely, we can see that the beucher gradient boundary is always two-pixel wide – one pixel per each side.

A = falses(7, 7)
A[3:5, 3:5] .= true
A
7×7 BitMatrix:
 0  0  0  0  0  0  0
 0  0  0  0  0  0  0
 0  0  1  1  1  0  0
 0  0  1  1  1  0  0
 0  0  1  1  1  0  0
 0  0  0  0  0  0  0
 0  0  0  0  0  0  0
Int.(mgradient(A))
7×7 Matrix{Int64}:
 0  0  0  0  0  0  0
 0  1  1  1  1  1  0
 0  1  1  1  1  1  0
 0  1  1  0  1  1  0
 0  1  1  1  1  1  0
 0  1  1  1  1  1  0
 0  0  0  0  0  0  0

This is because dilate extends the boundary for one pixel, while erode shrinks for one pixel. This observation introduces so-called half-gradients.

The external half-gradient, also known as half-gradient by dilation, is defined as dilate(img) - img:

Int.(mgradient(A; mode=:external)) # external boundary
7×7 Matrix{Int64}:
 0  0  0  0  0  0  0
 0  1  1  1  1  1  0
 0  1  0  0  0  1  0
 0  1  0  0  0  1  0
 0  1  0  0  0  1  0
 0  1  1  1  1  1  0
 0  0  0  0  0  0  0

The internal half-gradient, also known as half-gradient by erosion, is defined as img - erode(img):

Int.(mgradient(A; mode=:internal)) # internal boundary
7×7 Matrix{Int64}:
 0  0  0  0  0  0  0
 0  0  0  0  0  0  0
 0  0  1  1  1  0  0
 0  0  1  0  1  0  0
 0  0  1  1  1  0  0
 0  0  0  0  0  0  0
 0  0  0  0  0  0  0

Note that the result of internal gradient is inside the original image, and that of external gradient is outside the original image. Also, external gradient and internal are complementary to each other:

A = rand(32, 32)
mgradient(A; mode=:external) == mgradient(1 .- A; mode=:internal)
true

Thick gradient

The gradient thickness is controlled by the SE size, or the r parameter. When r>1, it is usually called thick gradient.

mosaic([mgradient(img01; r) for r in 1:3]; nrow=1)

See also

There are many useful gradient definitions in image processing. For instance, ImageBase.jl provides the finite-difference version of gradients fdiff and fgradient. ImageFiltering.jl provides sobel, prewitt and other gradient filters.

fout = abs.(ImageBase.FiniteDiff.fdiff(img; dims=1))
mout = mgradient(img; dims=1)
mosaic(fout, mout; nrow=1)

For a comprehensive and more accurate documentation, please check the mgradient reference page.


This page was generated using DemoCards.jl and Literate.jl.