ImageMorph Module

doc

https://pillow.readthedocs.io/en/latest/reference/ImageMorph.html

A binary morphology add-on for the Python Imaging Library.

with known patterns

import os
from PIL import Image, ImageMorph
from PIL.ImageMorph import LutBuilder, MorphOp

for bn in (
    "binary_shapes_01",
    "binary_noisy_letters_01",
    "binary_noisy_letters_02",
    ):

    img = Image.open(os.path.join("data", bn + ".jpg"))
    img.load()  # MorphOp.apply expects image are loaded.

    for op_name in (
        'corner',
        'dilation4', 'dilation8',
        'erosion4', 'erosion8',
        'edge',
        ):
        lb = LutBuilder(op_name=op_name)
        mop = MorphOp(lb.build_lut())
        _, dimg = mop.apply(img)
        dimg.save(
            os.path.join(
                "result",
                "ImageMorph01_" + bn + "_" + op_name + ".jpg"))

ImageMorph_src1 src

ImageMorph_src2 src

ImageMorph_src3 src

ImageMorph01.res13 corner

ImageMorph01.res01 corner

ImageMorph01.res07 corner

ImageMorph01.res14 dilation4

ImageMorph01.res02 dilation4

ImageMorph01.res08 dilation4

ImageMorph01.res15 dilation8

ImageMorph01.res03 dilation8

ImageMorph01.res09 dilation8

ImageMorph01.res16 edge

ImageMorph01.res04 edge

ImageMorph01.res10 edge

ImageMorph01.res17 erosion4

ImageMorph01.res05 erosion4

ImageMorph01.res11 erosion4

ImageMorph01.res18 erosion8

ImageMorph01.res06 erosion8

ImageMorph01.res12 erosion8

with custom structuring element

Example 1: identical to op_name="erosion4"

>>> import numpy as np
>>> from PIL import Image, ImageMorph
>>> from PIL.ImageMorph import LutBuilder, MorphOp
>>> img = Image.open("data/binary_shapes_01.jpg")  # mode="L"
>>> img.load()  # MorphOp.apply expects image are loaded.
<PixelAccess object at 0x0000000002B1DB90>
>>> # 'erosion4': [
... #     '4:(... .1. .0. )->0'
... # ]
... lb1 = LutBuilder(op_name='erosion4')
>>> _, dimg1 = MorphOp(lb1.build_lut()).apply(img)
>>> #
... erosion4_identical1 = [
...      '1:(... .1. .0.)->0',  # B -> out pixel off if fit
...      '1:(... .10 ...)->0',  # B.rotate(90) -> out pixel off if fit
...      '1:(.0. .1. ...)->0',  # B.rotate(180) -> out pixel off if fit
...      '1:(... 01. ...)->0'   # B.rotate(270) -> out pixel off if fit
...      ]
>>> lb2 = LutBuilder(patterns=erosion4_identical1)
>>> _, dimg2 = MorphOp(lb2.build_lut()).apply(img)
>>> # identical?
... all(np.array(dimg1.getdata()) == np.array(dimg2.getdata()))
True
>>> #
... erosion4_identical2 = [
...      '1:(... .1. .0.)->0',  # B -> out pixel off if fit
...      'M:(... .10 ...)->0',  # B.rotate(90), B.rotate(270) -> out pixel off if fit
...      '1:(.0. .1. ...)->0',  # B.rotate(180) -> out pixel off if fit
...      ]
>>> lb3 = LutBuilder(patterns=erosion4_identical2)
>>> _, dimg3 = MorphOp(lb3.build_lut()).apply(img)
>>> # identical?
... all(np.array(dimg1.getdata()) == np.array(dimg3.getdata()))
True

Example 2: ‘N’ (Negate)

Warning

This demo doesn’t work with pillow version <= 4.1.1. See issue #2590.

>>> import numpy as np
>>> from PIL import Image, ImageMorph
>>> from PIL.ImageMorph import LutBuilder, MorphOp
>>> img = Image.open("data/binary_shapes_01.jpg")  # mode="L"
>>> img.load()  # MorphOp.apply expects image are loaded.
<PixelAccess object at 0x0000000002B3DC30>
>>> #
... my_se1 = [
...      '''1:(000
...            010
...            000)->1''',
...      ]
>>> lb1 = LutBuilder(patterns=my_se1)
>>> _, dimg1 = MorphOp(lb1.build_lut()).apply(img)
>>> #
... my_se2 = [
...      '''N:(111
...            101
...            111)->0''',  # Negate
...      ]
>>> lb2 = LutBuilder(patterns=my_se2)
>>> _, dimg2 = MorphOp(lb2.build_lut()).apply(img)
>>> # identical?
... all(np.array(dimg1.getdata()) == np.array(dimg2.getdata()))
True