La umbralización o thresholding consiste en obtener una representación binaria de una imagen, por medio de la modificación de los píxeles. El valor de los píxeles se modificaran segun un valor umbral que establezcamos. En este post revisaremos tres tipos de umbralización: Umbralización simple, adaptativa y Otzu
Umbralización (thresholding) simple
La umbralización simple consiste el modificar el valor de un píxel si sobrepasa el umbral establecido. Existen varios tipos de umbralización simple establecidos en la documentación de openCV como:THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV
Para describir la umbralización simple uso la imagen en escala de grises que matiza desde 0 a 255.
Los píxeles de tonalidad más oscura estarán cerca de 0
y los más claros cerca de 255
. (Si no puedes hacer zoom el los pixeles, ejecuta tu código en un entorno virtual conda.
Para aplicar la umbralización simple se usa el siguiente comando en python:
ret,thresh = cv2.threshold(img, umbral, valorMax , tipo)
Los parámetros son los siguientes:
img
es la imagen gris que va a ser analizadaumbral
es el valor indicado a analizar en cada píxelvalorMax
Valor que se coloca a un píxel si sobrepasa el umbraltipo
se elige un tipo de umbralización
La función devuelve:
thresh
imagen binarizadaret
valor del umbral
En la siguente imagen, los píxeles por donde pasa la línea punteada tendrán el valor de 100
. En los siguientes ejemplos considero que el umbral es 100, lo que significa que se verán cambios en la umbralización a la derecha e izquierda de la línea punteada.
THRESH_BINARY
Si el píxel (src(x,y)
) supera el umbral (thresh
), en la imagen binarizada dst(x,y)
a los píxeles que superaron el umbral se les asigna el valor máximo establecido (maxval
en este ejemplo es 255). A continuación el código.
import cv2
img = cv2.imread('matizGris.png',0)
ret,thresh = cv2.threshold(img,100,255,cv2.THRESH_BINARY)
cv2.imshow("Imagen", img)
cv2.imshow("THRESH", thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
Los píxeles que superaron el valor de 100
, ahora son todos 255
y los que no superaron el umbral ahora tiene el valor de 0
THRESH_BINARY_INV
Si el píxel (src(x,y)
) supera el umbral (thresh
), en la imagen binarizada dst(x,y)
a los píxeles que superaron el umbral se les asigna cero 0
y a los que no superaron el umbral se les asigna el valor máximo establecido (maxval
en este ejemplo es 255). Debemos añadir esta línea en el código.
ret,thresh = cv2.threshold(img,100,255,cv2.THRESH_BINARY)
THRESH_TRUNC
Si el píxel (src(x,y)
) supera el umbral (thresh
), en la imagen binarizada dst(x,y)
a los píxeles que superaron el umbral se les asigna el mismo valor del umbral y a los que no superaron el umbral se les asigna los mismos valores que tenían originalmente. A continuación el código.
ret,thresh = cv2.threshold(img,100,255,cv2.THRESH_TRUNC)
THRESH_TOZERO
Si el píxel (src(x,y)
) supera el umbral (thresh
), en la imagen binarizada a los píxeles que superaron el umbral mantienen el valor de los pixeles originalmente, y cuando no superan el umbral se les asigna cero. A continuación el código.
ret,thresh = cv2.threshold(img,100,255,cv2.THRESH_TOZERO)
THRESH_TOZERO_INV
Si el píxel (src(x,y)
) supera el umbral (thresh
), en la imagen binarizada a los píxeles que superaron el umbral se les asigna cero, y a los píxeles que no superaron el umbral se les asigna el mismo valor que originalmente tenías. A continuación el código.
ret,thresh = cv2.threshold(img,100,255,cv2.THRESH_TOZERO_INV)
Umbralización (thresholding) adaptativa
Usare la imagen de una página para mostrar como puede mejorar la umbralización con un método adaptativo. En la imagen de la derecha vemos como la umbralización simple no da buenos resultados con variaciones de iluminación.
Página con variaciones de iluminación
Umbralización simple, THRESH_BINARY_INV
A diferencia de la umbralización simple, la umbralización adaptativa no tendrá un valor umbral establecido. Sino que el “algoritmo determina el umbral de un píxel en función de una pequeña región a su alrededor. Entonces obtenemos diferentes umbrales para diferentes regiones de la misma imagen, lo que brinda mejores resultados para imágenes con iluminación variable” 1.
Se puede seleccionar entre dos métodos adaptativos, que son los que deciden como se va a calcular el valor umbral:
cv.ADAPTIVE_THRESH_MEAN_C
cv.ADAPTIVE_THRESH_GAUSSIAN_C
threshold = cv2.adaptiveThreshold(img,maxValue,adaptiveMethod,thresholdType,blockSize,C)
img
es una imagen de un solo canal, debe ser en escala de grisesmaxValue
valor asignado a los pixeles cuando cumplen la condiciónadaptiveMethod
método adaptativo, se elige entrecv.ADAPTIVE_THRESH_MEAN_C
,cv.ADAPTIVE_THRESH_GAUSSIAN_C
thresholdType
elegir un método de umbralizaciónblockSize
Tamaño de una vecindad de píxeles que se utiliza para calcular un valor de umbral para el píxel: 3, 5, 7, etcC
Constante restada de la media o media ponderada
El código a continuación, muestra como la umbralización adaptativa funciona. El tamaño del bloque lo establezco como 11
y la contante C como 10 siguiendo el ejemplo de openCV documents, pero más adelante probaré con otros valores.
import cv2
img = cv2.imread('libro.jpg',0)
th1 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,11,10)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,10)
cv2.imshow("ADAPTIVE_THRESH_MEAN_C", th1)
cv2.imshow("ADAPTIVE_THRESH_GAUSSIAN_C", th2)
cv2.waitKey(0)
cv2.destroyAllWindows()
ADAPTIVE_THRESH_MEAN_C
ADAPTIVE_THRESH_GAUSSIAN_C
Método de Otsu
A diferencia del la umbralización simple, Otsu calcula automáticamente un umbral para toda la imagen. Y a diferencia de la umbralización adaptativa, el umbral es el mismo en toda la imagen y no varía por regiones.
import cv2
img = cv2.imread('libro.jpg',0)
ret1, th1 = cv2.threshold(img,0,255,cv2.THRESH_OTSU)
print('Umbral de th1:', ret1)
cv2.imshow("Imagen", img)
cv2.imshow("THRESH_OTSU", th1)
cv2.waitKey(0)
cv2.destroyAllWindows()
Inicialmente los valores del umbral los establecí aleatoriamente, y luego al ejecutar el método de Otsu, en la consola se imprime los valores del umbral que estableció automáticamente el algoritmo de Otsu. Puse 3 imágenes para ver como el algoritmo encuentra diferentes umbrales.
Umbral de th1: 150.0
El resultado de Otsu es el siguiente, para la imagen del libro:
Referencias
- OpenCV documentación. Image Thresholding. https://docs.opencv.org/4.5.2/d7/d4d/tutorial_py_thresholding.html
This is a topic which is near to my heart… Best wishes!
Exactly where are your contact details though?
Hello! For now you can leave your suggestions in the comments on YouTube and the Blog. Thanks for your comment.