使用 Document AI 和 Python 实现光学字符识别 (OCR)

1. 概览

实验简介

什么是 Document AI?

Document AI 是一种文档理解解决方案,可获取非结构化数据(例如文档、电子邮件、帐单、表单等),并让数据更易于理解、分析和使用。该 API 可通过内容分类、实体提取、高级搜索等提供结构化结构。

在本实验中,您将学习如何使用 Python 版 Document AI API 执行光学字符识别。

我们将使用 AA Milne 所编著的经典小说《Winnie the Pooh》的 PDF 文件,近期这本书已在美国加入了公共领域。此文件已被 Google 图书扫描并数字化。

学习内容

  • 如何启用 Document AI API
  • 如何对 API 请求进行身份验证
  • 如何安装 Python 版客户端库
  • 如何解析 PDF 文件中的文本
  • 如何使用 Google Cloud Storage 执行异步请求

所需条件

  • Google Cloud 项目
  • 一个浏览器,例如 ChromeFirefox
  • 熟悉如何使用 Python (3.7+)

调查问卷

您将如何使用本教程?

仅阅读教程内容 阅读并完成练习

您如何评价使用 Python 的体验?

新手水平 中等水平 熟练水平

您如何评价自己在使用 Google Cloud 服务方面的经验水平?

新手水平 中等水平 熟练水平

2. 设置和要求

cae48e4b2e19921d.png

在后续对话框中,点击“接受并继续”按钮以接受服务条款:

27d87930a0daf2f8.png

接受服务条款后,您将被重定向到一个结算摘要页,其右下角会出现一个面板,如下所示:

2076ea7aa9bf3f65.png

最后,当您创建第一个项目时,系统会显示一个对话框,您可以在其中为项目分配结算帐号。选择与您的免费赠金相关联的结算帐号,然后点击“创建”按钮:

dd3b0e795843296

总而言之,您现在拥有结算帐号和项目,这两个实体相关联,因此您今天的 Codelab 中所做的任何工作都将获得您的免费赠金**。**

自定进度的环境设置

  1. 登录 Cloud Console,然后创建一个新项目或重复使用现有项目。(如果您还没有 Gmail 或 Google Workspace 帐号,则必须创建一个。)

选择项目

新建项目

获取项目 ID

请记住项目 ID,它在所有 Google Cloud 项目中都是唯一名称。很抱歉,上述项目 ID 已被占用,您无法使用! 您稍后必须将此 ID 作为 PROJECT_ID 提供。

  1. 接下来,您必须在 Cloud Console 中启用结算功能才能使用 Google Cloud 资源。

请务必按照“清理”部分中的说明操作。本部分将指导您关闭资源,以免产生超出本教程费用的结算。Google Cloud 的新用户有资格参与 $300USD 免费试用计划。

启动 Cloud Shell

虽然 Google Cloud 可以从笔记本电脑远程运行 Google Cloud,但此 Codelab 使用 Google Cloud Shell,这是一个在云端运行的命令行环境。

激活 Cloud Shell

  1. 在 Cloud Console 中,点击激活 Cloud Shell 激活 Cloud Shell

激活 Cloud Shell

如果您以前从未启动过 Cloud Shell,将看到一个中间屏幕(在折叠下面),描述它是什么。如果是这种情况,请点击继续(您将永远不会再看到它)。一次性屏幕如下所示:

Cloud Shell 简介

预配和连接到 Cloud Shell 只需片刻。 Cloud Shell

Cloud Shell 为您提供对云中托管的虚拟机的终端访问权限。该虚拟机包含您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。本 Codelab 中的大部分(甚至全部)工作只需使用浏览器即可完成。

在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID。

  1. 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list

命令输出

 Credentialed Accounts
ACTIVE  ACCOUNT
*      <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

命令输出

[core]
project = <PROJECT_ID>

如果不是上述结果,您可以使用以下命令进行设置:

gcloud config set project <PROJECT_ID>

命令输出

Updated property [core/project].

3.启用 Document AI API

在开始使用 Document AI 之前,您必须启用该 API。在浏览器中打开 Cloud Console

  1. 使用控制台顶部的搜索栏,搜索“Document AI API”,然后点击启用以在 Google Cloud 项目中使用该 API

