Analiza formularzy za pomocą Document AI (Python)

1. Wprowadzenie

Z tego ćwiczenia w Codelabs dowiesz się, jak używać parsera formularzy Document AI do analizowania odręcznych formularzy w Pythonie.

Jako przykładu użyjemy prostego formularza przyjmowania leków, ale ta procedura sprawdzi się w przypadku każdej ogólnej postaci obsługiwanej przez DocAI.

Wymagania wstępne

To ćwiczenie w Codelabs opiera się na materiałach prezentowanych w innych ćwiczeniach z programowania Document AI.

Przed kontynuowaniem zalecamy ukończenie poniższych ćwiczeń z programowania.

Czego się nauczysz

  • Jak analizować i wyodrębniać dane ze zeskanowanego formularza za pomocą parsera formularzy Document AI.

Czego potrzebujesz

  • Projekt Google Cloud
  • przeglądarkę, np. Chrome lub Firefox;
  • Wiedza na temat języka Python 3

Ankieta

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z językiem Python?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz korzystanie z usług Google Cloud?

Początkujący Poziom średnio zaawansowany Biegły
.

2. Konfiguracja i wymagania

W tym ćwiczeniu w Codelabs zakładamy, że masz ukończone kroki konfiguracji Document AI wymienione w ramach ćwiczeń z programowania w Document AI OCR.

Zanim przejdziesz dalej, wykonaj te czynności:

Musisz też zainstalować Pandas – bibliotekę open source do analizy danych w Pythonie.

pip3 install --upgrade pandas

3. Tworzenie procesora Form Parser

Najpierw musisz utworzyć instancję procesora parsera formularzy do użycia na platformie Document AI w tym samouczku.

  1. W konsoli przejdź do omówienia Document AI Platform.
  2. Kliknij Create Processor (Utwórz procesor) i wybierz Form Parser.Procesory
  3. Podaj nazwę procesora i wybierz region z listy.
  4. Kliknij Utwórz, aby utworzyć procesor.
  5. Skopiuj identyfikator podmiotu przetwarzającego. Będzie trzeba użyć go później w kodzie.

Testowanie procesora w konsoli Cloud

Możesz przetestować procesor w konsoli, przesyłając dokument. Kliknij Prześlij dokument i wybierz formularz do przeanalizowania. Jeśli nie masz jeszcze odpowiedniego formularza, możesz go pobrać i wykorzystać.

Formularz zdrowotny

Dane wyjściowe powinny wyglądać tak: Przeanalizowany formularz

4. Pobierz przykładowy formularz

Udostępniamy przykładowy dokument, który zawiera prosty formularz przyjęcia medycznego.

Możesz pobrać plik PDF, klikając ten link. Następnie prześlij go do instancji Cloud Shell.

Możesz też pobrać ją z naszego publicznego zasobnika Google Cloud Storage za pomocą adresu gsutil.

gsutil cp gs://cloud-samples-data/documentai/codelabs/form-parser/intake-form.pdf .

Sprawdź, czy plik został pobrany do Cloud Shell, korzystając z tego polecenia:

ls -ltr intake-form.pdf

5. Wyodrębnianie par klucz-wartość formularza

W tym kroku użyjesz interfejsu API przetwarzania online, aby wywołać utworzony wcześniej procesor parsera formularzy. Następnie wyodrębnisz pary klucz-wartość znalezione w dokumencie.

Przetwarzanie online polega na wysłaniu jednego dokumentu i oczekiwaniu na odpowiedź. Z przetwarzania wsadowego możesz też korzystać, jeśli chcesz wysłać wiele plików lub jeśli rozmiar pliku przekracza maksymalną liczbę stron przetwarzania online. Więcej informacji o tym, jak to zrobić, znajdziesz w ćwiczeniach z programowania OCR.

Kod żądania procesu jest taki sam dla każdego typu procesora oprócz identyfikatora procesora.

Obiekt odpowiedzi Document zawiera listę stron z dokumentu wejściowego.

Każdy obiekt page zawiera listę pól formularza i ich lokalizacji w tekście.

Następujący kod wykona iterację na każdej stronie i wyodrębnia każdy klucz, wartość oraz wskaźnik ufności. Są to uporządkowane dane, które można łatwiej przechowywać w bazach danych lub używać w innych aplikacjach.

Utwórz plik o nazwie form_parser.py i użyj poniższego kodu.

form_parser.py

import pandas as pd
from google.cloud import documentai_v1 as documentai


