En este artículo, aprenderemos a implementar el etiquetado y el análisis de componentes conectados mediante OpenCV en Python.
Etiquetado de componentes conectados
El etiquetado de componentes consiste básicamente en extraer una región de la imagen original, excepto que tratamos de encontrar solo los componentes que están «conectados», lo que está determinado por la aplicación de la teoría de grafos.
OpenCV nos proporciona las siguientes 4 funciones para esta tarea:
- cv2.componentes conectados
- cv2.componentes conectados con estadísticas
- cv2.componentesconectadosConAlgoritmo
- cv2.componentesconectadosConEstadísticasConAlgoritmo
Los dos últimos son más eficientes y rápidos, pero solo se ejecutan si tiene habilitado el preprocesamiento paralelo con OpenCV; de lo contrario, es más inteligente ceñirse a los dos primeros. Tanto el primer como el segundo método son iguales, excepto que en el segundo método, como sugiere el nombre, obtenemos estadísticas para cada uno de los componentes y usaremos el segundo método porque en la mayoría de los casos necesitará esas estadísticas. .
En este programa, vamos a usar una imagen de banner para extraer los componentes de texto, la siguiente imagen muestra el resultado final de nuestro programa:
Instalación de dependencias
Comencemos instalando los paquetes necesarios:
$ pip install opencv-contrib-python
Paso 1: Carga y preprocesamiento de imágenes
Primero carguemos nuestra imagen y convirtámosla en una imagen en escala de grises, esto hace que el algoritmo sea mucho más eficiente y preciso. Después de esto, también aplicaremos un desenfoque gaussiano de 7 × 7, esto ayuda a eliminar los bordes no deseados y ayuda a una segmentación mucho más clara, lo que haremos en el siguiente paso.
Python3
# Applying threshold threshold = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
Paso 2: Umbral
La umbralización es una técnica de segmentación de imágenes muy básica que nos ayuda a separar el fondo y los objetos de primer plano que nos interesan. Después de aplicar el desenfoque, usaremos la función cv2.threshold para segmentar la imagen.
Python3
# Applying threshold threshold = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
Paso 3: Aplicación del método de análisis de componentes
Primero aplicamos cv2.connectedComponentsWithStats y luego desempaquetamos los valores que devuelve en diferentes variables que usaremos en los siguientes pasos, y también creemos una nueva array para almacenar todos los componentes que encontremos.
Python3
# Apply the Component analysis function analysis = cv2.connectedComponentsWithStats(threshold, 4, cv2.CV_32S) (totalLabels, label_ids, values, centroid) = analysis # Initialize a new image to # store all the output components output = np.zeros(gray_img.shape, dtype="uint8")
Ahora que tenemos nuestros componentes y análisis, repasemos cada uno de los componentes y filtremos los componentes útiles.
Paso 4: filtrar los componentes útiles
Recorramos cada uno de los componentes y usemos las estadísticas que obtuvimos en el último paso para filtrar los componentes útiles. Por ejemplo, aquí he usado el valor de Área para filtrar solo los caracteres de la imagen. Y después de filtrar los componentes, usaremos la variable label_ids para crear una máscara para el componente que estamos recorriendo y usaremos la operación bitwise_or en la máscara para generar nuestro resultado final. Suena difícil, pero lo entenderá mejor después de implementar el código usted mismo.
Python3
# Loop through each component for i in range(1, totalLabels): area = values[i, cv2.CC_STAT_AREA] if (area > 140) and (area < 400): # Labels stores all the IDs of the components on the each pixel # It has the same dimension as the threshold # So we'll check the component # then convert it to 255 value to mark it white componentMask = (label_ids == i).astype("uint8") * 255 # Creating the Final output mask output = cv2.bitwise_or(output, componentMask)
¿Cómo seleccionar el valor de Área (o cualquier otra condición como ancho o alto) para filtrar?
Agregue una declaración de impresión para imprimir el valor de la estadística que desea usar como condición y luego, para los componentes útiles, anote el rango de valores y utilícelos para crear la condición de filtro.
Paso 5: Visualice el resultado final
Ahora nuestro paso final es simplemente mostrar nuestra imagen original y la máscara final que obtuvimos.
Python3
cv2.imshow("Image", img) cv2.imshow("Filtered Components", output) cv2.waitKey(0)
A continuación se muestra la implementación:
Python3
import cv2 import numpy as np # Loading the image img = cv2.imread('Images/img5.png') # preprocess the image gray_img = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY) # Applying 7x7 Gaussian Blur blurred = cv2.GaussianBlur(gray_img, (7, 7), 0) # Applying threshold threshold = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] # Apply the Component analysis function analysis = cv2.connectedComponentsWithStats(threshold, 4, cv2.CV_32S) (totalLabels, label_ids, values, centroid) = analysis # Initialize a new image to store # all the output components output = np.zeros(gray_img.shape, dtype="uint8") # Loop through each component for i in range(1, totalLabels): # Area of the component area = values[i, cv2.CC_STAT_AREA] if (area > 140) and (area < 400): componentMask = (label_ids == i).astype("uint8") * 255 output = cv2.bitwise_or(output, componentMask) cv2.imshow("Image", img) cv2.imshow("Filtered Components", output) cv2.waitKey(0)
Producción:
Nota: Ejecute el programa en una cantidad de imágenes grandes y pequeñas para que vea que la salida consistió en mucho «ruido». Por lo tanto, aplicamos el «filtro» en la última ejecución, el resultado final que obtuvimos solo tenía los caracteres de texto que queríamos.
Etiquetado y análisis de componentes conectados de OpenCV:
Aquí hay otra implementación donde he demostrado todo el proceso para cada componente para que sea más fácil de visualizar:
Python3
import cv2 import numpy as np # Loading the image img = cv2.imread('Images/img5.png') # preprocess the image gray_img = cv2.cvtColor(img , cv2.COLOR_BGR2GRAY) # Applying 7x7 Gaussian Blur blurred = cv2.GaussianBlur(gray_img, (7, 7), 0) # Applying threshold threshold = cv2.threshold(blurred, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] # Apply the Component analysis function analysis = cv2.connectedComponentsWithStats(threshold, 4, cv2.CV_32S) (totalLabels, label_ids, values, centroid) = analysis # Initialize a new image to # store all the output components output = np.zeros(gray_img.shape, dtype="uint8") # Loop through each component for i in range(1, totalLabels): # Area of the component area = values[i, cv2.CC_STAT_AREA] if (area > 140) and (area < 400): # Create a new image for bounding boxes new_img=img.copy() # Now extract the coordinate points x1 = values[i, cv2.CC_STAT_LEFT] y1 = values[i, cv2.CC_STAT_TOP] w = values[i, cv2.CC_STAT_WIDTH] h = values[i, cv2.CC_STAT_HEIGHT] # Coordinate of the bounding box pt1 = (x1, y1) pt2 = (x1+ w, y1+ h) (X, Y) = centroid[i] # Bounding boxes for each component cv2.rectangle(new_img,pt1,pt2, (0, 255, 0), 3) cv2.circle(new_img, (int(X), int(Y)), 4, (0, 0, 255), -1) # Create a new array to show individual component component = np.zeros(gray_img.shape, dtype="uint8") componentMask = (label_ids == i).astype("uint8") * 255 # Apply the mask using the bitwise operator component = cv2.bitwise_or(component,componentMask) output = cv2.bitwise_or(output, componentMask) # Show the final images cv2.imshow("Image", new_img) cv2.imshow("Individual Component", component) cv2.imshow("Filtered Components", output) cv2.waitKey(0)
Producción:
Publicación traducida automáticamente
Artículo escrito por bobde_yagyesh y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA