Logo de CursoIA
CursoIA Curso de Inteligencia Artificial

Visión por computador desde cero, Unidad 6 — Detección de bordes, 6.2 — Operadores clásicos ·

Canny (intuición)

Canny (intuición)

Introducción

La detección de bordes es un paso fundamental en la visión por computador. Permite que las máquinas identifiquen y segmenten regiones significativas en imágenes, lo cual es crucial para muchas aplicaciones, desde robótica hasta reconocimiento facial. En este artículo, exploraremos el operador Canny de forma intuitiva, comprendiendo cómo funciona y cuándo se debe aplicar.

Explicación principal

El operador Canny fue desarrollado por John F. Canny en 1986. Es considerado uno de los algoritmos más efectivos para la detección de bordes debido a su capacidad de equilibrar entre minimizar falsos positivos y falsos negativos, así como mantener las características relevantes del borde.

Paso 1: Gradiente

El Canny comienza identificando los puntos de mayor intensidad en el gradiente. Esto se hace aplicando un operador diferencial (como el operador de Sobel) a la imagen. El resultado es una matriz donde cada punto representa la dirección y magnitud del cambio en la intensidad.

import cv2
import numpy as np

# Cargar una imagen en escala de grises
img = cv2.imread('imagen.jpg', 0)

# Calcular el gradiente utilizando Sobel
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)

# Calcular la magnitud del gradiente
grad_magnitude = np.sqrt(sobelx**2 + sobely**2)

Paso 2: Detección de direcciones

Después de obtener el gradiente, Canny identifica en qué dirección se produce el cambio más intenso. Esto permite distinguir entre bordes horizontales, verticales y diagonales.

Paso 3: Supresión de no-maxima

Este paso es crucial para eliminar falsos positivos. En esta etapa, se suprimen los puntos del gradiente que no son el máximo local en su dirección. Esto significa que solo se conservan los puntos que tienen la máxima intensidad en su vecindad.

import cv2
import numpy as np

# Calcular la dirección angular del gradiente
theta = np.arctan2(sobely, sobelx)

def non_max_suppression(magnitude, theta):
    h, w = magnitude.shape[:2]
    suppressed = np.zeros((h, w))
    
    for i in range(1, h-1):
        for j in range(1, w-1):
            angle = theta[i, j] * 180. / np.pi
            if (angle < 0): 
                angle += 180
            
            # Comprobar si el punto es un máximo local en su dirección angular
            if ((angle == 45 or angle == -45) and magnitude[i, j] <= magnitude[i+1, j-1]) or \
               (angle == 90 and magnitude[i, j] <= magnitude[i+1, j]) or \
               (angle == 135 or angle == -135) and magnitude[i, j] <= magnitude[i+1, j+1]:
                suppressed[i, j] = 0
            else:
                suppressed[i, j] = magnitude[i, j]
    
    return suppressed

suppressed_edges = non_max_suppression(grad_magnitude, theta)

Paso 4: Umbralización

El último paso es aplicar umbralización para determinar qué bordes son reales. Esto implica establecer un umbral bajo y uno alto. Los puntos con una intensidad superior al umbral alto se mantienen, mientras que los puntos entre el umbral bajo y alto pueden ser puestos a cero o conectados a los bordes más cercanos.

def double_thresholding(suppressed_edges, lowThresholdRatio=0.1, highThresholdRatio=0.2):
    h, w = suppressed_edges.shape[:2]
    highThreshold = np.max(suppressed_edges) * highThresholdRatio
    lowThreshold = highThreshold * lowThresholdRatio

    strong_edges = np.zeros((h, w))
    weak_edges = np.zeros((h, w))

    for i in range(h):
        for j in range(w):
            if suppressed_edges[i, j] > highThreshold:
                strong_edges[i, j] = 255
            elif suppressed_edges[i, j] < lowThreshold:
                weak_edges[i, j] = 1

    return strong_edges, weak_edges

strong_edges, weak_edges = double_thresholding(suppressed_edges)

Errores típicos / trampas

  1. Umbralización inadecuada: Un umbral bajo puede capturar muchos ruidos y bordes irrelevantes, mientras que un umbral alto puede omitir algunos bordes importantes.
  2. Detección de direcciones imprecisa: La dirección del gradiente se detecta con una precisión limitada (generalmente en 45° o 90°), lo que puede llevar a la supresión incorrecta de algunos bordes.
  3. Ruido en el gradiente: El ruido en las imágenes puede distorsionar los valores del gradiente, afectando negativamente al algoritmo.

Checklist accionable

  1. Verificar el umbral adecuado: Experimenta con diferentes umbrales para encontrar uno que no capture ruidos innecesarios y muestre todos los bordes relevantes.
  2. Ajustar la supresión de no-maxima: Asegúrate de que la supresión se realiza correctamente en todas las direcciones del gradiente.
  3. Tratar el ruido: Aplica técnicas de filtrado antes de aplicar Canny para reducir el ruido innecesario.

Siguientes pasos

  • Aprender más sobre Deep Learning: Los algoritmos basados en redes neuronales profundas pueden superar a los tradicionales como Canny, especialmente cuando se trata de tareas complejas.
  • Practicar con diferentes imágenes: Experimenta con diferentes tipos de imágenes para entender mejor cómo Canny se comporta bajo variadas condiciones.

Siguiendo estos pasos, podrás aplicar el operador Canny con mayor confianza y efectividad en tus proyectos de visión por computador.

Contacto

Indica tu objetivo (ChatGPT, RAG, agentes, automatización) y tu stack (web/backend).