Tutorial de deteção de texto em documentos densos

Público-alvo

O objetivo deste tutorial é ajudar a desenvolver aplicações através da API Google Cloud Vision Document Text Detection. Parte do princípio de que tem conhecimentos básicos de técnicas e construções de programação, mas, mesmo que seja um programador iniciante, deve conseguir acompanhar e executar este tutorial sem dificuldade. Em seguida, use a documentação de referência da Cloud Vision API para criar aplicações básicas.

Pré-requisitos

Anotar uma imagem com o OCR de texto de documentos

Este tutorial explica passo a passo uma aplicação básica da API Vision que faz um DOCUMENT_TEXT_DETECTION pedido e, em seguida, processa a fullTextAnnotation resposta.

Um fullTextAnnotation é uma resposta hierárquica estruturada para o texto UTF-8 extraído da imagem, organizado como Pages→Blocks→Paragraphs→Words→Symbols:

  • Page é uma coleção de blocos, além de metainformações sobre a página: tamanhos, resoluções (a resolução X e a resolução Y podem diferir).

  • Block representa um elemento "lógico" da página, por exemplo, uma área coberta por texto, uma imagem ou um separador entre colunas. Os blocos de texto e de tabela contêm as principais informações necessárias para extrair o texto.

  • Paragraph é uma unidade estrutural de texto que representa uma sequência ordenada de palavras. Por predefinição, as palavras são consideradas separadas por quebras de palavras.

  • Word é a unidade de texto mais pequena. É representada como uma matriz de símbolos.

  • Symbol representa um caráter ou uma marca de pontuação.

O elemento fullTextAnnotation também pode fornecer URLs de imagens Web que correspondam parcial ou totalmente à imagem no pedido.

Listagem de código completa

À medida que lê o código, recomendamos que o siga consultando a referência Python da Cloud Vision API.

import argparse
from enum import Enum

from google.cloud import vision
from PIL import Image, ImageDraw



class FeatureType(Enum):
    PAGE = 1
    BLOCK = 2
    PARA = 3
    WORD = 4
    SYMBOL = 5


def draw_boxes(image, bounds, color):
    """Draws a border around the image using the hints in the vector list.

    Args:
        image: the input image object.
        bounds: list of coordinates for the boxes.
        color: the color of the box.

    Returns:
        An image with colored bounds added.
    """
    draw = ImageDraw.Draw(image)

    for bound in bounds:
        draw.polygon(
            [
                bound.vertices[0].x,
                bound.vertices[0].y,
                bound.vertices[1].x,
                bound.vertices[1].y,
                bound.vertices[2].x,
                bound.vertices[2].y,
                bound.vertices[3].x,
                bound.vertices[3].y,
            ],
            None,
            color,
        )
    return image


def get_document_bounds(image_file, feature):
    """Finds the document bounds given an image and feature type.

    Args:
        image_file: path to the image file.
        feature: feature type to detect.

    Returns:
        List of coordinates for the corresponding feature type.
    """
    client = vision.ImageAnnotatorClient()

    bounds = []

    with open(image_file, "rb") as image_file:
        content = image_file.read()

    image = vision.Image(content=content)

    response = client.document_text_detection(image=image)
    document = response.full_text_annotation

    # Collect specified feature bounds by enumerating all document features
    for page in document.pages:
        for block in page.blocks:
            for paragraph in block.paragraphs:
                for word in paragraph.words:
                    for symbol in word.symbols:
                        if feature == FeatureType.SYMBOL:
                            bounds.append(symbol.bounding_box)

                    if feature == FeatureType.WORD:
                        bounds.append(word.bounding_box)

                if feature == FeatureType.PARA:
                    bounds.append(paragraph.bounding_box)

            if feature == FeatureType.BLOCK:
                bounds.append(block.bounding_box)

    # The list `bounds` contains the coordinates of the bounding boxes.
    return bounds




def render_doc_text(filein, fileout):
    """Outlines document features (blocks, paragraphs and words) given an image.

    Args:
        filein: path to the input image.
        fileout: path to the output image.
    """
    image = Image.open(filein)
    bounds = get_document_bounds(filein, FeatureType.BLOCK)
    draw_boxes(image, bounds, "blue")
    bounds = get_document_bounds(filein, FeatureType.PARA)
    draw_boxes(image, bounds, "red")
    bounds = get_document_bounds(filein, FeatureType.WORD)
    draw_boxes(image, bounds, "yellow")

    if fileout != 0:
        image.save(fileout)
    else:
        image.show()


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("detect_file", help="The image for text detection.")
    parser.add_argument("-out_file", help="Optional output file", default=0)
    args = parser.parse_args()

    render_doc_text(args.detect_file, args.out_file)

Esta aplicação simples realiza as seguintes tarefas:

  • Importa as bibliotecas necessárias para executar a aplicação
  • Aceita três argumentos e transmite-os à função main():
    • image_file: o ficheiro de imagem de entrada a anotar
    • output_file—o nome do ficheiro de saída no qual o Cloud Vision vai gerar uma imagem de saída com caixas poligonais desenhadas
  • Cria uma instância do ImageAnnotatorClient para interagir com o serviço
  • Envia o pedido e devolve uma resposta
  • Cria uma imagem de saída com caixas desenhadas à volta do texto

Uma visão mais detalhada do código

Importar bibliotecas

import argparse
from enum import Enum

from google.cloud import vision
from PIL import Image, ImageDraw

Importamos bibliotecas padrão:

  • argparse para permitir que a aplicação aceite nomes de ficheiros de entrada como argumentos
  • enum para a enumeração FeatureType
  • io para E/S de ficheiros

Outras importações:

  • A classe ImageAnnotatorClient na biblioteca google.cloud.vision para aceder à API Vision.
  • O módulo types na biblioteca