Morphological Operations

What are Morphological Operations?

Morphological operations: Processing based on shapes

Work on: Binary images (black/white) or grayscale

Structuring element (kernel): Defines neighborhood shape

  • Rectangle, ellipse, cross, custom

Applications:

  • Noise removal
  • Shape analysis
  • Object extraction
  • Skeletonization

Basic Operations

Erosion: Shrinks bright regions

  • Sets pixel to minimum in neighborhood
  • Removes small white noise
  • Disconnects objects

Dilation: Expands bright regions

  • Sets pixel to maximum in neighborhood
  • Fills small holes
  • Connects nearby objects

Formula:

  • Erosion: min(neighborhood)
  • Dilation: max(neighborhood)

Erosion

  1. import cv2
  2. import numpy as np
  3. # binary image
  4. _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
  5. # create structuring element
  6. #ans: kernel = np.ones((5, 5), np.uint8)
  7. #ans: can also use cv2.getStructuringElement()
  8. # erosion
  9. #ans: eroded = cv2.erode(binary, kernel, iterations=1)
  10. #ans: iterations: number of times to apply
  11. # effect: shrinks white regions, removes small noise
  12. #ans: larger kernel or more iterations = more erosion

Dilation

  1. # dilation
  2. #ans: dilated = cv2.dilate(binary, kernel, iterations=1)
  3. # effect: expands white regions, fills small holes
  4. #ans: larger kernel or more iterations = more dilation
  5. # multiple iterations
  6. dilated = cv2.dilate(binary, kernel, iterations=3)
  7. #ans: equivalent to applying 3 times

Opening

Opening: Erosion followed by dilation

Effect:

  • Removes small white noise
  • Preserves shape of large objects
  • Breaks thin connections

Use case: Noise removal without shrinking objects

Opening in OpenCV

  1. kernel = np.ones((5, 5), np.uint8)
  2. # opening = erosion + dilation
  3. #ans: opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)
  4. # equivalent to:
  5. #ans: eroded = cv2.erode(binary, kernel)
  6. #ans: opening = cv2.dilate(eroded, kernel)
  7. # removes small white noise, preserves large shapes

Closing

Closing: Dilation followed by erosion

Effect:

  • Fills small holes
  • Connects nearby objects
  • Closes gaps

Use case: Fill holes in objects, connect broken parts

Closing in OpenCV

  1. # closing = dilation + erosion
  2. #ans: closing = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
  3. # equivalent to:
  4. #ans: dilated = cv2.dilate(binary, kernel)
  5. #ans: closing = cv2.erode(dilated, kernel)
  6. # fills small black holes in white regions

Morphological Gradient

Gradient: Difference between dilation and erosion

Effect: Outlines edges of objects

Formula: dilation(img) - erosion(img)

  1. # morphological gradient
  2. #ans: gradient = cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel)
  3. # equivalent to:
  4. #ans: dilated = cv2.dilate(binary, kernel)
  5. #ans: eroded = cv2.erode(binary, kernel)
  6. #ans: gradient = dilated - eroded
  7. # highlights object boundaries

Top Hat

Top hat: Difference between image and opening

Effect: Extracts small bright features

Formula: img - opening(img)

  1. # top hat
  2. #ans: tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel)
  3. # extracts bright regions smaller than kernel
  4. #ans: useful for extracting bright objects on dark background

Black Hat

Black hat: Difference between closing and image

Effect: Extracts small dark features

Formula: closing(img) - img

  1. # black hat
  2. #ans: blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)
  3. # extracts dark regions smaller than kernel
  4. #ans: useful for extracting dark objects on bright background

Structuring Elements

  1. # rectangular kernel
  2. #ans: rect = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
  3. # elliptical kernel
  4. #ans: ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
  5. # cross-shaped kernel
  6. #ans: cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
  7. # custom kernel
  8. custom = np.array([[0, 1, 0],
  9. [1, 1, 1],
  10. [0, 1, 0]], np.uint8)
  11. #ans: cross-shaped, equivalent to MORPH_CROSS

Exercises - Part 1 (Concepts)

  1. # what is erosion?
  2. #ans: shrinks bright regions, sets pixel to neighborhood minimum
  3. # what is dilation?
  4. #ans: expands bright regions, sets pixel to neighborhood maximum
  5. # what is opening?
  6. #ans: erosion then dilation, removes noise
  7. # what is closing?
  8. #ans: dilation then erosion, fills holes
  9. # what is morphological gradient?
  10. #ans: dilation minus erosion, outlines edges

Exercises - Part 2 (Concepts)

  1. # when to use opening?
  2. #ans: remove small white noise, preserve object shape
  3. # when to use closing?
  4. #ans: fill small holes, connect broken parts
  5. # what is top hat?
  6. #ans: img - opening, extracts small bright features
  7. # what is black hat?
  8. #ans: closing - img, extracts small dark features
  9. # effect of larger kernel?
  10. #ans: more aggressive operation, affects larger structures

Exercises - Part 3 (Coding)

  1. # erosion with 3x3 kernel
  2. kernel = np.ones((3, 3), np.uint8)
  3. #ans: eroded = cv2.erode(binary, kernel, iterations=1)
  4. # dilation with 5x5 kernel
  5. kernel = np.ones((5, 5), np.uint8)
  6. #ans: dilated = cv2.dilate(binary, kernel, iterations=1)
  7. # opening
  8. kernel = np.ones((5, 5), np.uint8)
  9. #ans: opening = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)

Exercises - Part 4 (Coding)

  1. # closing
  2. kernel = np.ones((5, 5), np.uint8)
  3. #ans: closing = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
  4. # morphological gradient
  5. #ans: gradient = cv2.morphologyEx(binary, cv2.MORPH_GRADIENT, kernel)
  6. # elliptical kernel
  7. #ans: ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
  8. #ans: result = cv2.morphologyEx(binary, cv2.MORPH_OPEN, ellipse)

Exercises - Part 5 (Mixed)

  1. # top hat with 9x9 kernel
  2. kernel = np.ones((9, 9), np.uint8)
  3. #ans: tophat = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel)
  4. # black hat
  5. #ans: blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel)
  6. # multiple erosions
  7. kernel = np.ones((3, 3), np.uint8)
  8. #ans: eroded = cv2.erode(binary, kernel, iterations=3)
  9. # cross-shaped structuring element
  10. #ans: cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
  11. #ans: result = cv2.morphologyEx(binary, cv2.MORPH_OPEN, cross)

Google tag (gtag.js)