Search API

  1. 或者,您也可以使用以下 gcloud 命令启用该 API。
gcloud services enable documentai.googleapis.com

您应会看到类似下图的界面:

Operation "operations/..." finished successfully.

现在,您可以使用 Document AI 了!

4.创建和测试处理器

必须先创建将执行提取的 Document OCR 处理器实例。您可以使用 Cloud Console 或 Processor Management API 完成此操作。

Cloud Console

  1. 在控制台中,导航到 Document AI Platform 概览
  2. 点击 Create Processor(创建处理器),然后选择 Document OCR(文档 OCR)处理器
  3. 指定处理方名称,然后从列表中选择您的区域。
  4. 点击创建以创建处理器
  5. 复制处理器 ID。稍后,您必须在代码中使用此方法。 处理器 ID

您可以通过上传文件在控制台中测试处理器。点击 Upload Test Document,然后选择要解析的文档。

您可以下载下面的 PDF 文件,其中包含我们小说的前 3 页。

书名页

您的输出应如下所示:经过解析的图书

Python 客户端库

请按照此 Codelab 了解如何使用 Python 客户端库管理 Document AI 处理器:

使用 Python 管理 Document AI 处理器 - Codelab

5. 对 API 请求进行身份验证

为了向 Document AI API 发出请求,您必须使用服务帐号服务帐号属于您的项目,并且 Python 客户端库使用它来发出 API 请求。与任何其他用户帐号一样,服务帐号也由电子邮件地址表示。在本部分中,您将使用 Cloud SDK 创建服务帐号,然后创建作为服务帐号进行身份验证所需的凭据。

首先,使用 PROJECT_ID 设置环境变量,以在此 Codelab 中全程使用。

export GOOGLE_CLOUD_PROJECT=$(gcloud config get-value core/project)

接下来,使用以下命令创建新的服务帐号来访问 Document AI API:

gcloud iam service-accounts create my-docai-sa \
  --display-name "my-docai-service-account"

接下来,创建 Python 代码用于以新服务帐号身份登录的凭据。使用以下命令创建这些凭据并将其保存为 JSON 文件“~/key.json”:

gcloud iam service-accounts keys create ~/key.json \
  --iam-account  my-docai-sa@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

最后,设置 GOOGLE_APPLICATION_CREDENTIALS 环境变量,供库用来查找您的凭据。要详细了解此表单身份验证,请参阅指南。应使用以下内容将环境变量设置为您创建的凭据 JSON 文件的完整路径:

export GOOGLE_APPLICATION_CREDENTIALS="/path/to/key.json"

6.安装客户端库

安装客户端库:

pip3 install --upgrade google-cloud-documentai
pip3 install --upgrade google-cloud-storage

您应会看到类似下图的界面:

...
Installing collected packages: google-cloud-documentai
Successfully installed google-cloud-documentai-1.2.0
.
.
Installing collected packages: google-cloud-storage
Successfully installed google-cloud-storage-1.43.0

现在,您可以使用 Document AI API 了!

启动交互式 Python

在本教程中,您将使用名为 IPython 的交互式 Python 解释器。在 Cloud Shell 中运行 ipython 来启动会话。此命令会在交互式会话中运行 Python 解释器。

ipython

您应会看到类似下图的内容:

Python 3.7.3 (default, Jul 25 2020, 13:03:44)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.30.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

7. 下载 PDF 示例

我们提供了一个示例文档,其中包含这本小说的前 3 页。

您可以通过以下链接下载 PDF。然后将其上传到 cloudshell 实例

您还可以使用 gsutil 从我们的公开 Google Cloud Storage 存储分区中下载该应用。

gsutil cp gs://cloud-samples-data/documentai/codelabs/ocr/Winnie_the_Pooh_3_Pages.pdf .

8. 发出同步进程文档请求

在此步骤中,您将使用同步端点处理小说的前 3 页。此方法最适合本地存储的较小文档。请查看完整的处理器列表,了解每种处理器类型的最大页面和文件大小。

将以下代码复制到 iPython 会话中:

