Otimização de OCR com YOLOv10 Customizado e Ollama (Llama 3)

A integração de modelos de visão computacional com Large Lenguage Models (LLMs) abre portas para aplicações sofisticadas, como a digitalização inteligente de capas de livros. Ao unir um modelo YOLOv10 personalizado para localziação de regiões de texto com um LLM via Ollama, é possível transformar saídas caóticas de OCR em dados estruturados e de alta confiabilidade.

Limitações do OCR Convencional

Ferramentas tradicionais de Reconhecimento Óptico de Caracteres (OCR) enfrentam dificuldades quando o texto está sobreposto a elementos visuais complexos ou ruídos. Sem um pré-processamento adequado, os resultados tendem a ser inutilizáveis. O exemplo abaixo ilustra a aplicação direta do EasyOCR em uma imagem:

import easyocr
import cv2

leitor = easyocr.Reader(['en'])
img_capa = cv2.imread('capa_livro.jpg')
texto_bruto = leitor.readtext(img_capa)

for coordenadas, palavra, confianca in texto_bruto:
    print(f"Texto: {palavra} - Confiança: {confianca}")

Ao processar imagens densas, a saída frequentemente inclui fragmentos visuais interpretados como letras ou textos embaralhados. Para mitigar isso, o YOLO atua como um filtro espacial preciso, isolando apenas as regiões de intereses antes da extração do texto.

  1. Treinamento do Modelo YOLOv10

A fundação deste pipeline é treinar um detector de objetos especializado em identificar blocos de texto, como títulos e nomes de autores. O YOLOv10 se destaca por sua eficiência e otimização para objetos de pequenas dimensões.

from ultralytics import YOLO

detector = YOLO("yolov10n.pt")

detector.train(
    data="dataset_livros/config.yaml", 
    epochs=50, 
    imgsz=640
)

Ajustes nos hiperparâmetros e no volume do dataset podem ser aplicados para refinar a precisão da detecção de limites na sua base de dados específica.

  1. Extração de Caixas Delimitadoras em Vídeo

Com o modelo treinado, a inferência é aplicada quadro a quadro para gerar caixas delimitadoras (bounding boxes), separando visualmente o texto do fundo e preparando o terreno para um OCR limpo.

import cv2
from ultralytics import YOLO

captura = cv2.VideoCapture('video_livros.mp4')
detector = YOLO('pesos_modelo_livro.pt')

def processar_deteccoes(modelo, quadro, limiar=0.5):
    inferencias = modelo.predict(quadro, conf=limiar)
    for inferencia in inferencias:
        for caixa in inferencia.boxes:
            x1, y1, x2, y2 = map(int, caixa.xyxy[0].tolist())
            cv2.rectangle(quadro, (x1, y1), (x2, y2), (0, 255, 0), 2)
    return quadro, inferencias

while captura.isOpened():
    status, frame = captura.read()
    if not status:
        break
        
    frame_processado, inferencias = processar_deteccoes(detector, frame)
    cv2.imshow('Deteccao de Texto', frame_processado)
    
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

captura.release()
cv2.destroyAllWindows()

Este script isola as coordenadas exatas onde o texto reside, eliminando a interferência do restante da imagem durante a leitura.

  1. Aplicação de OCR nas Regiões Isoladas

Ao restringir a leitura do OCR apenas aos recortes das caixas delimitadoras, a precisão do texto extraído aumenta significativamente, evitando falsos positivos gerados por texturas ou ilustrações.

import easyocr

leitor_ocr = easyocr.Reader(['en'])

def ler_regioes_recortadas(quadro, caixas):
    resultados_ocr = []
    for caixa in caixas:
        x1, y1, x2, y2 = map(int, caixa.xyxy[0].tolist())
        recorte = quadro[y1:y2, x1:x2]
        leitura = leitor_ocr.readtext(recorte)
        resultados_ocr.append(leitura)
    return resultados_ocr

for inferencia in inferencias:
    leituras = ler_regioes_recortadas(frame, inferencia.boxes)
    palavras_extraidas = [detec[1] for leitura in leituras for detec in leitura]
    print(f"Palavras extraídas: {', '.join(palavras_extraidas)}")

O resultado agora contém apenas as palavras relevantes da capa, como 'THE, SECRET, HISTORY, DONNA, TARTT', minimizando erros de interpretação de fundo.

  1. Refinamento Semântico com Ollama (Llama 3)

Mesmo restrito às caixas, o OCR pode retornar caracteres equivocados ou sequências desordenadas. Ao direcionar a saída bruta para o Llama 3 via Ollama, é possível sanitizar, organizar e formatar as informações de forma semântica.

import ollama

instrucao_llm = f"""
- O texto a seguir foi obtido via OCR de uma capa de livro e contém o título e o autor.
- Pode haver pequenos erros de ortografia ou desordem de palavras.
- Sua tarefa é identificar o título e o autor corretamente.
- Retorne APENAS no formato: 'Título: <livro> | Autor: <autor>'.
- Não inclua nenhuma outra informação ou comentário.

Texto bruto:
{palavras_extraidas}
"""

resposta_llm = ollama.chat(
    model="llama3",
    messages=[{"role": "user", "content": instrucao_llm}]
)

dado_estruturado = resposta_llm['message']['content'].strip()
print(dado_estruturado)

A resposta gerada pelo modelo será algo como: Título: The Secret History | Autor: Donna Tartt. Esse dado formatado pode ser automaticamente inserido em bancos de dados, utilizado para indexação em bibliotecas digitais ou para geração de metadados em sistemas de arquivamento, eliminando a necessidade de curadoria manual e garantindo a consistência da informação extraída.

Tags: YOLOv10 ocr Ollama Llama3 EasyOCR

Publicado em 10-8 14:02