Detecta el área de texto en una imagen usando python y opencv

Quiero detectar el área de texto de las imágenes usando python 2.7 y opencv 2.4.9 y dibujar un área de rectángulo a su alrededor. Como se muestra en la imagen de ejemplo a continuación.

Soy nuevo en el procesamiento de imágenes, así que cualquier idea de cómo hacerlo será apreciada.

plano de construcción con habitaciones etiquetadas

Hay varias formas de detectar texto en una imagen.

Recomiendo ver esta pregunta aquí , ya que también puede responder a su caso. Aunque no está en python, el código se puede traducir fácilmente de c ++ a python (solo mire la API y convierta los métodos de c ++ a python, no con dificultad. Lo hice yo mismo cuando probé su código por mi propio problema) . Las soluciones aquí pueden no funcionar para su caso, pero le recomiendo que las pruebe.

Si tuviera que hacer esto, haría el siguiente proceso:

Prepare su imagen: si todas las imágenes que desea editar son aproximadamente como la que proporcionó, donde el diseño real consiste en una gama de colores grises y el texto siempre es negro. Primero eliminaría todo el contenido que no sea negro (o que ya sea blanco). Si lo haces, solo quedará el texto negro a la izquierda.

# must import if working with opencv in python import numpy as np import cv2 # removes pixels in image that are between the range of # [lower_val,upper_val] def remove_gray(img,lower_val,upper_val): hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) lower_bound = np.array([0,0,lower_val]) upper_bound = np.array([255,255,upper_val]) mask = cv2.inRange(gray, lower_bound, upper_bound) return cv2.bitwise_and(gray, gray, mask = mask) 

Ahora que todo lo que tiene es el texto negro, el objective es obtener esos cuadros. Como se dijo antes, hay diferentes maneras de hacer esto.

Transformación de ancho de trazo (SWT)

La forma típica de encontrar áreas de texto: puede encontrar regiones de texto utilizando la transformación de ancho de trazo como se muestra en “Detección de texto en escenas naturales con transformación de ancho de trazo” por Boris Epshtein, Eyal Ofek y Yonatan Wexler. Para ser honesto, si esto es tan rápido y confiable como lo creo, entonces este método es un método más eficiente que mi código de abajo. Sin embargo, aún puede usar el código anterior para eliminar el diseño del proyecto, y eso puede ayudar al rendimiento general del algoritmo swt.

Aquí está la biblioteca de CA que implementa su algoritmo, pero se dice que es muy simple y la documentación está incompleta. Obviamente, se necesitará una envoltura para usar esta biblioteca con python, y en este momento no veo una oferta oficial.

La biblioteca que vinculé es CCV . Es una biblioteca que está diseñada para ser utilizada en sus aplicaciones, no para recrear algoritmos. Así que esta es una herramienta que debe utilizarse, lo que va en contra de la necesidad de OP de hacerlo a partir de los “Primeros principios”, como se indica en los comentarios. Aún así, es útil saber que existe si no desea codificar el algoritmo usted mismo.


Método de elaboración de cerveza no elaborada en casa

Si tiene metadatos para cada imagen, digamos en un archivo xml, que indica cuántas habitaciones están etiquetadas en cada imagen, luego puede acceder a ese archivo xml, obtener los datos sobre cuántas tags hay en la imagen y luego almacenarlos. número en alguna variable por ejemplo, num_of_labels . Ahora tome su imagen y póngala en un bucle while que se erosiona a una tasa establecida que usted especifique, encontrando contornos externos en la imagen en cada bucle y deteniendo el bucle una vez que tenga la misma cantidad de contornos externos que su num_of_labels . Luego simplemente encuentra el cuadro delimitador de cada uno de los contornos y listo.

 # erodes image based on given kernel size (erosion = expands black areas) def erode( img, kern_size = 3 ): retval, img = cv2.threshold(img, 254.0, 255.0, cv2.THRESH_BINARY) # threshold to deal with only black and white. kern = np.ones((kern_size,kern_size),np.uint8) # make a kernel for erosion based on given kernel size. eroded = cv2.erode(img, kern, 1) # erode your image to blobbify black areas y,x = eroded.shape # get shape of image to make a white boarder around image of 1px, to avoid problems with find contours. return cv2.rectangle(eroded, (0,0), (x,y), (255,255,255), 1) # finds contours of eroded image def prep( img, kern_size = 3 ): img = erode( img, kern_size ) retval, img = cv2.threshold(img, 200.0, 255.0, cv2.THRESH_BINARY_INV) # invert colors for findContours return cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) # Find Contours of Image # given img & number of desired blobs, returns contours of blobs. def blobbify(img, num_of_labels, kern_size = 3, dilation_rate = 10): prep_img, contours, hierarchy = prep( img.copy(), kern_size ) # dilate img and check current contour count. while len(contours) > num_of_labels: kern_size += dilation_rate # add dilation_rate to kern_size to increase the blob. Remember kern_size must always be odd. previous = (prep_img, contours, hierarchy) processed_img, contours, hierarchy = prep( img.copy(), kern_size ) # dilate img and check current contour count, again. if len(contours) < num_of_labels: return (processed_img, contours, hierarchy) else: return previous # finds bounding boxes of all contours def bounding_box(contours): bBox = [] for curve in contours: box = cv2.boundingRect(curve) bBox.append(box) return bBox 

Los cuadros resultantes del método anterior tendrán espacio alrededor de las tags, y esto puede incluir parte del diseño original, si los cuadros se aplican a la imagen original. Para evitar esto, haga que las regiones de interés a través de sus nuevos cuadros encontrados y recorte el espacio en blanco. Luego guarda la forma de ese roi como tu nueva caja.

Quizás no tenga forma de saber cuántas tags habrá en la imagen. Si este es el caso, entonces recomiendo jugar con valores de erosión hasta que encuentre el mejor para adaptarse a su caso y obtener las burbujas deseadas.

O puede intentar encontrar contornos en el contenido restante, después de eliminar el diseño, y combinar los cuadros delimitadores en un rectángulo según la distancia entre ellos.

Después de que haya encontrado sus cajas, simplemente use esas cajas con respecto a la imagen original y lo terminará.


Módulo de Detección de Texto de Escena en OpenCV 3

Como se mencionó en los comentarios a su pregunta, ya existe un medio de detección de texto de escena (no de detección de texto de documento) en opencv 3. Entiendo que no tiene la capacidad de cambiar de versión, pero para aquellos con la misma pregunta y no limitado a una versión anterior de opencv, decidí incluir esto al final. La documentación para la detección de texto de escena se puede encontrar con una simple búsqueda en Google.

El módulo opencv para la detección de texto también viene con reconocimiento de texto que implementa tessaract, que es un módulo gratuito de reconocimiento de texto de código abierto. La desventaja de tessaract, y por lo tanto el módulo de reconocimiento de texto de escena de opencv es que no es tan refinado como las aplicaciones comerciales y su uso requiere mucho tiempo. Disminuyendo así su rendimiento, pero es de uso gratuito, por lo que es lo mejor que tenemos sin pagar dinero, si también desea el reconocimiento de texto.

Campo de golf:

  • Documentación OpenCv
  • Documentación anterior
  • El código fuente se encuentra aquí, para su análisis y comprensión.

Honestamente, carezco de la experiencia y los conocimientos tanto en el procesamiento de imagen como en el modo abierto para proporcionar una forma detallada de implementar su módulo de detección de texto. Lo mismo con el algoritmo SWT. Me metí en esto en los últimos meses, pero a medida que aprenda más, editaré esta respuesta.