from google.cloud import documentai_v1 as documentai

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

    # Instantiates a client
    documentai_client = documentai.DocumentProcessorServiceClient()

    # 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 main():
    """
    Run the codelab.
    """
    project_id = 'YOUR_PROJECT_ID'
    location = 'YOUR_PROJECT_LOCATION'  # Format is 'us' or 'eu'
    processor_id = 'YOUR_PROCESSOR_ID'  # Create processor in Cloud Console

    file_path = 'Winnie_the_Pooh_3_Pages.pdf'  # The local file in your current working directory
    # Refer to https://cloud.google.com/document-ai/docs/processors-list for the supported file types
    mime_type = 'application/pdf'

    document = process_document(project_id=project_id, location=location,
                                processor_id=processor_id, file_path=file_path,
                                mime_type=mime_type)

    print("Document processing complete.")
    print(f"Text: {document.text}")

调用 main 函数,您应该会看到控制台中提取并输出的文本。

main()

如果使用我们的示例文档,您应该会看到以下输出:

Document processing complete.
Text: CHAPTER I
IN WHICH We Are Introduced to
Winnie-the-Pooh and Some
Bees, and the Stories Begin
Here is Edward Bear, coming
downstairs now, bump, bump, bump, on the back
of his head, behind Christopher Robin. It is, as far
as he knows, the only way of coming downstairs,
but sometimes he feels that there really is another
way, if only he could stop bumping for a moment
and think of it. And then he feels that perhaps there
isn't. Anyhow, here he is at the bottom, and ready
to be introduced to you. Winnie-the-Pooh.
When I first heard his name, I said, just as you
are going to say, "But I thought he was a boy?"
"So did I," said Christopher Robin.
"Then you can't call him Winnie?"
"I don't."
"But you said "

...

Digitized by
Google

9. 发出异步进程文档请求

现在,假设您想要阅读整部小说中的文字。

  • process_documents() 方法对可以发送的页面数量和文件大小有限制,并且每个 API 调用只允许使用一个文档文件。
  • batch_process_documents() 方法允许对较大的文件进行异步处理,并对多个文件进行批处理。

在此步骤中,我们将使用 Document AI Aasync API 处理整本《小熊猫》小说,并将文本输出到 Google Cloud Storage 存储分区中。

将 PDF 上传到 Cloud Storage

batch_process_documents() 方法目前接受来自 Google Cloud Storage 的文件。如需详细了解对象结构,您可以参阅 documentai_v1.types.BatchProcessRequest

在本例中,您可以从我们的示例数据存储分区中复制文件...

gsutil cp gs://cloud-samples-data/documentai/codelabs/ocr/Winnie_the_Pooh.pdf gs://YOUR_BUCKET_NAME/

...或者,您可以通过以下链接下载小说的示例文件,然后将其上传到您自己的存储分区

您还需要一个 GCS 存储分区来存储 API 的输出。

使用 batch_process_documents() 方法

将以下代码复制到 iPython 会话中:

import re

from google.api_core.operation import Operation
from google.cloud import documentai_v1 as documentai
from google.cloud import storage

