ImageJ: Morphological operations#

Hide code cell content
%load_ext autoreload
%autoreload 2

# Default imports
import sys
sys.path.append('../../../')
from helpers import *
from matplotlib import pyplot as plt
from myst_nb import glue
import numpy as np
from scipy import ndimage

Introduction#

ImageJ’s Process ‣ Binary submenu contains various useful commands for working with binary images, including some of the morphological operations we’ve looked at.

However, there are other useful morphological operations lurking elsewhere – although most require extra plugins, or switching to Fiji.

Erosion, dilation, opening & closing#

Process ‣ Binary contains the commands Erode, Dilate, Open and Close- commands.

These are relevant here, but my advice is to avoid them. By default they work with fixed 3×3 pixel neighborhoods, but they could do something different if someone has been messing about with the Iterations (1-100) or Count (1-8) options under Process ‣ Binary ‣ Options… – and this unpredictability could well cause trouble.

To perform erosion, dilation, opening and closing with more control and possibly larger neighborhoods, I strongly prefer to use the Process ‣ Filters ‣ Maximum… and Process ‣ Filters ‣ Minimum… commands, combining them if necessary.

Morphological operations in Fiji

Fiji contains Process ‣ Morphology ‣ Gray Morphology, which provides a more flexible implementation of erosion, dilation, opening and closing using a variety of shapes for both grayscale and binary images.

You can also find the plugin for ImageJ at https://imagej.nih.gov/ij/plugins/gray-morphology.html

Outlines, holes & skeletonization#

The Process ‣ Binary ‣ Outline command, predictably, removes all the interior pixels from 2D binary objects, leaving only the perimeters (Fig. 116A).

Process ‣ Binary ‣ Fill Holes would then fill these interior pixels in again, or indeed fill in any background pixels that are completely surrounded by foreground pixels (Fig. 116B).

Process ‣ Binary ‣ Skeletonize shaves off all the outer pixels of an object until only a connected central line remains (Fig. 116C).

Analyzing skeletons

If you are analyzing linear structures (e.g. blood vessels, neurons), then this command or those in Fiji’s Plugins ‣ Skeleton ‣ submenu may be helpful.

Hide code cell content
fig = create_figure(figsize=(8, 4))

# There are different ways to generate outlines, depending upon how thick they should be
# and whether we get the 'inner' or 'outer'.
bw_outline = load_image('images/outline.png') > 0
bw_outlined = ndimage.binary_dilation(bw_outline) ^ bw_outline

# Fill holes
bw_fill = load_image('images/fill_holes.png') > 0
bw_filled = ndimage.binary_fill_holes(bw_fill)

# ndimage doesn't include skeletonize - so use skimage instead
# (Note that different skeletonize algorithms might give different results)
from skimage.morphology import skeletonize
bw_skeletonize = load_image('images/skeletonize.png') > 0
bw_skeletonized = skeletonize(bw_skeletonize)

# Show original concatenated with the filtered images
show_image(np.vstack((bw_outline, bw_outlined)), title="(A) Outline", pos=131)
show_image(np.vstack((bw_fill, bw_filled)), title="(B) Fill holes", pos=132)
show_image(np.vstack((bw_skeletonize, bw_skeletonized)), title="(C) Skeletonize", pos=133)
glue_fig('fig_outline_fill_skeleton', fig)
../../../_images/063a806c1efea730892f9c9f71aa0c4ae3e4d6ed92478986acb31a5ed19fb1f1.png

Fig. 116 The effects of the Outline, Fill holes and Skeletonize commands.#

The outline of an object in a binary image can also be determined by applying one other morphological operation to a duplicate of the image, and then using the Image Calculator. How?

To outline the objects in a binary image, you can simply calculate the difference between the original image and an eroded (or dilated, if you want the pixels just beyond the objects) duplicate of the image.

Other morphological operations#

ImageJ doesn’t contain an implementation of morphological reconstruction, and therefore doesn’t support all the extra operations that derive from it.

However, there’s an extremely library called MorphoLibJ that can be added to ImageJ or Fiji, which contains morphological reconstruction and much more.

Check out the excellent documentation at https://imagej.net/plugins/morpholibj for more details.