def online_process(
    project_id: str,
    location: str,
    processor_id: str,
    file_path: str,
    mime_type: str,
) -> documentai.Document:
    """
    Processes a document using the Document AI Online Processing API.
    """

    opts = {"api_endpoint": f"{location}-documentai.googleapis.com"}

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # The full resource name of the processor, e.g.:
    # projects/project-id/locations/location/processor/processor-id
    # You must create new processors in the Cloud Console first
    resource_name = documentai_client.processor_path(project_id, location, processor_id)

    # Read the file into memory
    with open(file_path, "rb") as image:
        image_content = image.read()

        # Load Binary Data into Document AI RawDocument Object
        raw_document = documentai.RawDocument(
            content=image_content, mime_type=mime_type
        )

        # Configure the process request
        request = documentai.ProcessRequest(
            name=resource_name, raw_document=raw_document
        )

        # Use the Document AI client to process the sample form
        result = documentai_client.process_document(request=request)

        return result.document


def trim_text(text: str):
    """
    Remove extra space characters from text (blank, newline, tab, etc.)
    """
    return text.strip().replace("\n", " ")


PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "YOUR_PROJECT_LOCATION"  # Format is 'us' or 'eu'
PROCESSOR_ID = "FORM_PARSER_ID"  # Create processor in Cloud Console

# The local file in your current working directory
FILE_PATH = "intake-form.pdf"
# Refer to https://cloud.google.com/document-ai/docs/processors-list
# for supported file types
MIME_TYPE = "application/pdf"

document = online_process(
    project_id=PROJECT_ID,
    location=LOCATION,
    processor_id=PROCESSOR_ID,
    file_path=FILE_PATH,
    mime_type=MIME_TYPE,
)

names = []
name_confidence = []
values = []
value_confidence = []

for page in document.pages:
    for field in page.form_fields:
        # Get the extracted field names
        names.append(trim_text(field.field_name.text_anchor.content))
        # Confidence - How "sure" the Model is that the text is correct
        name_confidence.append(field.field_name.confidence)

        values.append(trim_text(field.field_value.text_anchor.content))
        value_confidence.append(field.field_value.confidence)

# Create a Pandas Dataframe to print the values in tabular format.
df = pd.DataFrame(
    {
        "Field Name": names,
        "Field Name Confidence": name_confidence,
        "Field Value": values,
        "Field Value Confidence": value_confidence,
    }
)

print(df)

Uruchom kod teraz, a tekst powinien zostać wyodrębniony i wydrukowany w konsoli.

Jeśli korzystasz z przykładowego dokumentu, dane wyjściowe powinny wyglądać tak:

$ python3 form_parser.py
                                           Field Name  Field Name Confidence                                        Field Value  Field Value Confidence
0                                            Phone #:               0.999982                                     (906) 917-3486                0.999982
1                                  Emergency Contact:               0.999972                                         Eva Walker                0.999972
2                                     Marital Status:               0.999951                                             Single                0.999951
3                                             Gender:               0.999933                                                  F                0.999933
4                                         Occupation:               0.999914                                  Software Engineer                0.999914
5                                        Referred By:               0.999862                                               None                0.999862
6                                               Date:               0.999858                                            9/14/19                0.999858
7                                                DOB:               0.999716                                         09/04/1986                0.999716
8                                            Address:               0.999147                                     24 Barney Lane                0.999147
9                                               City:               0.997718                                             Towaco                0.997718
10                                              Name:               0.997345                                       Sally Walker                0.997345
11                                             State:               0.996944                                                 NJ                0.996944
...

6. Analizuj tabele

Parser formularzy może też wyodrębniać dane z tabel w dokumentach. W tym kroku pobierzemy nowy przykładowy dokument i wyodrębnimy dane z tabeli. Dane wczytują się do systemu Pandas, więc można je wyeksportować do pliku CSV i wielu innych formatów za pomocą pojedynczego wywołania metody.

Pobierz przykładowy formularz z tabelami

Udostępniamy przykładowy dokument, który zawiera przykładowy formularz i tabelę.

Możesz pobrać plik PDF, klikając ten link. Następnie prześlij go do instancji Cloud Shell.

Możesz też pobrać ją z naszego publicznego zasobnika Google Cloud Storage za pomocą adresu gsutil.

gsutil cp gs://cloud-samples-data/documentai/codelabs/form-parser/form_with_tables.pdf .

Sprawdź, czy plik został pobrany do Cloud Shell, korzystając z tego polecenia:

ls -ltr form_with_tables.pdf

Wyodrębnianie danych tabeli

Żądanie przetwarzania danych z tabeli jest dokładnie takie samo jak w przypadku wyodrębniania par klucz-wartość. Różnica polega na tym, z których pól wyodrębniane są dane w odpowiedzi. Dane tabeli są przechowywane w polu pages[].tables[].

W tym przykładzie wyodrębniane są informacje o wierszach nagłówków i treści każdej tabeli i strony, a następnie wydrukuje tabelę i zapisze ją jako plik CSV.

Utwórz plik o nazwie table_parsing.py i użyj poniższego kodu.

table_parsing.py

# type: ignore[1]
"""
Uses Document AI online processing to call a form parser processor
Extracts the tables and data in the document.
"""
from os.path import splitext
from typing import List, Sequence

