Tutoriel de détection de document texte dense

Audience

L'objectif de ce tutoriel est de vous aider à développer des applications à l'aide de la détection de documents texte de l'API Google Cloud Vision. Il y est supposé que vous maîtrisez les concepts et les techniques de base de la programmation. Mais même si vous êtes un programmeur débutant, vous devriez pouvoir suivre et exécuter ce tutoriel sans difficulté, puis utiliser la documentation de référence de l'API Cloud Vision pour créer des applications de base.

Prérequis

Python

Annoter une image à l'aide de l'OCR dans un document texte

Ce tutoriel vous présente une application de base de l'API Vision qui envoie une requête DOCUMENT_TEXT_DETECTION, puis traite la réponse fullTextAnnotation.

Une fullTextAnnotation est une réponse hiérarchique structurée pour le texte UTF-8 extrait de l'image. Elle est organisée sous la forme Pages → Blocks → Paragraphs → Words → Symbols (Pages → Blocs → Paragraphes → Mots → Symboles) :

  • Page est un ensemble de blocs, avec des méta-informations sur la page : tailles, résolutions (la résolution X et la résolution Y peuvent varier).

  • Block représente un élément "logique" de la page (par exemple, une zone couverte de texte, ou une image ou un séparateur situé entre des colonnes). Les blocs de texte et de tableau contiennent les principales informations nécessaires à l'extraction du texte.

  • Paragraph est une unité structurelle de texte représentant une séquence ordonnée de mots. Par défaut, les mots sont considérés comme séparés par des sauts de mot.

  • Word est la plus petite unité de texte. Elle est représentée sous la forme d'un tableau de symboles.

  • Symbol représente un caractère ou un signe de ponctuation.

fullTextAnnotation peut également fournir les URL d'images Web correspondant partiellement ou parfaitement à l'image de la requête.

Intégralité du code

Lors de la lecture du code, nous vous recommandons de vous reporter également la documentation de référence de l'API Cloud Vision pour Python.

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.