Saltar al contenido principal

Operaciones morfológicas

info

Todo el código de ejemplo se encuentra en Google Colab para su ejecución directa. Si no puedes ejecutar OpenCV localmente, puedes usar Google Colab junto con matplotlib para visualizar imágenes. Además la imagen que se utilizará en los ejemplos son imagen.png.

Objetivo

  • Aprender los principales métodos de operaciones morfológicas aplicados a imágenes.
  • Comprender cómo el kernel modifica la forma y estructura de los objetos en una imagen.
  • Aplicar erosión, dilatación, apertura, cierre, gradiente, top-hat y black-hat en OpenCV para preprocesamiento y análisis.

Conceptos clave

  • Kernel: matriz que define la forma y vecindad usada en la operación morfológica.
  • Erosión: reduce las regiones brillantes de una imagen.
  • Dilatación: expande las regiones brillantes de una imagen.
  • Apertura: erosión seguida de dilatación, elimina ruido pequeño.
  • Cierre: dilatación seguida de erosión, rellena huecos pequeños.
  • Gradiente morfológico: diferencia entre dilatación y erosión, resalta bordes.
  • Sombrero de copa (top-hat): diferencia entre la imagen original y su apertura, resalta detalles claros.
  • Sombrero negro (black-hat): diferencia entre el cierre y la imagen original, resalta detalles oscuros.

Funciones principales en OpenCV

  • cv.erode(): Aplica erosión a la imagen usando un kernel.
  • cv.dilate(): Aplica dilatación a la imagen usando un kernel.
  • cv.morphologyEx(): Aplica operaciones morfológicas avanzadas:
    • cv.MORPH_OPEN: Apertura.
    • cv.MORPH_CLOSE: Cierre.
    • cv.MORPH_GRADIENT: Gradiente morfológico.
    • cv.MORPH_TOPHAT: Sombrero de copa.
    • cv.MORPH_BLACKHAT: Sombrero negro.

Teoría de operaciones morfológicas

Las operaciones morfológicas provienen de la teoría matemática de la morfología, utilizada originalmente para el análisis de estructuras en imágenes binarias. La idea central es modificar la geometría de los objetos presentes en la imagen en función de la forma del kernel.

Existen dos transformaciones básicas:

  • Erosión: Encoge los objetos.
  • Dilatación: Expande los objetos.

A partir de ellas se definen transformaciones combinadas que permiten limpiar ruido, rellenar huevos o destacar contornos.

img con operación morfológica

Figura 1: Imagen original vs. Imagen con erosión vs. Imagen con dilatación.

Erosión

La erosión reduce el tamaño de los objetos brillantes (blancos) en una imagen. El kernel "desgasta" los bordes, eliminando pequeños detalles o ruido aislado.

  • Útil para: Eliminar puntos blancos pequeños o separar objetos pegados.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de la operación de erosión
erosion = cv.erode(
img, # Imagen de entrada
kernel, # Kernel
iterations = 1) # Número de iteraciones para aplicar la erosión

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(erosion, cmap="gray"),plt.title('Imagen con erosión')
plt.xticks([]), plt.yticks([])
plt.show()

Dilatación

La dilatación expande las regiones brillantes, haciendo que los objetos crezcan. Tiende a rellenar huevos y a unir componentes cercanos.

  • Útil para: Destacar características, unir fragmento de un objeto o rellenar espacios.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de dilatación
dilation = cv.dilate(
img, # Imagen de entrada
kernel, # Kernel
iterations = 1) # Número de iteraciones

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dilation, cmap="gray"),plt.title('Imagen con dilatación')
plt.xticks([]), plt.yticks([])
plt.show()

Apertura

La apertura combina erosión seguida de dilatación. Permite eliminar ruido fino sin afectar demasiado el tamaño de los objetos principales.

  • Útil para: Eliminar pequeños puntos blancos dispersos en el fondo.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de apertura morfológica
opening = cv.morphologyEx(
img, # Imagen de entrada
cv.MORPH_OPEN, # Tipo de operación morfológica
kernel) # Kernel

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(opening, cmap="gray"),plt.title('Imagen con apertura')
plt.xticks([]), plt.yticks([])
plt.show()

Cierre

El cierre combina dilatación seguida de erosión. Tiende a cerrar huecos pequeños o líneas negras dentro de un objeto blanco.

  • Útil para: Rellenar pequeños espacios o grietas dentro de los objetos.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de cierre morfológico
closing = cv.morphologyEx(
img, # Imagen de entrada
cv.MORPH_CLOSE, # Tipo de operación morfológica
kernel) # Kernel

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(closing, cmap="gray"),plt.title('Imagen con cierre')
plt.xticks([]), plt.yticks([])
plt.show()

Gradiente morfológico

El gradiente morfológico es la diferencia entre la dilatación y la erosión de una imagen. Resalta los bordes de los objetos, ya que muestra las zonas donde la forma cambia.

  • Útil para: Detección de contornos.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de gradiente morfológico
gradient = cv.morphologyEx(
img, # Imagen de entrada
cv.MORPH_GRADIENT, # Tipo de operación morfológica
kernel) # Kernel

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(gradient, cmap="gray"),plt.title('Imagen con gradiente morfológico')
plt.xticks([]), plt.yticks([])
plt.show()

Sombrero de copa (Top-hat)

El sombrero de copa es la diferencia entre la imagen original y su apertura. Resalta las regiones claras que son más pequeñas que el kernel.

  • Útil para: Detectar detalles brillantes
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de sombrero de copa
tophat = cv.morphologyEx(
img, # Imagen de entrada
cv.MORPH_TOPHAT, # Tipo de operación morfológica
kernel) # Kernel

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(tophat, cmap="gray"),plt.title('Imagen con sombrero de copa')
plt.xticks([]), plt.yticks([])
plt.show()

Sombrero negro (Black-hat)

El sombrero de copa es la diferencia entre la imagen original y su apertura. Resalta las regiones claras que son más pequeñas que el kernel.

  • Útil para: Detectar detalles brillantes sobre fondos oscuros.
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('patente_2.png', cv.IMREAD_GRAYSCALE)

# Creación del kernel 5x5
kernel = np.ones((5,5),np.uint8)

# Aplicación de sombrero negro
blackhat = cv.morphologyEx(
img, # Imagen de entrada
cv.MORPH_BLACKHAT, # Tipo de operación morfológica
kernel) # Kernel

# Generar plots de imágenes
plt.figure(figsize=(12, 8))
plt.subplot(121),plt.imshow(img, cmap="gray"),plt.title('Imagen original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(tophat, cmap="gray"),plt.title('Imagen con erosión')
plt.xticks([]), plt.yticks([])
plt.show()