import pandas as pd
from google.cloud import documentai


def online_process(
    project_id: str,
    location: str,
    processor_id: str,
    file_path: str,
    mime_type: str,
) -> documentai.Document:
    """
    Processes a document using the Document AI Online Processing API.
    """

    opts = {"api_endpoint": f"{location}-documentai.googleapis.com"}

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient(client_options=opts)

    # The full resource name of the processor, e.g.:
    # projects/project-id/locations/location/processor/processor-id
    # You must create new processors in the Cloud Console first
    resource_name = documentai_client.processor_path(project_id, location, processor_id)

    # Read the file into memory
    with open(file_path, "rb") as image:
        image_content = image.read()

        # Load Binary Data into Document AI RawDocument Object
        raw_document = documentai.RawDocument(
            content=image_content, mime_type=mime_type
        )

        # Configure the process request
        request = documentai.ProcessRequest(
            name=resource_name, raw_document=raw_document
        )

        # Use the Document AI client to process the sample form
        result = documentai_client.process_document(request=request)

        return result.document


def get_table_data(
    rows: Sequence[documentai.Document.Page.Table.TableRow], text: str
) -> List[List[str]]:
    """
    Get Text data from table rows
    """
    all_values: List[List[str]] = []
    for row in rows:
        current_row_values: List[str] = []
        for cell in row.cells:
            current_row_values.append(
                text_anchor_to_text(cell.layout.text_anchor, text)
            )
        all_values.append(current_row_values)
    return all_values


def text_anchor_to_text(text_anchor: documentai.Document.TextAnchor, text: str) -> str:
    """
    Document AI identifies table data by their offsets in the entirety of the
    document's text. This function converts offsets to a string.
    """
    response = ""
    # If a text segment spans several lines, it will
    # be stored in different text segments.
    for segment in text_anchor.text_segments:
        start_index = int(segment.start_index)
        end_index = int(segment.end_index)
        response += text[start_index:end_index]
    return response.strip().replace("\n", " ")


PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "YOUR_PROJECT_LOCATION"  # Format is 'us' or 'eu'
PROCESSOR_ID = "FORM_PARSER_ID"  # Create processor before running sample

# The local file in your current working directory
FILE_PATH = "form_with_tables.pdf"
# Refer to https://cloud.google.com/document-ai/docs/file-types
# for supported file types
MIME_TYPE = "application/pdf"

document = online_process(
    project_id=PROJECT_ID,
    location=LOCATION,
    processor_id=PROCESSOR_ID,
    file_path=FILE_PATH,
    mime_type=MIME_TYPE,
)

header_row_values: List[List[str]] = []
body_row_values: List[List[str]] = []

# Input Filename without extension
output_file_prefix = splitext(FILE_PATH)[0]

for page in document.pages:
    for index, table in enumerate(page.tables):
        header_row_values = get_table_data(table.header_rows, document.text)
        body_row_values = get_table_data(table.body_rows, document.text)

        # Create a Pandas Dataframe to print the values in tabular format.
        df = pd.DataFrame(
            data=body_row_values,
            columns=pd.MultiIndex.from_arrays(header_row_values),
        )

        print(f"Page {page.page_number} - Table {index}")
        print(df)

        # Save each table as a CSV file
        output_filename = f"{output_file_prefix}_pg{page.page_number}_tb{index}.csv"
        df.to_csv(output_filename, index=False)

Uruchom kod teraz, a tekst powinien zostać wyodrębniony i wydrukowany w konsoli.

Jeśli korzystasz z przykładowego dokumentu, dane wyjściowe powinny wyglądać tak:

$ python3 table_parsing.py
Page 1 - Table 0
     Item    Description
0  Item 1  Description 1
1  Item 2  Description 2
2  Item 3  Description 3
Page 1 - Table 1
  Form Number:     12345678
0   Form Date:   2020/10/01
1        Name:   First Last
2     Address:  123 Fake St

W katalogu, z którego uruchamiasz kod, powinny znajdować się też 2 nowe pliki CSV.

$ ls
form_with_tables_pg1_tb0.csv form_with_tables_pg1_tb1.csv table_parsing.py

7. Gratulacje

Gratulujemy! Udało Ci się użyć interfejsu Document AI API do wyodrębniania danych z odręcznego formularza. Zachęcamy do eksperymentowania z innymi dokumentami formularza.

Czyszczenie danych

Aby uniknąć obciążenia konta Google Cloud opłatami za zasoby zużyte w tym samouczku:

  • W konsoli Cloud otwórz stronę Zarządzanie zasobami.
  • Na liście projektów wybierz swój projekt i kliknij Usuń.
  • W oknie wpisz identyfikator projektu i kliknij Wyłącz, aby usunąć projekt.

Więcej informacji

Dowiedz się więcej o Document AI dzięki tym dodatkowym ćwiczeniom z programowania.

Materiały

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.