def batch_process_documents(
    project_id: str,
    location: str,
    processor_id: str,
    gcs_input_uri: str,
    input_mime_type: str,
    gcs_output_uri: str,
) -> Operation:
    """
    Constructs a request to process a document using the Document AI
    Asynchronous API.
    """
    # You must set the api_endpoint if you use a location other than 'us', e.g.:
    opts = {}
    if location == "eu":
        opts = {"api_endpoint": "eu-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)

    # Cloud Storage URI for the Input Document
    input_document = documentai.GcsDocument(
        gcs_uri=gcs_input_uri, mime_type=input_mime_type
    )

    # Load GCS Input URI into a List of document files
    input_config = documentai.BatchDocumentsInputConfig(
        gcs_documents=documentai.GcsDocuments(documents=[input_document])
    )

    # Cloud Storage URI for Output directory
    gcs_output_config = documentai.DocumentOutputConfig.GcsOutputConfig(
        gcs_uri=gcs_output_uri
    )

    # Load GCS Output URI into OutputConfig object
    output_config = documentai.DocumentOutputConfig(gcs_output_config=gcs_output_config)

    # Configure Process Request
    request = documentai.BatchProcessRequest(
        name=resource_name,
        input_documents=input_config,
        document_output_config=output_config,
    )

    # Future for long-running operations returned from Google Cloud APIs.
    operation = documentai_client.batch_process_documents(request)

    return operation

def get_documents_from_gcs(
    gcs_output_uri: str, operation_name: str
) -> [documentai.Document]:
    """
    Download the document output from GCS.
    """

    # The GCS API requires the bucket name and URI prefix separately
    match = re.match(r"gs://([^/]+)/(.+)", gcs_output_uri)
    output_bucket = match.group(1)
    prefix = match.group(2)

    # The output files will be in a new subdirectory with the Operation ID as the name
    operation_id = re.search("operations\/(\d+)", operation_name, re.IGNORECASE).group(1)

    output_directory = f"{prefix}/{operation_id}"

    storage_client = storage.Client()

    # List of all of the files in the directory `gs://gcs_output_uri/operation_id`
    blob_list = list(storage_client.list_blobs(output_bucket, prefix=output_directory))

    output_documents = []

    for blob in blob_list:
        # Document AI should only output JSON files to GCS
        if ".json" in blob.name:
            document = documentai.types.Document.from_json(blob.download_as_bytes())
            output_documents.append(document)
        else:
            print(f"Skipping non-supported file type {blob.name}")

    return output_documents

def main():
    """
    Run the codelab.
    """

    project_id = 'YOUR_PROJECT_ID'
    location = 'YOUR_PROJECT_LOCATION'  # Format is 'us' or 'eu'
    processor_id = 'YOUR_PROCESSOR_ID'  # Create processor in Cloud Console

    # Format 'gs://input_bucket/directory/file.pdf'
    gcs_input_uri = "INPUT_BUCKET_URI"
    input_mime_type = "application/pdf"

    # Format 'gs://output_bucket/directory'
    gcs_output_uri = "YOUR_OUTPUT_BUCKET_URI"

    # Batch Process returns a Long Running Operation (LRO)
    operation = batch_process_documents(
        project_id=project_id,
        location=location,
        processor_id=processor_id,
        gcs_input_uri=gcs_input_uri,
        input_mime_type=input_mime_type,
        gcs_output_uri=gcs_output_uri,
    )

    # Format: projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID
    operation_name = operation.operation.name

    # Continually polls the operation until it is complete.
    # This could take some time for larger files
    print(f"Waiting for operation {operation_name} to complete...")
    result = operation.result(timeout=300)

    # NOTE: Can also use callbacks for asynchronous processing
    #
    # def my_callback(future):
    #   result = future.result()
    #
    # operation.add_done_callback(my_callback)

    print("Document processing complete.")

    # Get the Document Objects from the Output Bucket
    document_list = get_documents_from_gcs(
        gcs_output_uri=gcs_output_uri, operation_name=operation_name
    )

    for document in document_list:
        print(document.text)

调用 main 函数,您应该会看到控制台中已提取并输出的完整新文本。

main()

这可能需要一些时间才能完成,因为文件比上一个示例大得多。(糟糕!)

但是,对于异步 API,您会收到一个操作 ID,该 ID 可用于在任务完成后从 GCS 中获取输出。

This is a reproduction of a library book that was digitized
by Google as part of an ongoing effort to preserve the
information in books and make it universally accessible.
TM
Google books
https://books.google.com

.....

He nodded and went
out ... and in a moment
I heard Winnie-the-Pooh
-bump, bump, bump-go-ing up the stairs behind
him.
Digitized by
Google

10. 恭喜

您已成功使用 Document AI 使用同步和异步 API 从小说中提取文本。

我们建议您尝试使用其他文档,并探索该平台上的其他处理方

清理

为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请执行以下操作:

  • 在 Cloud Console 中,转到管理资源页面。
  • 在项目列表中,选择您的项目,然后点击“删除”。
  • 在对话框中输入项目 ID,然后点击“关停”以删除项目。

了解详情

许可

此作品已获得 Creative Commons Attribution 2.0 通用许可授权。