Tengo un diagrama de múltiples imágenes, todas las cuales contienen etiquetas como caracteres alfanuméricos en lugar de solo la etiqueta de texto en sí. Quiero que mi modelo YOLO identifique todos los números y caracteres alfanuméricos presentes en él.
¿Cómo puedo entrenar a mi modelo YOLO para que haga lo mismo? El conjunto de datos se puede encontrar aquí. https://drive.google.com/open?id=1iEkGcreFaBIJqUdAADDXJbUrSj99bvoi
Por ejemplo: ver los cuadros delimitadores. Quiero que YOLO detecte donde esté presente el texto. Sin embargo, actualmente no es necesario identificar el texto dentro de él.
También es necesario hacer lo mismo para este tipo de imágenes.
Las imágenes se pueden descargar aquí.
Esto es lo que he intentado usar opencv pero no funciona para todas las imágenes en el conjunto de datos.
import cv2
import numpy as np
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Users\HPO2KOR\AppData\Local\Tesseract-OCR\tesseract.exe"
image = cv2.imread(r'C:\Users\HPO2KOR\Desktop\Work\venv\Patent\PARTICULATE DETECTOR\PD4.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
clean = thresh.copy()
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,1))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(clean, [c], -1, 0, 3)
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,30))
detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(clean, [c], -1, 0, 3)
cnts = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
area = cv2.contourArea(c)
if area < 100:
cv2.drawContours(clean, [c], -1, 0, 3)
elif area > 1000:
cv2.drawContours(clean, [c], -1, 0, -1)
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
x,y,w,h = cv2.boundingRect(c)
if len(approx) == 4:
cv2.rectangle(clean, (x, y), (x + w, y + h), 0, -1)
open_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
opening = cv2.morphologyEx(clean, cv2.MORPH_OPEN, open_kernel, iterations=2)
close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,2))
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, close_kernel, iterations=4)
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
x,y,w,h = cv2.boundingRect(c)
area = cv2.contourArea(c)
if area > 500:
ROI = image[y:y+h, x:x+w]
ROI = cv2.GaussianBlur(ROI, (3,3), 0)
data = pytesseract.image_to_string(ROI, lang='eng',config='--psm 6')
if data.isalnum():
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
print(data)
cv2.imwrite('image.png', image)
cv2.imwrite('clean.png', clean)
cv2.imwrite('close.png', close)
cv2.imwrite('opening.png', opening)
cv2.waitKey()
¿Hay algún modelo o alguna técnica de opencv o algún modelo previamente entrenado que pueda hacer lo mismo por mí? Solo necesito los cuadros delimitadores alrededor de todos los caracteres alfanuméricos presentes en las imágenes. Después de eso, necesito identificar qué hay en él. Sin embargo, la segunda parte no es importante actualmente.
fuente
Respuestas:
Un posible enfoque es utilizar el detector de texto de aprendizaje profundo EAST (Texto de escena eficiente y preciso) basado en el artículo de Zhou et al. De 2017, EAST: un detector de texto de escena eficiente y preciso . El modelo fue originalmente entrenado para detectar texto en imágenes de escenas naturales, pero es posible aplicarlo en imágenes de diagrama. EAST es bastante robusto y es capaz de detectar texto borroso o reflexivo. Aquí hay una versión modificada de la implementación de EAST de Adrian Rosebrock. En lugar de aplicar el detector de texto directamente en la imagen, podemos intentar eliminar la mayor cantidad de objetos que no sean de texto en la imagen antes de realizar la detección de texto. La idea es eliminar líneas horizontales, líneas verticales y contornos que no sean de texto (curvas, diagonales, formas circulares) antes de aplicar la detección. Aquí están los resultados con algunas de sus imágenes:
Ingrese
->
contornos sin texto para eliminar en verdeResultado
Otras imagenes
El
frozen_east_text_detection.pb
modelo previamente entrenado necesario para realizar la detección de texto se puede encontrar aquí . Aunque el modelo capta la mayor parte del texto, los resultados no son 100% precisos y ocasionalmente tienen falsos positivos, probablemente debido a cómo fue entrenado en imágenes de escenas naturales. Para obtener resultados más precisos, probablemente tenga que entrenar su propio modelo personalizado. Pero si desea una solución decente lista para usar, esto debería funcionar. Consulte la publicación de blog de Adrian OpenCV Text Detection (detector de texto EAST) para obtener una explicación más completa del detector de texto EAST.Código
fuente
Por conveniencia, me gustaría agregar el paquete keras_ocr . Se puede instalar fácilmente con pip y se basa en el detector de texto CRAFT, que es un poco más nuevo que el detector EAST si no me equivoco.
Al lado de la detección, ¡ya hace algo de OCR también! Los resultados se muestran a continuación, vea esto como una alternativa, quizás más fácil de implementar, que la respuesta aceptada.
fuente
Lo que estás describiendo parece ser OCR ( reconocimiento óptico de caracteres ). Un motor de OCR que conozco es tesseract , aunque también existe este de IBM y otros.
Como YOLO fue entrenado originalmente para una tarea muy diferente, usarlo para localizar texto probablemente requerirá volver a entrenarlo desde cero. Se podría tratar de usar paquetes existentes (adaptados a su configuración específica) para la verdad básica (aunque vale la pena recordar que el modelo generalmente solo sería tan bueno como la verdad básica). O, quizás más fácilmente, genere datos sintéticos para el entrenamiento (es decir, agregue texto en las posiciones que elija a los dibujos existentes y luego entrene para localizarlo).
Alternativamente, si todas sus imágenes de destino están estructuradas de manera similar a la anterior, se podría tratar de crear una verdad básica utilizando la heurística CV clásica como lo hizo anteriormente para separar / segmentar símbolos, seguido de la clasificación utilizando un CNN entrenado en MNIST o similar para determinar si un blob dado contiene un símbolo.
Para el caso de que opte por YOLO, hay implementaciones existentes en python, por ejemplo, tenía algo de experiencia con este , debería ser bastante sencillo configurar el entrenamiento con su propia verdad básica.
Finalmente, si usar YOLO o CNN no es un objetivo en sí mismo, sino solo la solución, cualquiera de las "verdades básicas" anteriores podría usarse directamente como una solución, y no para entrenar un modelo.
Espero haber entendido bien tu pregunta
fuente