Tutoriel sur la détection de documents texte

Public

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.

Conditions préalables

Annoter une image à l'aide de la reconnaissance optique des caractères d'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.

fullTextAnnotation est une réponse hiérarchique structurée pour le texte extrait de l'image. Elle est organisée sous la forme Pages → Blocs → Paragraphes → Mots → Symboles (Page, Block, Paragraph, Word, Symbol) :

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

  • Block représente un élément "logique" de la page (par exemple, une zone couverte de texte, une image ou un séparateur se trouvant 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
import io

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

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

def draw_boxes(image, bounds, color):
    """Draw a border around the image using the hints in the vector list."""
    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):
    """Returns document bounds given an image."""
    client = vision.ImageAnnotatorClient()

    bounds = []

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

    image = types.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)

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

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

def render_doc_text(filein, fileout):
    image = Image.open(filein)
    bounds = get_document_bounds(filein, FeatureType.PAGE)
    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 is not 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)

Cette application simple effectue les tâches suivantes :

  • Elle importe les bibliothèques nécessaires pour exécuter l'application.
  • Elle utilise trois arguments qu'elle transmet à la fonction main() :
    • image_file : le fichier image d'entrée à annoter.
    • output_file : le nom du fichier de sortie dans lequel Cloud Vision générera une image de sortie sur laquelle seront tracés des polygones.
  • Elle crée une instance ImageAnnotatorClient pour interagir avec le service.
  • Elle envoie la requête et retourne une réponse.
  • Elle crée une image de sortie sur laquelle des cadres sont tracés autour du texte.

En détail

Importer des bibliothèques

import argparse
from enum import Enum
import io

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

Nous importons des bibliothèques standards :

  • argparse pour permettre à l'application d'accepter les noms de fichiers d'entrée en tant qu'arguments.
  • enum pour l'énumération FeatureType.
  • io pour les E/S des fichiers.

Autres importations :

  • La classe ImageAnnotatorClient de la bibliothèque google.cloud.vision pour l'accès à l'API Vision.
  • Le module types de la bibliothèque google.cloud.vision pour la création des requêtes.
  • Les bibliothèques Image et ImageDraw de la bibliothèque PIL permettent de créer l'image de sortie (image d'entrée sur laquelle ont été tracés des cadres).

Exécuter l'application

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)

Ici, nous analysons simplement les arguments transmis, et nous les transmettons à la fonction render_doc_text().

S'authentifier dans l'API

Avant de communiquer avec le service de l'API Vision, vous devez authentifier votre service avec les identifiants précédemment acquis. Dans une application, le moyen le plus simple d'obtenir des identifiants est d'utiliser les identifiants par défaut de l'application. Par défaut, la bibliothèque cliente Cloud tente d'obtenir les identifiants de la variable d'environnement GOOGLE_APPLICATION_CREDENTIALS, laquelle doit être définie de manière à pointer sur le fichier de clé JSON de votre compte de service (consultez la section Configurer un compte de service pour en savoir plus).

Envoyer la requête API et lire les limites du texte à partir de la réponse

Maintenant que le service de l'API Vision est prêt, nous pouvons y accéder en appelant la méthode document_text_detection de l'instance ImageAnnotatorClient.

La bibliothèque cliente encapsule les informations sur les requêtes adressées à l'API et sur les réponses obtenues. Consultez la documentation de référence de l'API Vision pour obtenir des informations complètes sur la structure d'une requête.

"""Returns document bounds given an image."""
client = vision.ImageAnnotatorClient()

bounds = []

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

image = types.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)

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

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

Une fois la requête traitée par la bibliothèque cliente, la réponse contient un objet AnnotateImageResponse qui consiste en une liste de résultats d'annotation d'image (un par image envoyée dans la requête). Étant donné que nous n'avons envoyé qu'une seule image dans la requête, nous parcourons fullTextAnnotation et nous collectons les limites pour la caractéristique de document spécifiée.

Exécuter l'application

Pour exécuter l'application, vous pouvez télécharger ce fichier receipt.jpg (vous devrez peut-être cliquer avec le bouton droit de la souris sur le lien), puis transmettre l'emplacement du fichier téléchargé sur votre machine locale à l'application de tutoriel (doctext.py).

Voici la commande Python, suivie de l'image de sortie de l'annotation textuelle.

$ python doctext.py receipt.jpg -out_file out.jpg

Sur l'image ci-dessous, les mots sont dans des cadres jaunes et les phrases dans des cadres rouges.

Félicitations ! Vous avez effectué une détection de texte à l'aide de la réponse fullTextAnnotation de Google Cloud Vision.

Cette page vous a-t-elle été utile ? Évaluez-la :

Envoyer des commentaires concernant…

Cloud Vision API Documentation
Besoin d'aide ? Consultez notre page d'assistance.