Morphology

Overview

The Morphology sample demonstrates GPU-accelerated morphological image processing using CV-CUDA. It applies a dilation followed by an erosion (equivalent to a morphological close operation) to fill small dark gaps while preserving the main structures of the image. The sample illustrates how to choose a structuring element size and how to supply a workspace tensor when required.

Usage

Basic Usage

Apply morphological close (dilate then erode) with a 5×5 kernel to the default cat image:

python3 morphology.py -i input.jpg

Custom Input

Process a different image and save the result explicitly:

python3 morphology.py -i image.jpg -o cat_morphology.jpg

Command-Line Arguments

Argument

Short Form

Default

Description

--input

-i

tabby_tiger_cat.jpg

Input image file path

--output

-o

cvcuda/.cache/cat_morphology.jpg

Output image file path

Implementation

Morphological Close (Dilate then Erode)

# Wrap the HWC single image in a batch dimension (NHWC) so the morphology
# operator can process it. The operator accepts both HWC and NHWC layouts.
nhwc_image: cvcuda.Tensor = input_image.reshape((1, *input_image.shape), "NHWC")

# A 5x5 rectangular structuring element is large enough to show a visible
# effect on a natural image without destroying structure.
mask_size = [5, 5]
# anchor=[-1, -1] centres the structuring element automatically.
anchor = [-1, -1]

# DILATE expands bright regions — edges become thicker and fine dark lines
# are reduced.  A workspace tensor is not required for a single iteration.
dilated: cvcuda.Tensor = cvcuda.morphology(
    nhwc_image,
    cvcuda.MorphologyType.DILATE,
    mask_size,
    anchor,
    iteration=1,
    border=cvcuda.Border.REPLICATE,
)

# ERODE is the dual of dilation — it shrinks bright regions and removes
# small bright specks.  Running erode after dilate is a CLOSE operation,
# which suppresses small dark artifacts/holes while preserving larger
# structures.
workspace: cvcuda.Tensor = cvcuda.Tensor(
    nhwc_image.shape, nhwc_image.dtype, nhwc_image.layout
)
closed: cvcuda.Tensor = cvcuda.morphology(
    dilated,
    cvcuda.MorphologyType.ERODE,
    mask_size,
    anchor,
    iteration=1,
    border=cvcuda.Border.REPLICATE,
    workspace=workspace,
)

# Remove the batch dimension before writing; write_image expects HWC.
result: cvcuda.Tensor = closed.reshape(closed.shape[1:], "HWC")
write_image(result, args.output)

Key points:

  1. Batch reshape: The HWC tensor returned by read_image is reshaped to NHWC before calling the operator, which accepts both layouts.

  2. Structuring element: mask_size=[5, 5] selects a 5×5 rectangular kernel; anchor=[-1, -1] auto-centres it.

  3. DILATE then ERODE: Applying dilation followed by erosion is a morphological close, which fills small dark holes and gaps while keeping large bright structures intact.

  4. Workspace tensor: A workspace tensor of the same shape and dtype as the input is required when passing the result of one morphological call into a second one; it is used internally by the operator as scratch memory.

  5. Output reshape: The NHWC result is reshaped back to HWC before write_image to produce a standard single-image output.

Expected Output

The output shows the image after morphological closing — small dark gaps are filled and bright regions are slightly expanded:

../../_images/tabby_tiger_cat.jpg

Original Input Image

../../_images/cat_morphology.jpg

Output: Morphological Close (5×5 kernel)

CV-CUDA Operators Used

Operator

Purpose

cvcuda.morphology()

Apply dilation and erosion with a rectangular structuring element

Common Utilities Used

See Also