Skip to main content

Command Palette

Search for a command to run...

Algoritmo de Otsu para la Umbralización y Segmentación de Imágenes

Umbralización automática basada en histogramas

Updated
5 min read
Algoritmo de Otsu para la Umbralización y Segmentación de Imágenes

La umbralización (thresholding) es una técnica básica de segmentación que permite separar una imagen en escala de grises en dos regiones: primer plano y fondo. Este proceso convierte la imagen en una representación binaria comparando la intensidad de cada píxel con un valor de umbral previamente definido, los píxeles con intensidades superiores al umbral se clasifican como objeto, mientras que el resto se considera fondo.

Este enfoque requiere definir un umbral que permita separar correctamente ambas regiones. El análisis del histograma de intensidades resulta especialmente útil en este contexto, ya que, en muchos casos, el fondo y el objeto presentan distribuciones de intensidad diferenciadas.

Los métodos de umbralización automática buscan explotar esta característica para determinar el umbral de manera simple y rapida. Uno de los más utilizados es el algoritmo de Otsu, que selecciona el umbral óptimo maximizando la separabilidad estadística entre las dos clases de píxeles.

¿Cómo funciona?

El algoritmo de Otsu determina automáticamente un umbral global analizando la distribución de intensidades de la imagen. Su objetivo es encontrar el valor de umbral que separa los píxeles en dos clases de la forma más discriminativa posible, basándose únicamente en la información estadística del histograma.

1. Cálculo del histograma
El proceso comienza calculando el histograma de la imagen en escala de grises. Este histograma representa la frecuencia de cada nivel de intensidad y constituye la base para evaluar todos los posibles valores de umbral.

2. Evaluación de umbrales candidatos
Cada posible nivel de intensidad se considera como un umbral candidato. Para un umbral dado, la imagen se divide en dos clases: una correspondiente a los píxeles con intensidades menores o iguales al umbral y otra con intensidades mayores.

3. Cálculo de estadísticas por clase
Para cada una de las dos clases se calculan su peso (proporción de píxeles) y su media de intensidad. Estas magnitudes describen cómo se distribuyen los valores de gris en cada grupo.

4. Varianza entre clases
A partir de los pesos y las medias de ambas clases, se calcula la varianza entre clases, que mide qué tan separadas están estadísticamente. Cuanto mayor es esta varianza, mejor es la separación entre fondo y objeto para ese umbral.

5. Selección del umbral óptimo
El algoritmo recorre todos los umbrales posibles y selecciona aquel que maximiza la varianza entre clases. Este valor corresponde al umbral óptimo, ya que proporciona la mejor separabilidad estadística entre las dos regiones de la imagen.

def OtsuThreshold(I):
    """Implementación del algoritmo de Otsu para encontrar el umbral óptimo."""
    # 1. Calcular el histograma
    hist = CalHistogram(I)
    total_pixels = I.size

    # Inicialización de las medias m0 y m1
    m0 = 0
    m1 = np.sum(np.arange(256) * hist)
    w0 = 0
    w1 = np.sum(hist)

    # 2. Calcular el umbral óptimo
    max_between_class_variance = 0
    optimal_threshold = 0

    # Calcular la varianza intra-clase para cada umbral
    for t in range(1, 256):  # Iterar por todos los posibles umbrales (1 a 255)
        w0 += hist[t - 1]  # Proporción de píxeles en el grupo 0 (fondo)
        w1 -= hist[t - 1]  # Proporción de píxeles en el grupo 1 (objeto)

        # Calcular las medias de los grupos
        m0 += (t - 1) * hist[t - 1]
        m1 -= (t - 1) * hist[t - 1]

        # Si no hay píxeles en el fondo o en el objeto, continuar
        if w0 == 0 or w1 == 0:
            continue

        # Calcular la varianza entre clases
        mean_diff = m0 / w0 - m1 / w1
        between_class_variance = w0 * w1 * mean_diff ** 2

        # Comparar la varianza entre clases
        if between_class_variance > max_between_class_variance:
            max_between_class_variance = between_class_variance
            optimal_threshold = t

    return optimal_threshold

Resultados

Una vez obtenido el umbral óptimo con el algoritmo de Otsu, el siguiente paso consiste en aplicar la binarización de la imagen utilizando ese valor:

thr_ots = lip.OtsuThreshold(img) 
_, binary_img = cv.threshold(img, thr_ots, 255, cv.THRESH_BINARY)

En esta línea, thr_ots corresponde al umbral calculado automáticamente, y binary_img es la imagen binaria resultante, en la que los píxeles del objeto se asignan al valor máximo (255) y los del fondo a cero.

Este procedimiento es un método sencillo y eficiente de umbralización, que funciona particularmente bien cuando el fondo es claramente distinguible del objeto. La facilidad de cálculo y su efectividad en imágenes con histogramas bimodales lo convierten en una herramienta práctica para segmentación rápida y confiable.

El algoritmo de Otsu es un método robusto y eficiente para la umbralización de imágenes en escala de grises, especialmente cuando el fondo y el objeto están claramente diferenciados y el histograma presenta una distribución bimodal. Su simplicidad y capacidad para calcular automáticamente un umbral óptimo lo hacen ideal para tareas de segmentación rápida sin necesidad de calculos manuales.

Limitaciones

Sin embargo, esta técnica presenta limitaciones importantes. En imágenes más complejas, donde el fondo y el objeto exhiben intensidades similares, o donde intervienen sombras, gradientes de iluminación o ruido, la segmentación mediante un único umbral global suele resultar ineficaz. Esto se debe a que dicho enfoque no considera variaciones locales de intensidad, lo que puede conducir a errores en la separación de regiones.

Un ejemplo de esta situación se observa en la imagen de las monedas: aunque el fondo es visualmente distinguible de los objetos, el histograma de intensidades muestra una fuerte concentración en valores superiores a 200.

Esto ocurre debido a la predominancia del fondo blanco y de los tonos grises claros presentes en la imagen, lo que provoca que el método de Otsu no logre una separación adecuada entre fondo y objetos.

Una solución simple consiste en eliminar explícitamente el rango de intensidades correspondiente al fondo. Dado que el fondo se concentra en valores altos de intensidad, se puede aplicar una umbralización por rango para suprimir dichos píxeles.

img_rg, mask_rg = lip.RemoveIntensityRange(img, low=245, high=255, fill=0)

En este caso, se descartan las intensidades comprendidas entre 0 y 245 , asignándoles un valor 255, lo que permite reducir la influencia del fondo y resaltar las regiones de interés antes de aplicar técnicas de segmentación posteriores.

La umbralización y, en particular, el método de Otsu, constituyen herramientas simples y eficientes para la segmentación de imágenes en escala de grises cuando existe una separación clara entre fondo y objeto. No obstante, su carácter global limita su desempeño en escenas más complejas, donde la distribución de intensidades está dominada por el fondo o presenta variaciones locales significativas. En estos casos, resulta necesario complementar la umbralización automática con estrategias adicionales, como la supresión de rangos de intensidad o el uso de espacios de color más adecuados, con el fin de mejorar la separación de las regiones de interés.