1. Introducción
En este codelab, aprenderás a usar el analizador de formularios de Document AI para analizar un formulario escrito a mano con Python.
Usaremos un formulario de admisión médica simple como ejemplo, pero este procedimiento funcionará con cualquier formulario generalizado admitido por DocAI.
Requisitos previos
Este codelab se basa en contenido presentado en otros codelabs de Document AI.
Recomendamos que completes los siguientes codelabs antes de continuar.
Qué aprenderás
- Cómo analizar y extraer datos de un formulario escaneado con el analizador de formularios de Document AI.
Requisitos
Encuesta
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia en Python?
¿Cómo calificarías tu experiencia en el uso de los servicios de Google Cloud?
2. Configuración y requisitos
En este codelab, se supone que completaste los pasos de configuración de Document AI que se indican en el Codelab de OCR de Document AI.
Completa estos pasos antes de continuar:
También tendrás que instalar Pandas, una biblioteca de análisis de datos de código abierto para Python.
pip3 install --upgrade pandas
3. Crea un procesador de analizador de formularios
Primero, debes crear una instancia del procesador del Analizador de formularios para usarla en Document AI Platform para este instructivo.
- En Console, navega a Descripción general de la plataforma de Document AI
- Haz clic en Create Processor y selecciona Form Parser.
- Especifica el nombre del procesador y selecciona tu región en la lista.
- Haz clic en Crear para crear tu procesador.
- Copia el ID del procesador. Debes usar esto en el código más adelante.
Prueba un procesador en la consola de Cloud
Para probar tu procesador en la consola, puedes subir un documento. Haz clic en Subir documento y selecciona un formulario para analizar. Puedes descargar y usar este formulario de muestra si no tienes uno disponible para usar.
Tu resultado debería tener la siguiente apariencia:
4. Descargar el formulario de muestra
Tenemos un documento de muestra que contiene un formulario simple de admisión médica.
Puedes descargar el PDF mediante el siguiente vínculo. Luego, súbelo a la instancia de Cloud Shell.
También puedes descargarlo de nuestro bucket público de Google Cloud Storage con gsutil
.
gsutil cp gs://cloud-samples-data/documentai/codelabs/form-parser/intake-form.pdf .
Confirma que el archivo se haya descargado en Cloud Shell con el siguiente comando:
ls -ltr intake-form.pdf
5. Extrae pares clave-valor de formularios
En este paso, usarás la API de procesamiento en línea para llamar al procesador del analizador de formularios que creaste anteriormente. Luego, extraerás los pares clave-valor que se encuentran en el documento.
El procesamiento en línea consiste en enviar un solo documento y esperar la respuesta. También puedes utilizar el procesamiento por lotes si deseas enviar varios archivos o si el tamaño del archivo supera el máximo de páginas de procesamiento en línea. Puedes revisar cómo hacerlo en el Codelab de OCR.
El código que se usa a fin de realizar una solicitud de proceso es idéntico para todos los tipos de procesadores, excepto el ID.
El objeto de respuesta Document contiene una lista de páginas del documento de entrada.
Cada objeto page
contiene una lista de campos de formulario y sus ubicaciones en el texto.
El siguiente código se itera en cada página y extrae cada clave, valor y puntuación de confianza. Se trata de datos estructurados que pueden almacenarse más fácilmente en bases de datos o usarse en otras aplicaciones.
Crea un archivo llamado form_parser.py
y usa el código que se proporciona a continuación.
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)
Ejecuta el código ahora y deberías ver el texto extraído e impreso en tu consola.
Deberías ver el siguiente resultado si usas nuestro documento de muestra:
$ 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. Analizar tablas
El analizador de formularios también puede extraer datos de tablas de documentos. En este paso, descargaremos un nuevo documento de muestra y extraeremos datos de la tabla. Dado que estamos cargando los datos en Pandas, estos se pueden enviar a un archivo CSV y a muchos otros formatos con una sola llamada al método.
Descargar el formulario de muestra con tablas
Tenemos un documento de muestra que contiene un formulario de muestra y una tabla.
Puedes descargar el PDF mediante el siguiente vínculo. Luego, súbelo a la instancia de Cloud Shell.
También puedes descargarlo de nuestro bucket público de Google Cloud Storage con gsutil
.
gsutil cp gs://cloud-samples-data/documentai/codelabs/form-parser/form_with_tables.pdf .
Confirma que el archivo se haya descargado en Cloud Shell con el siguiente comando:
ls -ltr form_with_tables.pdf
Extraer datos de tablas
La solicitud de procesamiento de los datos de la tabla es exactamente la misma que la de la extracción de pares clave-valor. La diferencia está en los campos de los que extraemos los datos en la respuesta. Los datos de la tabla se almacenan en el campo pages[].tables[]
.
En este ejemplo, se extrae información de las filas de encabezado y de cuerpo de la tabla para cada tabla y página. Luego, imprime la tabla y la guarda como un archivo CSV.
Crea un archivo llamado table_parsing.py
y usa el código que se proporciona a continuación.
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)
Ejecuta el código ahora y deberías ver el texto extraído e impreso en tu consola.
Deberías ver el siguiente resultado si usas nuestro documento de muestra:
$ 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
También deberías tener dos archivos CSV nuevos en el directorio desde el que ejecutas el código.
$ ls form_with_tables_pg1_tb0.csv form_with_tables_pg1_tb1.csv table_parsing.py
7. Felicitaciones
Felicitaciones, usaste correctamente la API de Document AI para extraer datos de un formulario escrito a mano. Te recomendamos experimentar con otros documentos del formulario.
Realiza una limpieza
Para evitar que se generen cargos en tu cuenta de Google Cloud por los recursos que usaste en este instructivo, sigue estos pasos:
- En la consola de Cloud, ve a la página Administrar recursos.
- En la lista de proyectos, selecciona tu proyecto y haz clic en Borrar.
- En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrarlo.
Más información
Sigue aprendiendo sobre Document AI con estos codelabs de seguimiento.
- Procesadores especializados con Document AI (Python)
- Administra procesadores de Document AI con Python
- Document AI: Con interacción humana
Recursos
Licencia
Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.